简体   繁体   中英

Selenium and Appium and WaitForSomeElementToBeVisible

I have this method implemented some time ago. I use it pretty extensively in my web automation.

The gist is to wait for one of several elements to be visible.

    public void waitForSomeElementToBeVisible(int timeout, final By... locators) throws Exception, TimeoutException {
       boolean found = false;
    
       try {
          driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
          WebDriverWait wait = new WebDriverWait(driver, timeout);
    
          ExpectedCondition<?>[] conditionsToEvaluate = new ExpectedCondition[locators.length];
          for (int i = 0; i < locators.length; i++) {
             conditionsToEvaluate[i] = ExpectedConditions.visibilityOfElementLocated(locators[i]);
          }
          found = wait.until(ExpectedConditions.or(conditionsToEvaluate));
        } catch (TimeoutException e)  {
                throw e;
        } catch (Exception e)  {
                throw e;
        } finally {
          driver.manage().timeouts().implicitlyWait(<default>, TimeUnit.SECONDS);
        }
        
       if (!found) throw new Exception("Nothing found");
    }

Now I'm trying to use this method with a mobile browser. Specifically, iOS Safari via Appium. It works on iOS occasionally but usually fails and in the Appium log I see when executing the line:

found = wait.until(ExpectedConditions.or(conditionsToEvaluate));

(It does work consistently with Android+Appium).

[WD Proxy] Got response with status 404: {"value":{"error":"no such alert","message":"An attempt was made to operate on a modal dialog when one was not open","traceback":""},"sessionId":"03E95205-9E98-4DB4-BB61-0F125C2C5B3E"} [debug] [W3C] Matched W3C error code 'no such alert' to NoSuchAlertError

There is, of course, no alert AND one of the elements does exist.

What's going wrong here?
Is there a better way to wait for one of several elements to be visible?

Please try this java method:

    public static boolean waitForElement(WebElement element) throws IOException {
    log.info("Waiting for an element in the page...");
    boolean isElementPresent = true;
    try {
        WebDriverWait wait = new WebDriverWait(driver, 30);
        wait.until(ExpectedConditions.visibilityOf(element));
        log.info("Element is visible");
        return isElementPresent;
    } catch (Exception e) {
        log.info("waitForElement method failed! " + e.getMessage());
        return !isElementPresent;
    }
}

or this method:

    public static WebElement fluentWait(final WebElement webElement, int timeinsec) {
    log.info("waiting ..."+ timeinsec +" seconds");
    FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
            .withTimeout(timeinsec, TimeUnit.SECONDS).pollingEvery(timeinsec, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class);
    WebElement element = wait.until(new Function<WebDriver, WebElement>() {
        public WebElement apply(WebDriver driver) {
            return webElement;
        }
    });
    return element;
}

FYI: Both of these method are present under the below maven Dependency I created a while ago. It has a lot of re-usable method that you can use:

    <dependency>
     <groupId>com.github.mbn217</groupId>
     <artifactId>MyUtilities</artifactId>
     <version>1.0.2</version>
    </dependency>

To use it you just need to call the class name and the method. No need to create an object from the class example:

SeleniumUtils.waitForElement(pass your element here)

@mbn217 I have been using Thread.sleep in my appium script and it is messing up my script.

Is there a way to implement a wait in my BaseFile and extends to all class so that I wont have to be writing explicit wait on every line of my script. I tried to implement your first code block in my BaseFile but I am getting error that log cannot be resolved.

Also I attached a section of my script and you will see how messed up it is with Thread.sleep.public class AddItemToCartTest extends ScriptDependency {

@Test(description =" This test checks if Items are succesfully added to Cart")

public void AddItemToCart() throws MalformedURLException, InterruptedException {
    
    service = startServer();

    IOSDriver<IOSElement> driver = DesiredCapabilities();

    OnboardingPage OnboardingPage = new OnboardingPage(driver);

    OnboardingPage.startNow.click();
    Thread.sleep(2000);

    OnboardingPage.allow.click();

    OnboardingPage.zipCodeField.sendKeys("00000");
    Thread.sleep(2000);

    OnboardingPage.confirmZipCod.click();
    Thread.sleep(2000);

    HomePage HomePage = new HomePage(driver);

    HomePage.medicationsCategory.click();
    Thread.sleep(2000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM