Nathan Hyland
Nathan Hyland

Reputation: 860

Selenium Events and Waiting

I'm working with Selenium on automating some testing for our company website but running in to issues.

TestItemFromSearch: (driver, part, qty) => {
    Search.SearchItem(driver, part);
    driver.findElement(By.id('enterQty')).findElement(By.tagName('input')).sendKeys(qty); 
    driver.findElement(By.linkText('Personalize')).click();
    //This directs to a new page.
    driver.wait(() => {
    }, 1000).then(() => {
        }, //TODO: This sucks. Fix it.
        Login.Login(driver, Logins.username, Logins.password));
    driver.findElement(By.className('selectDesignButton')).click();
}

Some times, when Selenium is directed to a new page, I ave to use the wait. No matter what condition I put in, it doesn't really find that condition - it fails. I have to hijack the Reject method to put in a desired action (like Login.Login).

I may have to do this again in the same test since it's going to run through multiple pages.. that's going to result in ugly, ugly, unreadable code.

How can I get Selenium to PROPERLY wait? If I do the following:

driver.wait(()=>{},1000)

it just sits forever. If I put in a return statement, it instantly fails and doesn't even wait the second.

Upvotes: 1

Views: 787

Answers (3)

Gabba
Gabba

Reputation: 11

maybe this helps it is a "async function () "

var nameButton = By.linkText('Personalize')
await driver.wait(function () {
    return until.elementIsVisible(nameButton);
}, 20000).then(() => {console.log("element visible")})
button =  await button.findElement(nameButton).then(()=>{ console.log("found element")})
await button.click().then(()=>{ console.log("I clicked the button")})

Upvotes: 0

marchocolate
marchocolate

Reputation: 53

You need to use an explicit (rather than implicit) wait. There are multiple ways to do this:

WebDriverWait wait = new WebDriverWait(driver, timeOut);
wait.until(ExpectedConditions.elementToBeClickable(locator));

Or you can use a different form of explicit wait, which is a fluentWait:

public WebElement fluentWait(final By locator) {
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
        .withTimeout(30, TimeUnit.SECONDS)
        .pollingEvery(5, TimeUnit.SECONDS)
        .ignoring(NoSuchElementException.class);

WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
    public WebElement apply(WebDriver driver) {
        return driver.findElement(locator);
    }
}); return  foo; };;

Either will work, I personally prefer a fluentWait because you can specify:

  1. Frequency with which FluentWait has to check the conditions defined.
  2. Ignore specific types of exception waiting such as NoSuchElementExceptions while searching for an element on the page.
  3. Maximum amount of time to wait for a condition

Try this:

driver.wait(function() {
    return driver.findElement(locator).isDisplayed();
}, timeout);

Upvotes: 1

CaptainAdams
CaptainAdams

Reputation: 81

You should be using the selenium driver's WaitForElementPresent or WaitForElementVisible functionalities prior to interacting with elements on the page. The selenium driver will watch the DOM and verify the presence or rendering, respectively, of each element. After those checks pass first, it should be safe to interact with the page for further testing.

Upvotes: 0

Related Questions