0

I'm trying to create a explicit wait method in my framework to handle the user's input. The method is supposed to handle all types of search: id, xpath, and css. However, When I tried testing this method, the error is returning an odd error

Method of explicit wait

public static void isDisplaying(String variable){
    wait = new WebDriverWait(driver,3);
    System.out.println("Looking for: " + variable);

    if (driver.findElement(By.id(variable)).isDisplayed()){
        System.out.println("Found variable via id");
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(variable)));
    } else if (driver.findElement(By.xpath(variable)).isDisplayed()) {
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(variable)));
        System.out.println("Found variable via xpath");
    } else if (driver.findElement(By.cssSelector(variable)).isDisplayed()){
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(variable)));
        System.out.println("Found variable via css");
    } else {
        System.out.println(variable +" is not displayed.");
    }
}

Error that I'm receiving:

org.openqa.selenium.NoSuchElementException: Unable to locate element: #\/\/div\[\@id\=\'slideOut\-nav\'\]\/ul\/li\[2\]\/a

I have no clue why it is returning the value with all those back and forward slashes. My guess is that the application failed as soon as it tried searching the xpath string using id. But shouldn't it be moving to the next else if statement? How should I handle such issue, if this is indeed the issue?

When I simply locate the element and clicking, it works fine and returns the correct path:

//div[@id='slideOut-nav']/ul/li[2]/a

I've been stuck on this issue for a loooooong time so any help would greatly be appreciated!!

Krishnan Mahadevan
  • 14,121
  • 6
  • 34
  • 66
MikeyC
  • 85
  • 1
  • 7

3 Answers3

1

The call to driver.findElement(By.id(variable)) is bound to throw exceptions immediately if the element is not found.

Try replacing calls to driver.findElement() with driver.findElements() because this call does not throw exceptions but it returns an empty list of webelements when the call fails.

If you are really looking at building a generic method, then you should first parse the variable contents to see if it represents xPath or css and finally fall back to using id (or) name.

You can take a look at this implementation for reference.

Krishnan Mahadevan
  • 14,121
  • 6
  • 34
  • 66
  • Hi Krishnan, thank you for your response. Just learned something new! Never knew findElement would immediately throw exception when the element is not found. I have modified my code with if statements by checking the initial characters of the variable to identify the locator. – MikeyC Feb 27 '17 at 08:29
  • I've fixed my issue by reassigning all the variables to "By variablename". Thanks for the help! – MikeyC Mar 11 '17 at 01:07
0

I am not sure what your function is intended to do. You are checking to see if the element is displayed and if it is then wait for it to be displayed. If an element is displayed, it's already visible.

Instead of passing a String around, pass a locator, By. Passing a locator reduces having to check all the different locator types.

I've added a return type of boolean to your function so you can reuse it. It waits for up to 3 seconds for the element to be visible. If it doesn't timeout, the element is visible and it returns true. If it does time out, the element is not visible and returns false. You can reduce your code to the below.

public static boolean isDisplaying(By locator)
{
    try
    {
        new WebDriverWait(driver, 3).until(ExpectedConditions.visibilityOfElementLocated(locator));
        return true;
    }
    catch (TimeoutException e)
    {
        return false;
    }
}

You would call it like

System.out.println(isDisplaying(By.xpath("//div[@id='slideOut-nav']/ul/li[2]/a")));

or

System.out.println(isDisplaying(By.id("someId")));
JeffC
  • 22,180
  • 5
  • 32
  • 55
  • Hi Jeff, thanks for your response. I wont know what the user will be inputting, hence the if statements. What I am providing is hard coded variables that may contain one of the 3(id, xpath, css), which the user should not have to care about. – MikeyC Feb 27 '17 at 08:22
  • You should probably add some of this to your original question. When you mentioned "the user" I assumed you meant an automator that was going to consume this function. If the user is going to handcraft one of these locators, they will know which kind they are crafting. You should add a dropdown, etc. as part of the user input where they can choose by id, css selector, xpath, etc. That will allow you to put the two together correctly without having to parse them. You are still going to have a hard time differentiating between IDs and some CSS selectors. – JeffC Feb 27 '17 at 14:34
0
public void waitUntilElementclickable(WebElement element){
    //Waits Until Element is Clickable on screen
    WebDriverWait wait = new WebDriverWait(driver, 10);
    wait.until(ExpectedConditions.elementToBeClickable(element));
}
  • 1
    Whilst this code snippet is welcome, and may provide some help, it would be [greatly improved if it included an explanation](//meta.stackexchange.com/q/114762) of *how* and *why* this solves the problem. Remember that you are answering the question for readers in the future, not just the person asking now! Please [edit] your answer to add explanation, and give an indication of what limitations and assumptions apply. – Toby Speight Feb 27 '17 at 10:52