问题
I'm trying to wait for Selenium to switch changing frames before waiting on another element. I.e.
var wait = new WebDriverWait(driver, 15);
wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.Id("frameA"));
var wait2 = new WebDriverWait(driver, 15);
// wait for element within frameA to exist
wait2.Until(ExpectedConditions.ElementExists(By.Id("elementA")));
If I toss in a simple Thread.Sleep(1000);
before the second wait it functions fine, but without that I get the following error:
'unknown error: unhandled inspector error: {"code":-32000,"message":"Cannot find context with specified id"}
enter code here
Is there a better way to wait for the frame context to switch finishing before waiting for an element within that frame to be populated?
回答1:
There are a couple of things you need to consider :
The line of code to switch to the frame looks perfect which doesn't throws any error :
var wait = new WebDriverWait(driver, 15);
wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.Id("frameA"));
In the next line you have tried the ExpectedConditions method ElementExists. As per the API Docs ElementExists Method is defined as :
An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.
Selenium can't interact with elements until the element is visible. Hence you need to use the method ElementIsVisible as follows :
var wait2 = new WebDriverWait(driver, 15);
wait2.Until(ExpectedConditions.ElementIsVisible(By.Id("elementA")));
Here you can find a detailed discussion on Ways to deal with #document under iframe
回答2:
You can wait for the frame itself to be clickable:
wait2.Until(ExpectedConditions.ElementExists(By.Id("YOURFRAMEID")));
回答3:
This is how you can do it:
var wait = new WebDriverWait(new SystemClock(), driver, TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(sleepInterval));
wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt("yourFrameName");
driver.SwitchTo().Frame("yourFrameName");
回答4:
I am not sure which language you're working on. But in C#, you would need to SwitchTo default content first and then switch to the Iframe you're dealing with which is frameA. So here is my suggested code to try:
driver.SwitchTo().DefaultContent();
driver.SwitchTo().Frame(frameA);
Update: Implement a method that waits for element explicitly:
public void WaitForElementExplicitly(int WaitInMilliSeconds = 3000, By Selector = null)
{
WebDriverWait wait = new WebDriverWait(CommonTestObjects.IWebDriver, TimeSpan.FromSeconds(WaitInMilliSeconds / 1000));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
return d.FindElement(Selector);
});
}
And then call the method to wait for your element
WaitForElementExplicitly(Selector: By.Id("elementA"));
来源:https://stackoverflow.com/questions/49677267/how-to-wait-for-a-frame-to-load-before-locating-an-element