When checking to see if a price is given on a webpage, I don't want to check the exact value (as that's subject to change), I first want to check that the page object exists (no error, etc.) and then that it's returning a numerical value.
Is this possible?
With C#
private IWebElement priceElement = driver.FindElement(By.Id("price_value"));
public bool PriceObjectValidation()
{
decimal outDecim;
try
{
string str = priceElement.Text;
bool isDecimal = decimal.TryParse(str, out outDecim);
return isDecimal;
}
catch (NoSuchElementException e)
{
throw new Exception("Price element is not found");
}
catch (FormatException)
{
return false;
}
}
In your Test Script you can use
Assert.True(PriceObjectValidation(), "Price element is not numeric value");
Related
I need to find if an element is displayed or not. How to check that in selenium web driver?
if(driver.findElement(By.id("p_first_name")).isDisplayed())
{
WebElement fname =driver.findElement(By.id("p_first_name"));
fname.sendKeys("pradnya");
WebElement lname = driver.findElement(By.xpath("//*[#id=\"p_last_name\"]"));
lname.sendKeys("Bolli");
WebElement Address1 = driver.findElement(By.xpath("//*[#id=\"address_11\"]"));
Address1.sendKeys("New address1");
WebElement Address2 = driver.findElement(By.xpath("//*[#id=\"address_21\"]"));
Address2.sendKeys("New address2");
WebElement City = driver.findElement(By.xpath("//*[#id=\"city1\"]"));
City.sendKeys("Pune");
WebElement Country = driver.findElement(By.xpath("//*[#id=\"country1\"]"));
Country.sendKeys("India");
WebElement ZipCode = driver.findElement(By.xpath("//*[#id=\"pincode1\"]"));
ZipCode.sendKeys("India");
WebElement State = driver.findElement(By.xpath("//*[#id=\"bds\"]"));
State.sendKeys("Maharashtra");
}
else
{
WebElement address = driver.findElement(By.xpath("//*[#id=\"update_add77\"]"));
address.click();
}
On the checkout page first it shows address form and when user fils that then listing is shown. Address form is not showing when the listing is showing. In this case, how to check if an address form field is displayed or not?
I use above code but it gives me exception message
'Unable to locate element: #p_first_name'
The element is giving NoSuchElementException as the element is not present on the UI on which you are trying to find it using the isDisplayed() method.
So, to solve your problem you should fetch the list of the element and then can get the size of that list, if the size is greater than 0, it means the element is present on the page else the element is not present.
You need to make the following changes in the code:
if(driver.findElements(By.id("p_first_name")).size()>0){
// Add the if code here
}
else{
// Add the else code here
}
You can create method for such check. We are using NoSuchElementException to verify element is not existing.
public boolean isElementExist(By locator)
{
try {
driver.findElement(locator);
} catch (NoSuchElementException e) {
return false;
}
return true;
}
Or due slow loading and timeouts, i advice to use *WebDriverWait*
public boolean isElementPresent(By element,int timeOutInSeconds,int pollingEveryInMiliSec) {
try {
WebDriverWait wait = new WebDriverWait(d, timeOutInSeconds);
wait.pollingEvery(pollingEveryInMiliSec, TimeUnit.MILLISECONDS);
wait.ignoring(NoSuchElementException.class);
wait.ignoring(ElementNotVisibleException.class);
wait.ignoring(StaleElementReferenceException.class);
wait.ignoring(NoSuchFrameException.class);
wait.until(ExpectedConditions.visibilityOfElementLocated(element) ));
return true;
}
catch(Exception e) {
return false;
}
}
If you consider timeOutInSeconds=20 and pollingEveryInMiliSec=5 in every 5 ms this method will search for the giving element until it find's it with in 20ms
I created a method that takes all values from a datepicker and throws it into a variable of type List . Then I made a FOR looking for a specific day and when I find the day, I click on it.
Now I need to implement a routine that displays an error message when the last day is not valid. I am using the JOptionPane.showMessageDialog class to display the error. But the problem is that the message appears every time the script enters the IF to test the value and can not find it.
public void campoRechamada(String dia) {
driver.findElement(By.id("txtDtRechamada")).click();
WebElement dateWidget = driver.findElement(rechamada);
// List<WebElement> linhas = dateWidget.findElements(By.tagName("tr"));
List<WebElement> colunas = dateWidget.findElements(By.tagName("td"));
for (WebElement cell : colunas) {
if (cell.getText().equals(dia)) {
cell.findElement(By.linkText(dia)).click();
break;
} else {
JOptionPane.showMessageDialog(null, "The date entered in the method is invalid: " + dia, "Erro",
JOptionPane.ERROR_MESSAGE);
}
}
}
Passage from the parameter to the method.
Method that receives the parameter and validates whether the day is valid or not.
Datepicker
Add a boolean flag outsiet for loop and change it to be true when find the day.
Then check the flag is true or false after the for loop:
public void campoRechamada(String dia) {
driver.findElement(By.id("txtDtRechamada")).click();
WebElement dateWidget = driver.findElement(rechamada);
// List<WebElement> linhas = dateWidget.findElements(By.tagName("tr"));
List<WebElement> colunas = dateWidget.findElements(By.tagName("td"));
boolean find = false;
for (WebElement cell : colunas) {
if (cell.getText().equals(dia)) {
find = true;
cell.findElement(By.linkText(dia)).click();
break;
}
}
if(find == false) {
JOptionPane.showMessageDialog(null, "The date entered in the method is invalid: " + dia, "Erro",
JOptionPane.ERROR_MESSAGE);
}
}
Can I assert an element that is not present? I want to assert that the element "textarea" is not present on the site.
try {
assertFalse(isElementPresent(By.cssSelector("textarea")));
} catch (Error e) {
verificationErrors.append(e.toString());
System.out.println(verificationErrors);
}
private boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
The code in your question ought to work.
Another method is to call driver.findElements instead of driver.findElement (note the added s). Instead of throwing a NoSuchElementException, driver.findElements will return an empty list if there are no matches. From there, you just have to assert that the size of the returned list is zero.
Method #1
import junit.framework.Assert;
if(!isElementPresent(By.cssSelector("textarea")))
{
System.out.println("Text Not Available");
} else
{
Assert.fail();
}
Method #2
In your case, please go with negative use case given below
positive case
import junit.framework.Assert;
boolean b = driver.getPageSource().contains("your text");
Assert.assertTrue(b);
negative case
import junit.framework.Assert;
boolean b = driver.getPageSource().contains("your text");
Assert.assertFalse(b);
There are numerous ways to do this. The above is few :)
Method #1 is highly suggested!
In my application during releases, I'm forced to change id to xpath or class name or tag. So I can't use any of the element selection methods like driver.findElement(By.id()).
In the next build I might have to use driver.findElement(By.xpath()) OR driver.findElement(By.name()) for the same element location. This means I will have to visit each and every class file I have written and modify By.id() to the respective selector.
Is there any way to avoid this by parametrising or some other way to resolve this issue?
Thanks in advance.
Had similar issue so came up with this generic method
public WebElement getElement(Identifier identifier, String expression) {
By byElement = null;
switch (identifier) {
case xpath: {
byElement = By.xpath(expression);
break;
}
case id: {
byElement = By.id(expression);
break;
}
case name: {
byElement = By.name(expression);
break;
}
case classname: {
byElement = By.className(expression);
break;
}
case linktext: {
byElement = By.linkText(expression);
break;
}
case paritallinktext: {
byElement = By.partialLinkText(expression);
break;
}
case tagname: {
byElement = By.tagName(expression);
break;
}
}
WebElement element = driver.findElement(byElement);
return element;
}
public static enum Identifier {
xpath, id, name, classname, paritallinktext, linktext, tagname
};
You can also use properties file to store values. Like
# login
login.username.identifier=xpath
login.username.expression=//input[#id='userNameText']
and in Java you can write
SeleniumUtil.getElement(prop.getProperty("login.username.identifier"), prop.getProperty("login.username.expression")).click();
So you will not need to change any Java code
You can also make use of key=value in your locators as a good practice which was seen in Selenium 1.0 and accordingly the selector will be selected.
So you can have a common getByLocator method that returns you with the By class object, example code
public By getByLocator(String locator) {
By by = null;
if (locator.startsWith("class=")) {
by = By.className(locator.replace("class=", "").trim());
} else if (locator.startsWith("css=")) {
by = By.cssSelector(locator.replace("css=","").trim());
} else if (locator.startsWith("link=")) {
by = By.linkText(locator.replace("link=", "").trim());
} else if (locator.startsWith("//") or locator.startsWith("/")) {
by = By.xpath(locator);
} else if (locator.startsWith("id=")) {
by = By.id(locator.replace("id=", ""));
} else {
by = By.name(locator.replace("name=", ""));
}
return by;
}
Here I made use of link=, css=, id= as some of factors to identify the locator type and accordingly I got the By locator object.
The usage of this would be something like below
List<WebElement> element = driver.findElements(getByLocator("css= input[type=input]"));
You have to work on your framework. Make it more generic. My code handles the problem. I have used key and value concept. In my .properties file, I have defind the object like
Test_login_user=id||username
Test_login_pass=className||passwd
after that my code get the value and spits it from ||. Here I have mention the type of locator if its BY id then id||username etc.
public By extractWebElement(String keyobject){
if(keyobject.startsWith("name_")){
currentWebElement = By.name(actualLocator);
}else if(keyobject.startsWith("xpath_")){
currentWebElement =By.xpath(actualLocator);
}else if(keyobject.startsWith("linkText_")){
currentWebElement =By.linkText(actualLocator);
}else if(keyobject.startsWith("id_")){
currentWebElement =By.id(actualLocator);
}else if(keyobject.startsWith("cssSelector_")){
currentWebElement =By.cssSelector(actualLocator);
}else if(keyobject.startsWith("tagName_")){
currentWebElement =By.tagName(actualLocator);
}
return currentWebElement;
}
public String extractActualLocator(String locatorInSheet ){
int underScoreIndex = locatorInSheet.indexOf('_');
return locatorInSheet.substring(underScoreIndex+1);
}
Now actual locator is in the "currentWebElement", we can use this in our methods. See how my keywords are written
public String enterTextt(By object,String data){
APP_LOGS.debug("Writing in text box");
try{
***driver.findElement(object).sendKeys(data);***
}catch(Exception e){
return Constants.KEYWORD_FAIL+" Unable to write "+e.getMessage();
}
return Constants.KEYWORD_PASS;
}
In Selenium 2 I want to ensure that an element on the page that the driver has loaded does not exist. I'm including my naive implementation here.
WebElement deleteLink = null;
try {
deleteLink = driver.findElement(By.className("commentEdit"));
} catch (NoSuchElementException e) {
}
assertTrue(deleteLink != null);
Is there a more elegant way that basically verifies to assert that NoSuchElementException was thrown?
If you are testing using junit and that is the only thing you are testing you could make the test expect an exception using
#Test (expected=NoSuchElementException.class)
public void someTest() {
driver.findElement(By.className("commentEdit"));
}
Or you could use the findElements method that returns an list of elements or an empty list if none are found (does not throw NoSuchElementException):
...
List<WebElement> deleteLinks = driver.findElements(By.className("commentEdit"));
assertTrue(deleteLinks.isEmpty());
...
or
....
assertTrue(driver.findElements(By.className("commentEdit")).isEmpty());
....
You can use this:
Boolean exist = driver.findElements(By.whatever(whatever)).size() == 0;
If it doesn't exist will return true.
I split out page classes so I don't have to define elements more than once. My nunit and mbunit test classes call those page classes. I haven't tried this out yet but this is how I'm thinking about doing it so I can use .exists() like I did with WatiN.
Extension Class:
public static class ExtensionMethods
{
public static IWebElement ElementById(this IWebDriver driver, string id)
{
IWebElement e = null;
try
{
e = driver.FindElement(By.Id(id));
}
catch (NoSuchElement){}
return e;
}
public static bool Exists(this IWebElement e)
{
if (e == null)
return false;
return true;
}
}
Page Class:
public IWebElement SaveButton { get { try { return driver.ElementById("ctl00_m_m_body_body_cp2_btnSave")); } }
Test Class:
MyPageClass myPageClass = new MyPageClass(driver);
if (myPageClass.SaveButton.Exists())
{
Console.WriteLine("element doesn't exist");
}
You can retrieve a list of elements by using driver.findElements("Your elements") and then search for the element. if the list doesn't contains the element you got yourself your desired behavior :)
If you're using the Javascript API, you can use WebElement.findElements(). This method will return a Promise with an array of found elements. You can check the length of the array to ensure no items were found.
driver.findElements(By.css('.selector')).then(function(elements) {
expect(elements.length).to.equal(0)
})
I'm using Chai assertion library inside the Promise's callback to expect a certain value.
Reference: https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebElement.html
Best solution
protected boolean isElementPresent(WebElement el){
try{
el.isDisplayed();
return true;
}
catch(NoSuchElementException e){
return false;
}
}
public boolean exist(WebElement el){
try {
el.isDisplayed();
return true;
}catch (NoSuchElementException e){
return false;
}
}
if(exist(By.id("Locator details"))==false)
or
WebElement el= driver.findElementby(By.locator("locator details")
public boolean exists(WebElement el)
try{
if (el!=null){
if (el.isDisplayed()){
return true;
}
}
}catch (NoSuchElementException e){
return false;
}
}
Using webdriver find_element_xxx() will raise exception in my code and take us the waiting time of implicit/explicit webdriver wait.
I will go for DOM element check
webdriver.execute_script("return document.querySelector('your css class')")
p.s.
Also found similar discussion on our QA-main sister site here
For full check for visibility+existence
# check NOT visible the :aftermeet and :viewintro
# ! . . ! !offsetWidth to check visible in pure js ref. https://stackoverflow.com/a/20281623/248616
css='yourcss'; e=wd.execute_script(f"return document.querySelector('{css}').offsetWidth > 0") ; assert not e
# check NOT exists :viewintro
css='yourcss'; e=wd.execute_script(f"return document.querySelector('{css}')") ; assert not e
Use assertFalse :)
assertFalse(isElementPresent(By.className("commentEdit")));