webdriver org.openqa.selenium.NoSuchElementException: Unable to locate element: - java

What I'm trying to do is checking elements on each page, if visible and if it is visible on current page i would like to make some assertion.
My code looks like below:
package com.example.tests;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.Select;
import com.thoughtworks.selenium.Selenium;
import com.thoughtworks.selenium.webdriven.WebDriverBackedSelenium;
public class Webdriver_class {
private WebDriver driver;
private String baseUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
#Before
public void setUp() throws Exception {
driver = new FirefoxDriver();
baseUrl = "http://www.lotto.pl/";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void testUntitled() throws Exception {
driver.get(baseUrl + "/lotto/wyniki-i-wygrane/wygrane");
assertEquals("Wyniki i wygrane Lotto i Lotto Plus | Lotto, Kaskada, Multi Multi, Mini Lotto, Joker, Zdrapki - lotto.pl", driver.getTitle());
assertEquals("28-07-11", driver.findElement(By.xpath("//div[#id='page']/div[3]/div[2]/div[2]/table/tbody/tr[77]/td[5]")).getText());
///number of pages///
String xpath = "html/body/div[3]/div[1]/div/div[3]/div[2]/div[2]/div[3]/div/ul/li";
List<WebElement> elements = driver.findElements(By.xpath(xpath));
int x=elements.size();
System.out.println("liczba stron = "+elements.size());
////end//////
for(int i=1; i<=x; i++){
if(driver.findElement(By.xpath("//div[#id='page']/div[3]/div[2]/div[2]/table/tbody/tr[contains(td[3],'Warszawa') and contains (td[5],'21-02-09')]/td[1]")) != null)
{ assertEquals("100.", driver.findElement(By.xpath("//div[#id='page']/div[3]/div[2]/div[2]/table/tbody/tr[contains(td[3],'Warszawa') and contains (td[5],'21-02-09')]/td[1]")).getText());
assertEquals("100.", driver.findElement(By.xpath("//div[#id='page']/div[3]/div[2]/div[2]/table/tbody/tr[contains(td[3],'Warszawa') and contains (td[5],'21-02-09')]/td[1]")).getText());
};
if(driver.findElement(By.xpath("//div[#id='page']/div[3]/div[2]/div[2]/table/tbody/tr[contains(td[3],'Nowa Sól') and contains (td[5],'05-04-12')]/td[1]")) != null)
{ assertEquals("99.", driver.findElement(By.xpath("//div[#id='page']/div[3]/div[2]/div[2]/table/tbody/tr[contains(td[3],'Nowa Sól') and contains (td[5],'05-04-12')]/td[1]")).getText());
};
//go to the new page//
driver.findElement(By.xpath("html/body/div[3]/div[1]/div/div[3]/div[2]/div[2]/div[3]/div/ul/li/a["+i+"]")).click();
for (int second = 0;; second++) {
if (second >= 60) fail("timeout- nie znalazł 'Wyniki i wygrane Lotto i Lotto Plus' ");
try { if ("Wyniki i wygrane Lotto i Lotto Plus".equals(driver.findElement(By.cssSelector("h1.title")).getText())) break; } catch (Exception e) {}
Thread.sleep(50000);
}
}
}
}
All elements are visible on the first page so on first page is ok but when it goes to the second page I get error:
org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"xpath","selector":"//div[#id='page']/div[3]/div[2]/div[2]/table/tbody/tr[contains(td[3],'Warszawa') and contains (td[5],'21-02-09')]/td[1]"}
Command duration or timeout: 30.10 seconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Can anyone help with it. Why I get this error when I use IF statement. 'Webdriver' doesnt find element = doesnt make assertion, does it?
So when it doesnt find element then should go further
Please, help me what to do to make it working :)
thanks

