7

I want to automate a script which verify certain contents in the webpage.

The login page redirected several times before landing on an application page and these redirects were causing issues occasionally. The issue was definately related to timing. So how can webdriver wait until the final page is fully loaded or settled ?

A typical solution is to wait for an element on the target page to become available. Unfortunately, we use 100+ unique urls therefore there is no predictable landing page.

So how can an ExpectedCondition be implemented, that waits for the application to stabilize with respect to redirects ?

The main agenda is, I have a set of URL's and i wanted to verify that all these URL's are valid by checking the content in it. All these are direct URL's of learning contents to which my organization has partnered eg Lynda, skillsoft,etc. So when we launch these URL through automated scrip first it will ask authentication(My organizational credential) and after that it will redirect to corresponding sites. During these redirect, in certain cases there is multiple redirection happening and finally the content page is loaded. This is the scenario. My script fails mainly due to the wait i guess

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
Avinash
  • 71
  • 1
  • 3
  • After login you will get user action right.So you can write a while loop in which you can search for username.`while(username.isDisplayed(){Thread.sleep(5000);}` – Sudha Velan Nov 15 '17 at 07:24
  • Some url has login page where some have direct url. Those page that do not have login. How will we wait ? – Avinash Nov 15 '17 at 07:35
  • Can you elaborate a bit how `these redirects were causing issues `? – undetected Selenium Nov 15 '17 at 08:03
  • You do `wait for an element` on a `predictable landing page` what else can be your validation points? Can you update the questions with your exact Manual Steps which you are trying to `Automate`? – undetected Selenium Nov 15 '17 at 08:06
  • The main agenda is, I have a set of URL's and i wanted to verify that all these URL's are valid by checking the content in it. All these are direct URL's of learning contents to which my organization has partnered eg Lynda, skillsoft,etc. So when we launch these URL through automated scrip first it will ask authentication(My organizational credential) and after that it will redirect to correspond sites. During these redirect, in certain cases there is multiple redirection happening and finally the content page is loaded. This is the scenario. My script fails mainly due to the wait i guess – Avinash Nov 15 '17 at 09:01

2 Answers2

9

As you mentioned multiple redirection happening and finally the content page is loaded and the script fails mainly due to the wait is pretty much possible. In these cases we need to induce ExplicitWait i.e. WebDriverWait with expected_conditions clause set to either of the following :


Java :

  1. urlToBe: An expectation for checking the current url is an exact match.

    new WebDriverWait(driver, 10).until(ExpectedConditions.urlToBe("https://www.facebook.com/"));
    
  2. urlContains: An expectation for checking that the current url contains a case-sensitive substring.

    new WebDriverWait(driver, 10).until(ExpectedConditions.urlContains("facebook"));
    
  3. urlMatches: An expectation for checking the current url pattern is the expected pattern which must be an exact match.

    new WebDriverWait(driver, 10).until(ExpectedConditions.urlMatches("my_regex"));
    

Python :

  1. url_to_be: An expectation for the URL of the current page to be a specific url.

    WebDriverWait(driver, 10).until(EC.url_to_be("https://www.google.co.in/"))
    
  2. url_matches: An expectation for the URL to match a specific regular expression.

    WebDriverWait(driver, 10).until(EC.url_matches("my_regex"))
    
  3. url_contains: An expectation for the URL of the current page to contain specific text.

    WebDriverWait(driver, 10).until(EC.url_contains("google"))
    
  4. url_changes: An expectation for checking the current url which must not be an exact match.

    WebDriverWait(driver, 10).until(EC.url_changes("https://www.google.co.in/"))
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
0

I solved this with a custom function + Fluent Wait. The custom function checks origins while counting number of times the same origin is seen. It also ensures that there was at least one change (i.e. we are not stuck on the first origin).

Here is the TypeScript version:

function getOrigin(url: string): string {
  return new URL(url).origin;
}

async function waitForRedirectToStabilize(
  driver: WebDriver,
  minStableChecks: number,
  maxWaitMs: number,
  checkIntervalMs: number,
) {
  let matchCounter = 0;
  let previousOrigin: string | undefined = undefined;
  const startingOrigin = getOrigin(await driver.getCurrentUrl());

  const untilRedirectStabilizes = async (waitWebDriver: WebDriver) => {
    const currentOrigin = getOrigin(await waitWebDriver.getCurrentUrl());
    if (previousOrigin != currentOrigin) {
      previousOrigin = currentOrigin;
      matchCounter = 0;
    } else {
      matchCounter++;
    }

    const isRedirectSettled =
      matchCounter > minStableChecks && currentOrigin != startingOrigin;
    return isRedirectSettled;
  };


  await driver.wait(
    untilRedirectStabilizes,
    maxWaitMs,
    `Redirects did not stabilize. Matches: ${matchCounter}, last seen origin: ${previousOrigin}`,
    checkIntervalMs
  );
}

async function main() {
  const chromeOptions = new chrome.Options();
  chromeOptions.addArguments("--headless");

  const driver = await new Builder()
    .forBrowser(Browser.CHROME)
    .setChromeOptions(chromeOptions)
    .build();
  await driver.get(<some url that redirects>);

  try {
    await waitForRedirectToStabilize(driver, 4, 10000, 500);
  } catch (e) {
    console.log(e);
  }
  console.log(await driver.getCurrentUrl());
}

main();

There is room for false positives if the redirect time is slow. Use the check interval and number of checks to tweak to your use case.

tday03
  • 534
  • 4
  • 14