Как заставить webDriver ждать загрузки страницы (проект C# Selenium)
Я начал проект Селена в C#. Попытка дождаться завершения загрузки страницы и только после этого перейти к следующему действию.
мой код выглядит так:
loginPage.GoToLoginPage();
loginPage.LoginAs(TestCase.Username, TestCase.Password);
loginPage.SelectRole(TestCase.Orgunit);
loginPage.AcceptRole();
внутри loginPage.SelectRole (TestCase.Orgunit):
RoleHierachyLabel = CommonsBasePage.Driver.FindElement(By.XPath("//span[contains(text(), " + role + ")]"));
RoleHierachyLabel.Click();
RoleLoginButton.Click();
Я ищу элемент RoleHierachyLabel. Я пытался использовать несколько способов ожидания загрузки страницы или поиска свойства элемента, позволяющего некоторое время ожидания:
1. _browserInstance.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5));
2. public static bool WaitUntilElementIsPresent(RemoteWebDriver driver, By by, int timeout = 5)
{
for (var i = 0; i < timeout; i++)
{
if (driver.ElementExists(by)) return true;
}
return false;
}
как вы бы справились с этим препятствием?
4 ответов
Я искал альтернативы и я остановился на следующих вариантах. Все они используют явное ожидание с определенным таймаутом и основаны на свойствах элемента в первом случае и на стойкости элемента во втором случае.
выбор будет проверять свойства элемента до тех пор, пока не будет достигнут тайм-аут. Я прибыл к следующим свойствам, которые подтверждают, что он доступен на странице:
существование - ожидание для проверка наличия элемента в DOM страницы. Это не обязательно означает, что элемент виден.
//this will not wait for page to load
Assert.True(Driver.FindElement(By elementLocator).Enabled)
//this will search for the element until a timeout is reached
public static IWebElement WaitUntilElementExists(By elementLocator, int timeout = 10)
{
try
{
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(timeout));
return wait.Until(ExpectedConditions.ElementExists(elementLocator));
}
catch (NoSuchElementException)
{
Console.WriteLine("Element with locator: '" + elementLocator + "' was not found in current context page.");
throw;
}
}
видимость - ожидание для проверки того, что элемент присутствует в DOM страницы и видны. Видимость означает, что элемент не только отображается, но также имеет высоту и ширину больше 0.
//this will not wait for page to load
Assert.True(Driver.FindElement(By elementLocator).Displayed)
//this will search for the element until a timeout is reached
public static IWebElement WaitUntilElementVisible(By elementLocator, int timeout = 10)
{
try
{
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(timeout));
return wait.Until(ExpectedConditions.ElementIsVisible(elementLocator));
}
catch (NoSuchElementException)
{
Console.WriteLine("Element with locator: '" + elementLocator + "' was not found.");
throw;
}
}
Clickable - ожидание для проверки элемента видно и включено такое что вы можете щелкнуть по нему.
//this will not wait for page to load
//both properties need to be true in order for element to be clickable
Assert.True(Driver.FindElement(By elementLocator).Enabled)
Assert.True(Driver.FindElement(By elementLocator).Displayed)
//this will search for the element until a timeout is reached
public static IWebElement WaitUntilElementClickable(By elementLocator, int timeout = 10)
{
try
{
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(timeout));
return wait.Until(ExpectedConditions.ElementToBeClickable(elementLocator));
}
catch (NoSuchElementException)
{
Console.WriteLine("Element with locator: '" + elementLocator + "' was not found in current context page.");
throw;
}
}
второй вариант применяется, когда объект триггера, например элемент меню, больше не прикреплен к DOM после его нажатия. Обычно это происходит, когда действие щелчка по элементу вызывает перенаправление на другую страницу. В этом случае полезно проверьте StalenessOf (элемент) где элемент-элемент, который был нажат для запуска перенаправления на новую страницу.
public static void ClickAndWaitForPageToLoad(By elementLocator, int timeout = 10)
{
try
{
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(timeout));
var element = Driver.FindElement(elementLocator);
element.Click();
wait.Until(ExpectedConditions.StalenessOf(element));
}
catch (NoSuchElementException)
{
Console.WriteLine("Element with locator: '" + elementLocator + "' was not found in current context page.");
throw;
}
}
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(5);
Также см. ответ
обычно я использую явное ожидание этого и жду, пока элементы не будут видны, а затем перейдем к следующему действию. Это должно выглядеть так:
WebDriverWait waitForElement = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
waitForElement.Until(ExpectedConditions.ElementIsVisible(By.Id("yourIDHere")));
подробнее о явных ожиданиях здесь:явное ожидание Selenium c# и здесь WebDriver явно ждет
Я сделал это, чтобы решить эту проблему. Это комбинация таймеров и циклов, которые ищут определенный элемент, пока он не выйдет через определенное количество миллисекунд.
private IWebElement FindElementById(string id, int timeout = 1000)
{
IWebElement element = null;
var s = new Stopwatch();
s.Start();
while (s.Elapsed < TimeSpan.FromMilliseconds(timeout))
{
try
{
element = _driver.FindElementById(id);
break;
}
catch (NoSuchElementException)
{
}
}
s.Stop();
return element;
}
Я также сделал один для элемента включен
private IWebElement ElementEnabled(IWebElement element, int timeout = 1000)
{
var s = new Stopwatch();
s.Start();
while (s.Elapsed < TimeSpan.FromMilliseconds(timeout))
{
if (element.Enabled)
{
return element;
}
}
s.Stop();
return null;
}