Я использую Selenium Webdriver с С#, и мне интересно, есть ли способ переопределить метод FindElement? То, что я хотел бы сделать - если возможно, - добавить дополнительный параметр и код в метод, который заставит его дождаться, пока элемент станет видимым, прежде чем продолжить. Например, это было бы примерно так:
Driver.FindElement(By.Id("orion.dialog.box.ok"), 60).Click();
Это будет ждать до 60 секунд, пока элемент появится и будет доступен для клика.
Есть идеи, как это сделать? Спасибо, Джон
Я кодирую Selenium для 6+ месяцев, и у меня была такая же проблема, как у вас. Я создал этот метод расширения, и он работает для меня каждый раз.
Что делает код: в течение 20 секунд он проверяет каждые 500 мс, присутствует ли элемент на странице. Если через 20 секунд он не будет найден, это вызовет исключение. Это поможет вам сделать динамическое ожидание.
public static class SeleniumExtensionMethods {
public static WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
public static void SafeClick(this IWebElement webElement) {
try {
wait.Until(ExpectedConditions.ElementToBeClickable(webElement)).Click();
} catch (TargetInvocationException ex) {
Console.WriteLine(ex.InnerException);
}
}
и затем используйте его следующим образом:
IWebElement x = driver.FindElement(By.Id("username"));
x.SafeClick();
Я бы предложил вам добавить его как метод расширения. Псевдокод:
public static IWebElement WaitForAndFindElement(this IWebDriver driver, By by)
{
// do a wait
// something like...
WebDriverWait wait = new WebDriverWait(TimeSpan.FromSeconds(60)); // hard code it here if you want to avoid each calling method passing in a value
return wait.Until(webDriver =>
{
if (webDriver.FindElement(by).Displayed)
{
return webDriver.FindElement(by);
}
return null; // returning null with force the wait class to iterate around again.
});
}
Просто чтобы заявить, неявное ожидание станет частью вашего решения. Это приведет к тому, что Selenium будет ждать до 60 секунд, чтобы элемент присутствовал в DOM, но быть видимым - это нечто совершенно другое.
.Displayed
будет обрабатывать это, и он должен обрабатываться в WebDriverWait
.
Вы можете использовать ImplicitWait для этого. Вы можете создать новую пользовательскую функцию, чтобы принять объект By и время ожидания и вернуть функцию IWebElement, как показано ниже:
IWebElement elem = MyOwnGetElement(By.id("test"),60);
Вышеупомянутая функция может иметь следующий код, где time_out_sec - это параметр функции.
WebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(time_out_sec));
driver.Url = "http://somedomain/url_that_delays_loading";
IWebElement myDynamicElement = driver.FindElement(By.Id("someDynamicElement"));