Как заставить 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;
}