0

I am running a test on a web page that may or may not have a certain element. The procedure is the following: I fill out the form, then click "Search" button. When the browser opens a new url, I need to choose an element_1, but if it does not exist I must choose element_2.

WebElement element = driver.findElement(By.xpath("//....")) || driver.findElement(By.xpath("//..."));
element.click();

// This does not do the trick, is there any other way? Is it possible to do without try and catch?

Buras
  • 3,069
  • 28
  • 79
  • 126
  • @Code Enthusiastic, do you know the answer to the above question? – Buras Mar 19 '13 at 07:05
  • @Keyser, if I use if-esle then I would need to create a new method that would verify element presence and return boolean, say: public boolean isPresent {... return present; } I was hoping to have a different solution – Buras Mar 19 '13 at 07:07
  • Isn't your above code giving you error Buras? because I should give error like `driver.findElement(By.xpath("//....")) is not boolean, you can not apply boolean operation to it` or something like it! – Patriks Mar 19 '13 at 07:08
  • @Pratic, you are right. It is giving me an error. I know it is not boolean. I was just trying to write kinda pseudocode...to get my point across. – Buras Mar 19 '13 at 07:10
  • ok @Buras then code below should work for you I think. try it and let me know. :) – Patriks Mar 19 '13 at 07:11
  • @Keyser, what is the shorthand, could you show me, please? – Buras Mar 19 '13 at 07:11
  • @Buras, I think it is what I have shown in my answer. `(condition) ? op1 : op2` – Patriks Mar 19 '13 at 07:13
  • Check edit in my answer @Buras. – Patriks Mar 19 '13 at 07:24

5 Answers5

3

Using driver.findElement() does the implicit wait. So even when secondElement appears - the test will wait for some time. Instead using findElements() in a WebDriverWait might be a better solution.

    WebDriverWait wait = new WebDriverWait(driver, 10);
    // Wait for one element to be available
    wait.until(new Predicate<WebDriver>() {
        @Override public boolean apply(WebDriver driver) {
            return driver.findElements(By.cssSelector("xpath1")).size() > 0
                    || driver.findElements(By.cssSelector("xpath2")).size() > 0;
        }
    });
    // Get the element
    WebElement e = null;
    if (driver.findElements(By.cssSelector("xpath1")).size() > 0)
        e = driver.findElements(By.cssSelector("xpath1")).get(0);
    else if (driver.findElements(By.cssSelector("xpath2")).size() > 0)
        e = driver.findElements(By.cssSelector("xpath1")).get(0);

    if (e != null)
        e.click();
Dakshinamurthy Karra
  • 5,353
  • 1
  • 17
  • 28
  • what is the difference between using the ExpectedCondition and Predicate in the until? – Code Enthusiastic Mar 19 '13 at 07:52
  • I think implicit wait is the better choice in this case as the wait.until will only wait until either element1 or element 2 appears, that is if element2 is loaded before element1, don't you think it will assume that elemen1 is not present or am I missing something here? – Code Enthusiastic Mar 19 '13 at 07:55
  • Depends on the requirement. I am assuming that either the first or second will be available. If that is not the case, implicit wait is a better option. – Dakshinamurthy Karra Mar 19 '13 at 08:00
2

You can try something like this, yes, it is using try and catch blocks but this is the procedure one would follow as there is no special method isPresent() other than isDisplayed(), isEnabled() and isSelected() and what is wrong in handling the exception with try and catch block anyway?

boolean isElement1Present = true;

try{       
      driver.findElement(By.xpath("xpathExpression1"));    
}catch (NoSuchElementException e){
    isElement1Present = false;
}

if(isElement1Present == false)
     driver.findElement(By.xpath("xpathExpression2"));

Or Using the below avoids try and catch block.

List<WebElement> elements = driver.findElements(By.xpath("xpathExpression1"));   

if (elements.size() == 0) {
    System.out.println("Element is not present"); 
} else {
    System.out.println("Element is present");
}
Code Enthusiastic
  • 2,827
  • 5
  • 25
  • 39
  • You forgot to assign it to something :p, also, the second element could also throw the exception. Just being thorough. – keyser Mar 19 '13 at 08:06
1

This might help you

 WebElement element = null;

try{
    element = driver.findElement(By.xpath("//path1/...."));
}catch(NoSuchElementException ex){
    try{
        element = driver.findElement(By.xpath("//path2/...."));
    }catch(NoSuchElementException ex2){}
} 

if(element!=null) element.click();
Patriks
  • 1,012
  • 1
  • 9
  • 29
  • Doesn't this throw NoSuchElementException? – Code Enthusiastic Mar 19 '13 at 07:08
  • You should catch the specific type of Exception that is NoSuchElementException for your code to work better. The above one might throw RuntimeException if there is something wrong with the xpath expression then you are catching that exception and assuming that element is not present – Code Enthusiastic Mar 19 '13 at 07:51
  • @CodeEnthusiastic Happy? but I was guessing that the guy is knowing java very well, because he is working on selinium. :) – Patriks Mar 19 '13 at 09:07
1

Actually there is no explicit way. You can use WATIR. It does provide such a code if you are ok with Ruby. Otherwise, you just try and catch.

messivanio
  • 2,263
  • 18
  • 24
0

I think the better approach here is to use CSS3 selectors which can group selectors by using a comma:

Apologize for the python:

element = WebDriverWait(driver, 2).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "tr.entry , div.not-found"))
)

Assuming the web page would display a <div class="not-found"> in case nothing is found. Or display the results with <tr class="entry">

ClojureMostly
  • 4,652
  • 2
  • 22
  • 24