0

I've been working with ExpectedConditions.or . It is quite useful to find if one or the other element is present, for example. What I would like to do now is build a more flexible method using variable arguments.

See what I did below. It works...such as it is, but I'd like a more elegant solution that would actually work with any number of elements.

public void waitForSomeElementToBeVisible(int timeout, final By... locators) throws Exception, TimeoutException {
        boolean found = false;

        try {
            waitUntilJSReady();
            setImplicitWait(0);
            WebDriverWait wait = new WebDriverWait(driver, timeout);
            if (1 == locators.length) {
                WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locators[0]));
                found = null == element ? false : true; 
            } else if (2 == locators.length) {
                found = wait.until(ExpectedConditions.or(ExpectedConditions.visibilityOfElementLocated(locators[0]), 
                        ExpectedConditions.visibilityOfElementLocated(locators[1])));
            } else if (3 == locators.length ) {
                found = wait.until(ExpectedConditions.or(ExpectedConditions.visibilityOfElementLocated(locators[0]), 
                        ExpectedConditions.visibilityOfElementLocated(locators[1]),
                        ExpectedConditions.visibilityOfElementLocated(locators[2])));
            } else if (4 == locators.length ) {
                found = wait.until(ExpectedConditions.or(ExpectedConditions.visibilityOfElementLocated(locators[0]), 
                        ExpectedConditions.visibilityOfElementLocated(locators[1]),
                        ExpectedConditions.visibilityOfElementLocated(locators[2]),
                        ExpectedConditions.visibilityOfElementLocated(locators[3])));           
            }
        } catch (Exception e)  {
            // log...whatever
            throw e;
        } finally {
            setImplicitWait(SelTestCase.WAIT_TIME_OUT);
        }
        if (!found) throw new TimeoutException("Nothing found");
    }
Rob G
  • 55
  • 11
  • Just a thought for cleaner approach `wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath1 +"|"+xpath2 +"|" +xpath3)));`. You can use this approach if you are sure that always you will pass xpath as locator. – supputuri Aug 01 '19 at 04:01
  • Does [this](https://stackoverflow.com/questions/46147145/python-selenium-logic-operators-in-webdriverwait-expected-conditions/46147830#46147830) or [this](https://stackoverflow.com/questions/51034819/how-to-extract-dynamic-text-from-multiple-child-nodes-within-the-html-through-ge/51035034#51035034) discussion helps you? – undetected Selenium Aug 01 '19 at 13:14
  • @supputuri I do not want to limit to xpath, so this is not what I'm looking for, BUT I didn't know I could do that with xpaths. I will give that a try soon. Thanks. – Rob G Aug 03 '19 at 17:57
  • @DebanjanB No. 1 is python and 2 is getText() – Rob G Aug 03 '19 at 18:00
  • @RobG Difference within _Python_ / _Java_ / _C#_ and `getText()` / `get_attribute()` is trivial. Important is you understand how _Selenium_ interacts. – undetected Selenium Aug 03 '19 at 18:13

1 Answers1

2

You can obtain the number of locators during runtime and use them in for loop.

In the below code I created the array which holds ExpectedCondition[]. Store them before you use them in the until method and then just pass it to until

This allows you to get rid of if-else :)

public void waitForSomeElementToBeVisible(int timeout, final By... locators) throws Exception, TimeoutException {
        boolean found = false;

        try {
            waitUntilJSReady();
            setImplicitWait(0);
            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 (Exception e)  {
            // log...whatever
            throw e;
        } finally {
            setImplicitWait(SelTestCase.WAIT_TIME_OUT);
        }
        if (!found) throw new TimeoutException("Nothing found");
    }

Hope it helps!

Fenio
  • 3,528
  • 1
  • 13
  • 27
  • Thanks. I tried a similar tactic with ArrayList but couldn't make it work (even with .toArray()). This is cleaner anyway. – Rob G Aug 03 '19 at 18:03