Reputation: 31
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.
Upvotes: 3
Views: 7020
Reputation: 25643
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
.
Upvotes: 4
Reputation: 559
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
}
Upvotes: -2