3

I am testing a webpage that does some user error validation. When the webpage first appears, no error messages should appear, so I need to check for that. Then, depending upon the error (sometimes after clicking “submit” other times after the user enters data), I need to verify that the correct error messages appear.

In the code below, no error message should appear when the webpage is first loaded, but if I don’t enter a date and click the submit button, the error message should appear.

<div id="showNotIE" style="display: none;">
<input id="txtImplantDate" class="ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required" type="date" required="" placeholder="YYYY-MM-DD" name="txtImplantDate" ng-model="ImplantInsert.ImplantImplantDate">
</div>
<div class="ng-scope" ng-if="showMsgs && (Currentdate < newDate)" style="">
<span style="color:red;">Implant Date cannot be greater than today and is required</span>

Using the Java code below, this seems to function properly (the first check in the IE 11 browser takes a REALLY LONG TIME, but it does appear to work).

//Confirming text is not visible 
boolean isPresent = driver.findElements(By.xpath(textLocator)).size() > 0;
if (isPresent) {
 //Write to log that text is present (FAIL)
} else {
 //Write to log that text is not present (PASS)
} //end if

This code also seems to work:

//Confirming text is not visible
boolean isEmpty = driver.findElements(By.xpath(textLocator)).isEmpty();
if (isEmpty) {  
   //Write to log that text is not present (PASS)
} else {
        //Write to log that text is present (FAIL)
} //end if

However, when I test against this HTML code and use the same Selenium WebDriver Java logic to test, I get the wrong results.

<select id="selPatientTypes" class="fontInput ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required" required="" name="selPatientTypes" ng-options="n.PatienTypeID as n.PatientTypeDescription for n in scPatientTypes | filter:FilterPatientTypes" ng-model="ImplantInsert.ImplantPatientTypeID">
<option class="" value="" selected="selected">-- Please select Patient Type --</option>
<option label="Adult" value="number:1">Adult</option>
<option label="Pediatric" value="number:2">Pediatric</option>
</select>
<span class="ng-hide" style="color:red;" ng-show="showMsgs && ImplantForm.selPatientTypes.$error.required">Patient Type is required</span>

If I try using this “isDisplayed” code, Java errors out.

try {
    boolean xpathIsDisplayed = driver.findElement(By.xpath(fieldLocator[value])).isDisplayed();
    // Write to log that text is present (FAIL)
} catch (Error e) {
    //Write to log that text is not present (PASS)

} //end try

The error message is:

org.openqa.selenium.NoSuchElementException: Unable to find element with xpath == //div[2]/table[2]/tbody/tr[1]/td[2]/div[3]/span (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 30.06 seconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html  (BTW: This URL doesn’t provide any useful information)

This is another type of error logic that is used on the webpage.

<input id="txtPatientBSA" class="fontInput ng-pristine ng-untouched ng-valid ng-empty ng-valid-maxlength" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1'); " title="Patient BSA should be in range of 0 to 5.00 (X.XX)" ng-keyup="ValidateBSA()" style="direction: rtl" max="5.00" min="0.00" maxlength="4" size="4" ng-model="ImplantInsert.ImplantPatientBSA" name="txtPatientBSA" placeholder="X.XX">
<span id="ErrorMsgBSA" class="error error-keyup-1 ng-hide" style="color:red;" ng-show="ShowErrorMsgBSA"> Patient BSA should be in range of 0 to 5.00 (X.XX)</span>

Does anyone know if there is a way to check for all types of HTML error message logic and determine if they are visible or not visible on the webpage?

Thanks.

1
  • Is all error message appears in same container or different?? Commented Sep 16, 2016 at 17:16

2 Answers 2

4

I'm guessing the reason your first error code takes a really long time is because you have an implicit wait set for a long time. Implicit waits will wait for the specified amount of time for an element to appear. In the case of an error message that isn't there, it will wait for the timeout period and then move on which makes your code execute slowly. I would remove the implicit wait and add explicit waits where needed. The second error is just saying that it can't find the element with the given XPath. You probably need to update your XPath or use another locator.

Here's a Java function that you can pass your desired locator into and it will return true if the element exists and is visible.

/**
 * Returns whether an element is visible
 * 
 * @param locator the locator to find the desired element
 * @return true if the element exists and is visible, false otherwise
 */
public boolean IsVisible(By locator)
{
    List<WebElement> elements = driver.findElements(locator);
    if (elements.isEmpty())
    {
        // element doesn't exist
        return false;
    }
    else
    {
        // element exists, check for visibility
        return elements.get(0).isDisplayed();
    }
}

For the element below,

<span id="ErrorMsgBSA" class="error error-keyup-1 ng-hide" style="color:red;" ng-show="ShowErrorMsgBSA"> Patient BSA should be in range of 0 to 5.00 (X.XX)</span>

you could use the locator, By.id("ErrorMsgBSA").

For the element below,

<span class="ng-hide" style="color:red;" ng-show="showMsgs && ImplantForm.selPatientTypes.$error.required">Patient Type is required</span>

you could use a CSS selector like, "span.ng-hide" which just means find a SPAN that contains a class (.) ng-hide.

A CSS Reference

CSS Selector Tips

Sign up to request clarification or add additional context in comments.

7 Comments

This logic doesn't error out and it appears to work when the error message text is not present, but when the error text appears, "isDisplayed()" is reading "False".
I think your statement about using another locator would probably work.
I'd like to search by cssSelector, but I don't know how to create the address. Perhaps by looking at the value of "ng-show" to see what it equals, would solve the problem. Or perhaps class = "ng-hide"...
I've added some more examples, one using a CSS selector and some CSS Selector references.
If this answered your question, please mark it as accepted and if you found it useful (or any answer for that matter) please upvote it.
|
-2

you should add findElement in try catch block and use findElement instead of findElements (Xpath is a unique). Use for construction. the point is that your element can be there, but the selenium may not be able to find it at once. So you need to check it more then once and wait a little after every iteration.

    WebElement element = null;
    boolean flag = false;
        for (int i = 0; i< 10; i++) {// iterating 10 times 
            try {
                element = driver.findElement(By.xpath("yourXpath"));
                if (element != null) {
                    flag = true;
                    break;
                }
            } catch (Exception e) {
                 //you can log or whatever you want 
            }
            pause(1000); //after iteration wait for a second , 
                         //so it will give a time to load the DOM
        }
 if(flag){
     //your code goes here 
 }else{
    //your code goes here 
 }

7 Comments

XPath is not always unique... it depends on the XPath and the HTML of the page. .findElement will only return the first element no matter how many elements match. This function is not necessary... you should instead use WebDriverWait and ExpectedConditions and wait for the element to be visible.
I wait 5 seconds for the entire page to load before I start this logic, so I don't think this will work.
@JeffC if use Webdriver you should know that there are many cases when the element presents but it can't be found by selenium so that you have to use even JS, because other methods does not work. Show me a case where you have 2 different element with the same xpath, it interesting...
If the element is visible, WebDriver should find it. The only cases that I've seen where JSE is needed is when the element exists but is hidden. I'm confused about what you are saying about XPath... it's simple to craft an XPath that returns more than one element. For example, "//a" returns 276 elements on this page. It really depends on how you create the XPath... but it's not hard to have an XPath return more than 1 element. If you only want the first element (or only one element is returned), you should use .findElement() otherwise use .findElements().
What I was talking about is that you can replace your most of your function with a one liner, new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(locator));. It's better to use the library provided instead of writing your own code because the library has been fully tested, etc. It also saves time and effort.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.