Как ждать загрузки кадра, прежде чем найти элемент?

Я пытаюсь дождаться, пока Selenium переключит смену кадров, прежде чем ждать другого элемента. Т.е.

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")));

Если я бросаю в простом Thread.Sleep(1000); перед вторым ожиданием все работает нормально, но без этого я получаю следующую ошибку:

'unknown error: unhandled inspector error: {"code":-32000,"message":"Cannot find context with specified id"}
    enter code here

Есть ли лучший способ дождаться, пока контекст фрейма переключится на окончание, прежде чем ждать заполнения элемента в этом фрейме?

4 ответа

Решение

Есть несколько вещей, которые вы должны рассмотреть:

Строка кода для переключения на фрейм выглядит идеально, что не выдает никакой ошибки:

var wait = new WebDriverWait(driver, 15);
wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.Id("frameA"));

В следующей строке вы попробовали метод ExpectConditions ElementExists. В соответствии с документами API ElementExists Метод определяется как:

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.

Селен не может взаимодействовать с элементами, пока элемент не виден. Следовательно, вам нужно использовать метод ElementIsVisible следующее:

var wait2 = new WebDriverWait(driver, 15);
wait2.Until(ExpectedConditions.ElementIsVisible(By.Id("elementA")));

Вы можете подождать, пока сама рамка будет кликабельной:

wait2.Until(ExpectedConditions.ElementExists(By.Id("YOURFRAMEID")));

Вот как вы можете это сделать:

var wait = new WebDriverWait(new SystemClock(), driver, TimeSpan.FromSeconds(timeout), TimeSpan.FromSeconds(sleepInterval)); 
wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt("yourFrameName"); 
driver.SwitchTo().Frame("yourFrameName");

Я не уверен, на каком языке вы работаете. Но в C# вам нужно сначала переключиться на содержимое по умолчанию, а затем переключиться на Iframe, с которым вы работаете, это frameA. Вот мой предложенный код:

driver.SwitchTo().DefaultContent();
driver.SwitchTo().Frame(frameA);

Обновление: Реализуйте метод, который явно ожидает элемент:

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);
  });
}

А затем вызовите метод для ожидания вашего элемента

WaitForElementExplicitly(Selector: By.Id("elementA"));
Другие вопросы по тегам