1

I am writing tests on a third party system, that utilizes iframes. I have been going through my code and eliminating places where I have been using waits/sleep for 2-5 seconds, and looking more for elements to show.

But, there is one frame, where I have a wait for 90 seconds, because it can take a long time to process, and can take 2 seconds to process in our test system. So, the only way I would know is that the frame is closed and returned back to the main window. I looked to see if I can find out if I am on a frame or a page from the Driver.Instance.... but I can't see anything in particular that could help. What should I look for to see if I am still on a frame, or control has returned to the calling web page?

4 Answers 4

1

I answered my own question, and went through the wait helper, one by one, and found this one... that I didn't think about.

SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.ClassName("collapse"));

Waited for the button to be clickable before clicking on it.

1
  • Greg, your solution might have helped in this particular case, but it is not really the correct way to handle it.
    – hfontanez
    Feb 18, 2021 at 19:14
1

I have had similar issues....

The best way to wait for some particular state of a WebElement is to use explicit waits. This is when you command the web driver to wait until some condition is met. To do this, you need to select one or more conditions provided by the ExpectedConditions class. Yes, I said one or more... Also, some people don't know that here is a way to negate these expected conditions. For example, let's assume I need to tell the web driver to wait until a button is clickable

WebDriver driver = ....; // obtain your web driver
WebDriverWait wait = new WebDriverWait(driver, 5); // wait max. of 5 seconds for condition to be reached
WebElement button = wait.until(ExpectedConditions.ExpectedConditions.elementToBeClickable(LOCATOR)); // where LOCATOR is the strategy you want to use to locate a web element

The result of the until call will return something depending on the expected condition passed. Some conditions return a boolean, other return a single element, while others return a list of web elements. In this case, the expected condition is to return a single element. THEREFORE, you need to make absolutely sure that your LOCATOR locates a single component. Otherwise, it will return the first one it finds and that may or may not be the one you need.

As I mentioned before, the condition can be negated. Using the same example, how do you wait until the button is not clickable?

wait.until(ExpectedConditions.not(ExpectedConditions.elementToBeClickable(LOCATOR)));

Notice I placed the previous ExpectedConditions inside a not. This is how you negate the expected condition.

So, going back to the OP's question, how to do wait for an "iframe" to be closed? This depends on your specific situation. In my situation, I kicked off a process where an iframe is opened to upload some pictures and then a button is clicked to close it. Often times is that the next instruction in your Selenium test class or your Gherkins script is executed while the frame is in the process of closing. This results in an unstable condition when sometimes the next instruction succeeds and sometimes it fails because the time it takes the iframe to close is affected by other things (i.e. your server or test box is "running slow"). For those cases, it is a good practice to tell the driver to WAIT UNTIL the iframe is gone. What I have done is to write a condition that occurs after the clicking of the "close iframe" button.

button.click(); // my button click
WebDriverWait wait = new WebDriverWait(driver, 5);
boolean iframeGone = wait.until(ExpectedConditions.not(
    ExpectedConditions.presenceOfElementLocated(LOCATOR)));

The not condition returns a boolean based on the expected condition it evaluates. In my case, the iframe is totally removed from the DOM when the "close iframe" button is clicked. This is different that checking for "visibility" because an invisible component can still be active. In the above snippet, if the wait conditions times out, it will throw a Selenium TimeoutException which is a form of RuntimeException so do not expect to be forced to handle it. That said, you should ABSOLUTELY handle it, but also you need to include a finally block to switch back to the parent frame. So, the correct structure for the code I showed you is

try {
    // Execute the equivalent of the above code that fits your situation
} catch (TimeoutException e) {
    // handle the exception (most likely mean your test failed)
} finally {
    // switch to parent frame
    driver.switchTo().parentFrame();
}

If you are already in the parent frame, there is not side effect of invoking this method. IF you are in a frame other than the parent frame, the web driver is not smart enough to acknowledge that your subsequent tests require it to be in the parent frame. You need to be explicit by informing the web driver which frame contains the web elements it needs to interact to in future test steps.

0

Although, your haven't mentioned the language. Refer below code (Java) to dynamically wait for the iFrame and switch into it

WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frameLocator));

It will wait until your frame gets in into web page and then switch in.

There you can write the code to perform the action on iframe element and then switch back to default window

driver.switchTo().defaultContent();
2
  • I understand how to close a frame...I am looking on what to look for to know when it closes...if I just close this, and return back to the defaultContent, and it takes more than a second to process, I get this. Element <i class="collapse-icon fa fa-fw fa-refresh"></i> is not clickable at point (1766, 542). Other element would receive the click: <div class="ui-widget-overlay ui-front" style="z-index: 100;"></div>, because the frame is still open, processing. I was hoping for some wait helper for this.
    – Greg P
    Feb 5, 2019 at 12:48
  • This doesn't work..... always. If you have this in your scripts and you don't run into cases where the next web element interaction fails due to interference from the iframe, you are just lucky. Physically closing the iframe doesn't necessarily mean that it closes instantly. And because it doesn't, the next instruction could fail, UNLESS you tell the web driver "wait until the frame is closed" which is what the OP asked.
    – hfontanez
    Feb 19, 2021 at 14:03
0

In Webdriver, you should use driver.switchTo().defaultContent(); to get out of a frame. You need to get out of all the frames first, then switch into the outer frame again.

// between step 4 and step 5
// remove selenium.selectFrame("relative=up");
driver.switchTo().defaultContent(); // you are now outside both frames
driver.switchTo().frame("cq-cf-frame");
// now continue step 6
driver.findElement(By.xpath("//button[text()='OK']")).click();
2
  • Let me know it helps or not.
    – Meet
    Feb 12, 2020 at 12:21
  • The OP didn't ask "how to close an iframe". The question is "how do you know when the frame is fully closed". Do you understand the difference?
    – hfontanez
    Feb 19, 2021 at 14:04

Your Answer

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

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