How to make webDriver wait for page to load (Selenium C # project)

I started a Selenium project in C #. Trying to wait for the page to finish loading, and only then go to the next step.

My code is as follows:

loginPage.GoToLoginPage(); loginPage.LoginAs(TestCase.Username, TestCase.Password); loginPage.SelectRole(TestCase.Orgunit); loginPage.AcceptRole(); 

inside loginPage.SelectRole (TestCase.Orgunit):

  RoleHierachyLabel = CommonsBasePage.Driver.FindElement(By.XPath("//span[contains(text(), " + role + ")]")); RoleHierachyLabel.Click(); RoleLoginButton.Click(); 

I am looking for the RoleHierachyLabel element. I am trying to use several ways to wait for a page to load or to search for an element property that allows us to use some timeout:

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

How would you deal with this obstacle?

+14
source share
6 answers

I was looking for alternatives, and I decided to use the following versions. Everyone uses an explicit wait with a given timeout and is based on the properties of the element in the first case and on the durability of the element in the second case.

The first choice will check the properties of the element until a timeout is reached. I came to the following properties, confirming that it is available on the page:

Existence . Waiting to verify that the element is present in the DOM of the page. This does not necessarily mean that the item is visible.

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

Visibility Waiting to verify that the element is present in the DOM of the page and visible. Visibility means that the item is not only displayed, but also has a height and width greater than 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 . The pending item check is visible and turned on so that you can click it.

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

The second choice applies when a trigger object, such as a menu item, is no longer attached to the DOM after it is clicked. This usually happens when a click action on an element causes a redirect to another page. In this case, it is useful to check StalenessOf (element) , where the element is the element that was clicked to cause a redirect to a new page.

 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; } } 
+20
source

driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(5);

Also see this answer

+4
source

I usually use an explicit expectation of this and wait for the elements to be visible, and then continue to the next step. It should look like this:

 WebDriverWait waitForElement = new WebDriverWait(driver, TimeSpan.FromSeconds(5)); waitForElement.Until(ExpectedConditions.ElementIsVisible(By.Id("yourIDHere"))); 

Read more about explicit waiting here: Explicitly waiting for Selenium C # and here WebDriver Explicit is waiting

+1
source

I did this to solve this problem. This is a combination of timers and loops that look for a specific item until it expires after a certain number of milliseconds.

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

I also made one for the item included

 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; } 
+1
source

As stated in " Waiting for a page to load in Selenium" :

In general, in Selenium 2.0, the web driver should return control to the calling code only after it determines that the page is loaded . If this is not the case, you can call waitforelemement , which cyclically findelement calls findelement until findelement until it is found or findelement does not wait (you can set the wait time).

0
source

Because of its simplicity, I like this solution. He also has the advantage of avoiding excessive expectations and eliminating the need for an assumption that there might be an upper limit to expectations:

  public bool WaitToLoad(By by) { int i = 0; while (i < 600) { i++; Thread.Sleep(100); // sleep 100 ms try { driver.FindElement(by); break; } catch { } } if (i == 600) return false; // page load failed in 1 min else return true; } 

Which can be changed to also enable a "timer" if monitoring page load delay is required:

  public int WaitToLoad(By by) { int i = 0; while (i < 600) { i++; Thread.Sleep(100); // sleep 100 ms try { driver.FindElement(by); break; } catch { } } return i; // page load latency in 1/10 secs } 
0
source

Source: https://habr.com/ru/post/1266296/


All Articles