The possible cause for this error might be that the element that you are trying to find with xpath :-
//div[#id='page']/div[3]/div[2]/div[2]/table/tbody/tr[contains(td[3],'Warszawa') and contains (td[5],'21-02-09')]/td[1]
is not present in the second page. So, even if you have used if for checking whether the element is present or not, if webdriver could not find the element, then selenium will throw NoSuchElementException exception. To make it simpler, let's put it in this way :-
if (driver.findElement(By.xpath(element_xpath)) != null)
{
do_some_stuff
}
Now let's break it as follows :-
is_present = driver.findElement(By.xpath(element_xpath))
if(is_present != null)
{
do_some_stuff
}
The above piece of code is the simplified version of the previous one and this is how your previous code is evaluated while you run the program. That is, first the condition inside if block is evaluated (in your case driver.findElement(By.xpath()) and then the result is compared with null.
But in the first case, while webdriver tries to locate the element with the given xpath, it couldn't be found. So at that point itself webdriver throws NoSuchElementException exception. So, once exception is encountered, python doesn't evaluate it any more and the program terminates.
To solve it, put it inside try-catch block :-
try
{
if (driver.findElement(By.xpath(element_xpath)) != null)
{
do_some_stuff
}
}
catch(Exception e)
{
System.out.println(e);
System.out.println("Element not found");
}
So, even if webdriver finds any Exception failing to locate the given element, instead of terminating the program it will move further and the next piece of your code will be executed, because the catch block will take care of the exception and let your program move further.
I would suggest you to put each if block within try-catch, so, even though any of your if block has an exception, the next if block would not be affected by it's exception.
Hope, this would solve your issue.

Related

the getText() function in selenium with web element returns null string

so I am learning on this website to learn how to automate using selenium with Java.
my task was to enter Ind in the edit box called Suggession Class Example and then there will be a list that appears like in this image :
I have to click on India and then check if the editText had the value India as supposed or not.
I manage to do all of that except for one thing that I am facing right now, I can't extract the text in the editText back. every time I try to extract it using .getText() method, it returns null string ("") although the visible text is India. I tried many thing like using .getAttribute("value"); it returned Ind, I tried using .getAttribute("innerText"); it returned null string (""). this is the HTML code of the part I want to extract its text:
<input type="text" id="autocomplete" class="inputs ui-autocomplete-input" placeholder="Type to Select Countries" autocomplete="off">
as you see there is no attribute that I can use to get the text back.
this is my attempt so far:
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
public class Assignment8 {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
System.setProperty("webdriver.chrome.driver", "C:\\chrome driver\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://rahulshettyacademy.com/AutomationPractice/");
WebElement editText = driver.findElement(By.xpath("//input[#id='autocomplete']"));
editText.sendKeys("Ind");
Thread.sleep(500);
List<WebElement> suggested = driver.findElements(By.className("ui-menu-item"));
for(WebElement e : suggested)
if (e.getText().equalsIgnoreCase("India")) {
e.click();
break;
}
Thread.sleep(500);
System.out.println(editText.getText());
if(editText.getText().equalsIgnoreCase("India"))
System.out.println("Success");
else
System.out.println("Failed");
}
}
and this is the output in the console:
Failed
everything is done successfully like the clicking part, but my problem is extracting the text back of that editText, I don't have any prior knowledge in HTML, thought that someone could help me here.
so I figured out what is the problem, the problem was in this line :
Thread.sleep(500);
the delay wasn't enough to get the text written back when clicked on the list, so I change it to :
Thread.sleep(1500);
and it worked.
also I was supposed to use .getAttribute("value"); instead of .getText(); to Get the visible text (i.e. hidden by CSS)

Getting StaleElementReferenceException while trying print the link names

