4

If driver switched to iframe, selenium would take a screenshot of iframe content only (EDIT: this is because of bug in gecko driver). I need to mask an element from the screenshot, but if I find an area by

element.getLocation()

method - masked area is a bit off.

Does anyone know if it's possible to get the location of an element relative to iframe and not the whole screen?

Appreciate your help!

2 Answers 2

1

If driver switched to iframe, selenium would take screenshot of iframe content only

I tried to reproduce your issue and looks like you are not completely right. In my case when I took the screen-shot it contained the entire page despite I switched to iFrame before.

if it's possible to get location of an element relative to iframe and not the whole screen?

getLocation method returns you the position relative to iFrame. I.e. exactly what you need. So in order to get the position of an element in the entire view you should take the position of iframe in the parent view and add the position of the elemetn in iframe. Here is the proof-of-concept:

Test site: https://jsfiddle.net/o1kqLahu/5/

Code:

public static void main(String[] args) throws IOException {

    System.setProperty("webdriver.chrome.driver", "C:\\Temp\\chromedriver.exe");
    WebDriver chromeDriver = new ChromeDriver();
    chromeDriver.get("https://jsfiddle.net/o1kqLahu/5/");
    Point locationOfIFrame = chromeDriver.findElement(By.name("result")).getLocation();
    System.out.println("X: " + locationOfIFrame.x + "; Y: " + locationOfIFrame.y);
    chromeDriver.switchTo().frame("result");
    Point locationInIFrame = chromeDriver.findElement(By.id("secret-input")).getLocation();
    File scrFile = ((TakesScreenshot)chromeDriver).getScreenshotAs(OutputType.FILE);
    FileUtils.copyFile(scrFile, new File("c:\\Temp\\screenshot2.png"));
    System.out.println("Location of element in iframe: X: "
            + locationInIFrame.x + "; Y: " + locationInIFrame.y);
    System.out.println("Location of element of the screen: X: " +
            (locationInIFrame.x + locationOfIFrame.x) +
            "; Y: " +
            (locationInIFrame.y + locationOfIFrame.y));
    chromeDriver.close();

}

Output:

X: 570; Y: 474
Location of element in iframe: X: 8; Y: 8
Location of element of the screen: X: 578; Y: 482

Some screens saved:

enter image description here

enter image description here

UPD:

In case of the defect in geko-driver (as per the update of your question) I would recommend the following workaround:

  1. Take iFrame position before switching to that iFrame
  2. Take position of the required element (related to the entire screen)
  3. Take screenshot.

Now we have the picture of the iFrame content and we can calculate the position of the element inside the iFrame using the following formula:

PositionOfElementInsideIFrame = PositionOfTheElementInsideEntireScreen - PositionOfIFrameInsideEntireScreen
4
  • Hey, would you try with firefox? I just tried it with chrome - turns out that indeed chrome driver takes screenshot of whole page.
    – vilkg
    Mar 20, 2018 at 11:45
  • You can calculate ([position of the element] -[position of the frame]) so that you have position of the element on the screenshot where the only frame content is taken.
    – Alexey R.
    Mar 20, 2018 at 13:35
  • But then that will still not work with gecko driver, since screenshot only contains the iframe and location of the element is also relative to the frame. I will accept your answer, since it helped to realize that solution must be driver specific, even though it didn't solve the problem and area is still incorrectly masked out.
    – vilkg
    Mar 20, 2018 at 16:06
  • It still not very clear what exactly you need to capture: if the iframe then the solution should work, if the entire screen, then switch to the default frame before making a screenshot. You also would have all the coordinates to evaluate the proper position of a mask.
    – Alexey R.
    Mar 20, 2018 at 16:10
0

To get the element's location relative to an iframe in Selenium:

Switch to the iframe. Use element.getLocation() to get the element's position. Capture the screenshot and mask the element as needed. Optionally, switch back to the main frame if necessary.

1
  • Can you add some code to illustrate this?
    – Lee Jensen
    Oct 8 at 20:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.