I'm trying to print first 5 pages links displayed in google search.. But getting StateElementReferenceException Not sure which one went wrong..
public class GoogleCoInTest {
static WebDriver driver = null;
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.gecko.driver", "D:\\bala back up\\personel\\selenium\\Jars\\Drivers\\geckodriver.exe");
driver=new FirefoxDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://www.google.co.in/");
//driver.findElement(By.xpath("//input[class='gsfi']")).sendKeys("Banduchode");;
WebElement search=driver.findElement(By.cssSelector("input#lst-ib"));
search.sendKeys("Banduchode");
search.sendKeys(Keys.ENTER);
printLinksName();
List<WebElement> fiveLinks=driver.findElements(By.xpath(".//*[#id='nav']/tbody/tr/td/a"));
for(int i=0;i<5;i++){
System.out.println(fiveLinks.get(i).getText());
fiveLinks.get(i).click();
Thread.sleep(5000);
printLinksName();
}
}
public static void printLinksName() throws InterruptedException{
List<WebElement> allLinks=driver.findElements(By.xpath("//*[#id='rso']/div/div/div/div/div/h3/a"));
System.out.println(allLinks.size());
//print all list
for(int i=0;i<allLinks.size();i++){
System.out.println("Sno"+(i+1)+":"+allLinks.get(i).getText());
}
}
}
it prints fine till 2nd page , but there after I am getting
Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: The element reference of <a class="fl"> stale: either the element is no longer attached to the DOM or the page has been refreshed
For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html
A couple of things:
Your script prints the result from the first 2 pages as expected.
When you call printLinksName() for the first time it works.
Next, you are storing the 10 PageNumbers in a Generic List of type WebElement.
First time within the for() loop you are clicking on the WebElement of Page 2 and then printing all the links by calling printLinksName().
While you are in the second iteration within for() loop, the reference of List<WebElement> fiveLinks is lost as the DOM have changed. Hence, you see StaleElementReferenceException.
Solution
A simple solution to avoid StaleElementReferenceException would be to move the line of code List<WebElement> fiveLinks=driver.findElements(By.xpath(".//*[#id='nav']/tbody/tr/td/a")); with in the for() loop. So your code block will look like:
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class Q44970712_stale
{
static WebDriver driver = null;
public static void main(String[] args) throws InterruptedException
{
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
driver=new FirefoxDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://www.google.co.in/");
//driver.findElement(By.xpath("//input[class='gsfi']")).sendKeys("Banduchode");;
WebElement search=driver.findElement(By.cssSelector("input#lst-ib"));
search.sendKeys("Banduchode");
search.sendKeys(Keys.ENTER);
printLinksName();
for(int i=0;i<5;i++)
{
List<WebElement> fiveLinks=driver.findElements(By.xpath(".//*[#id='nav']/tbody/tr/td/a"));
System.out.println(fiveLinks.get(i).getText());
fiveLinks.get(i).click();
Thread.sleep(5000);
printLinksName();
}
}
public static void printLinksName() throws InterruptedException
{
List<WebElement> allLinks=driver.findElements(By.xpath("//*[#id='rso']/div/div/div/div/div/h3/a"));
System.out.println(allLinks.size());
//print all list
for(int i=0;i<allLinks.size();i++)
{
System.out.println("Sno"+(i+1)+":"+allLinks.get(i).getText());
}
}
}
Note: In this simple solution when you finish printing the second page, next when you will create List<WebElement> fiveLinks through xpath with .//*[#id='nav']/tbody/tr/td/a for second time, Page 1 is the first element which gets stored in the fiveLinks List. Hence you may be again redirected to Page 1. To avoid that you may consider to take help of xpath with proper indexing.
your script is trying to click on each link from the first page, which brings you to a new page. once it completes work on that page, it doesn't seem to return to the first page, so the script can't find the next link in your list.
even if it did return to the first page, you would still have a stale element because the page has been reloaded. You'll need to keep track of the links in the first page by something else (like the href maybe?), and find the link again by that identifier before you click on it.
This is due to referencing object after moving to another page. please try to add the following lines inside the for loops at the end. It may resolve stale reference issue.
driver.navigate().back();
fiveLinks=driver.findElements(By.xpath(".//*[#id='nav']/tbody/tr/td/a"));

Checking for `driver.findElement(...)` in an IF statement throws `NoSuchElementException`

I'm getting NoSuchElementException when running the following code.
if (driver.findElement(By.xpath("//*[#id='gr2']")).isDisplayed()) {
Thread.sleep(5000);
driver.findElement(By.xpath("//*[#id='balInqTableStep2']/td/table/tbody/tr/td/table/tbody/tr[3]/td[4]/input[2]")).click();
}
else {
test.log(LogStatus.FAIL,"Please configure Gift Slabs for this site. Contact business.");
test.log(LogStatus.FAIL,"Second time wallet credit is not done");
}
NoSuchElementException exception means there is not element present on the page.
isDisplayed method assumes that element is already present on the page and so throws you exception when element is not present.
you can either make sure that element is present before calling webdriver method and you can write your own method to handle this for you.
following code snippet might help you
public boolean isDisplayed(By identifier){
boolean isElementDisplayed = false;
try{
WebElement element = driver.findElement(identifier);
isElementDisplayed = element.isDisplayed()
}catch (NoSuchElementException){
return false;
}
return isElementDisplayed;
}
and you can call it like this
isDisplayed(By.xpath("//*[#id='gr2']")
Always when you call driver.findElement(By.xpath("//*[#id='gr2']")) and the element is not present in the DOM, it's gonna throw a NoSuchElementException.
There is an alternative to avoid the code throwing the exception, calling the method findElements, instead of findElement.
E.g.:
List<WebElement> elements = driver.findElements(By.xpath("//*[#id='gr2']"));
if(!elements.isEmpty() && elements.get(0).isDisplayed()) {
Thread.sleep(5000);
driver.findElement(By.xpath("//*[#id='balInqTableStep2']/td/table/tbody/tr/td/table/tbody/tr[3]/td[4]/input[2]")).click();
}
else {
test.log(LogStatus.FAIL,"Please configure Gift Slabs for this site. Contact business.");
test.log(LogStatus.FAIL,"Second time wallet credit is not done");
}
Hope it works for you.

Selenium - webdriver Test if-else loop stuck/error

I am trying to fill up a dynamic from which is automatically generated with user info. So I want to set if else condition for field of the from. So i use if else loop in step defenition but suppose if condition true its ok the code excute but if "if condition fail the code stuck in else loop why.Please help
The code is below
#And("^Input Height in add report$")
public void Input_Height_in_add_report(DataTable newHeight) throws Throwable {
if(driver.findElement(By.xpath("//label//span[contains(text(),'Height')]")).isDisplayed()){
Thread.sleep(2000);
List<List<String>> data = newHeight.raw();
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[2]/form/div[7]/div[1]/div/div/input")).sendKeys(data.get(1).get(1));
}
else{
}
}
The problem is that if findElement finds the element it goes if statement but if it doenst find the element it gives NosuchElementFound exception. To handle this yo can use try-catch block to run code in the else, check the following:
#And("^Input Height in add report$")
public void Input_Height_in_add_report(DataTable newHeight) throws Throwable {
try {
if(driver.findElement(By.xpath("//label//span[contains(text(),'Height')]")).isDisplayed()){
Thread.sleep(2000);
List<List<String>> data = newHeight.raw();
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[2]/form/div[7]/div[1]/div/div/input")).sendKeys(data.get(1).get(1));
}
}
catch(Exception e) {
// your else code should be here
}
}

Selenium 2.0 WebDriver: Element is no longer attached to the DOM error using Java

I'm using the PageObject/PageFactory design pattern for my UI automation. Using Selenium 2.0 WebDriver, JAVA, I randomly get the error: org.openqa.selenium.StaleElementReferenceException: Element is no longer attached to the DOM, when I attempt logic like this:
#FindBy(how = HOW.ID, using = "item")
private List<WebElement> items
private void getItemThroughName(String name) {
wait(items);
for(int i = 0; i < items.size(); i++) {
try {
Thread.sleep(0500);
} catch (InterruptedException e) { }
this.wait(items);
if(items.get(i).getText().contains(name)) {
System.out.println("Found");
break;
}
}
}
The error randomly happens at the if statement line, as you can see I've tried a couple things to avoid this, like sleeping a small amount of time, or waiting for the element again, neither works 100% of the time
First if you really have multiple elements on the by with the ID of "item" you should log a bug or talk to the developers on the site to fix that. An ID is meant to be unique.
As comments on the question already implied you should use an ExplicitWait in this case:
private void getItemThroughName(String name) {
new WebDriverWait(driver, 30)
.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("id('item')[.='" + name + "']")
));
// A timeout exception will be thrown otherwise
System.out.println("Found");
}

Categories