StaleElementReferenceException when trying to reidentify the object - selenium

I am facing problem to identify the object when i move forward and comeback to parent page.
Here is the scenario. I would like to click on each link in a home page and print page title and navigate back to home page.
Following is the code which i tried. It works fine clicking on the first link and coming back to HomePage. At this point of time, the List Object needs to be identified excluding already visited links. How to do that?
In QTP, we have RefreshObject and Init to do this. Is there a similar method in WebDriver?
WebDriver driver = new FirefoxDriver();
driver.get("http://www.googl.com/");
driver.manage().window().maximize();
List<WebElement> objWEs = driver.findElements(By.tagName("a"));
for(WebElement e:objWEs)
{
if(!e.getText().isEmpty())
{
e.click();
System.out.println(driver.getTitle());
driver.navigate().back();
}
}
driver.close();

As soon as you navigate to another web-page, or even switch into an iframe in the same web-page, any WebElement object that you have in memory is potentially "stale".
One optional solution, is to list down all the element IDs, and then iterate that list instead:
Set<String> linkIds = new HashSet<String>();
List<WebElement> links = driver.findElements(By.tagName("a"));
for (WebElement link : links)
{
if(!link.getText().isEmpty())
linkIds.add(link.getAttribute("id"));
}
for (String linkId : linkIds)
{
driver.findElement(By.id(linkId)).click();
System.out.println(driver.getTitle());
driver.navigate().back();
}
Please note, however, that all the above is under the assumption that each link has a unique ID, and that all the links remain in the web-page when you navigate back into it. If this is not the case in the specific web-page that you are accessing, then an alternative approach is required here.
Instead of iterating the link-IDs, you can iterate the link-indexes, assuming that the links remain in the same order when you navigate in and out of the web-page. This is somewhat less efficient though, because you have to retrieve the entire list of all the links at the beginning of each iteration.
for (int i=0; true; i++)
{
List<WebElement> links = driver.findElements(By.tagName("a"));
if (i >= links.size())
break;
links.get(i).click();
System.out.println(driver.getTitle());
driver.navigate().back();
}
The code above should work even if the links do not remain in the same order when you navigate back into the web-page. However, under such scenario, you will most likely miss out on some of them.

Here is the complete code for my above problem.
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(1, TimeUnit.MINUTES);
driver.get("http://www.googl.com/");
driver.manage().window().maximize();
for (int i=0; true; i++)
{
List<WebElement> links = driver.findElements(By.tagName("a"));
if (i >= links.size())
break;
WebElement ele=links.get(i);
if(!ele.getText().isEmpty())
{
ele.click();
System.out.println(driver.getTitle());
driver.navigate().back();
}
}
driver.close();

Related

clicking multiple links on a given webpage to open them in a new tab gives error

I'm trying to open each link on the given web page in a new tab But by clicking two links, it throws this error. Any suggestions would help. Thanks.
Here is my code:
public class FirstClass {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver",
"chromedriver");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().deleteAllCookies();
driver.get("https://www.google.com/");
Actions action = new Actions(driver);
List<WebElement> web = driver.findElements(By.tagName("a"));
for (int i = 1; i < web.size(); i++) {
System.out.println(web.get(i).getText());
action.moveToElement(web.get(i)).keyDown(Keys.CONTROL).click().build().perform();
}
}
}
Here is an error which I got -
Exception in thread "main" org.openqa.selenium.JavascriptException: javascript error: Failed to execute 'elementsFromPoint' on 'Document': The provided double value is non-finite.
The code fails as some of the links in the Google Webpage are not displayed and can only be seen when certain actions are performed. The first link which results in failure of the code is "Report inappropriate predictions" link which can be seen when one clicks on the search bar.
To handle these links, one needs to traverse through the DOM when things get tricky. So, I added a JavaScriptExecutor to the code which comes into picture when a given link is not displayed.
Please use the below-mentioned code to open every link in the Google HomePage:
System.setProperty("webdriver.chrome.driver", "chromedriver");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().deleteAllCookies();
driver.get("https://www.google.com/");
Actions action = new Actions(driver);
List<WebElement> web = driver.findElements(By.tagName("a"));
for (int i = 0; i < web.size(); i++) {
if(web.get(i).isDisplayed()){
action.moveToElement(web.get(i)).keyDown(Keys.CONTROL).click().build().perform();
}else{
String url = web.get(i).getAttribute("href");
((JavascriptExecutor)driver).executeScript("window.open('" + url + "', '_blank');");
}
}
Hope this helps.

Send keys not working , right xpath and id (Selenium)

Tried sendomg keys , right relative xpath or ID used but still not working properly
Tried using absolute xpath , relative xpath also ID. Tried using selassist and chropath still not working. Could there be something preventing it?
public void LoginWebSystem() {
driver = new ChromeDriver();
driver.get("http://localhost:82");
WebElement email = driver.findElement(By.id("login_username"));
email.sendKeys("superadmin");
System.out.println("Username Set");
WebElement password = driver.findElement(By.id("login_password"));
password.sendKeys("nelsoft121586");
System.out.println("Password Set");
WebElement login = driver.findElement(By.id("login_submit"));
login.click();
System.out.println("Login Button Clicked");
String newUrl = driver.getCurrentUrl();
if(newUrl.equalsIgnoreCase("http://localhost:82/controlpanel.php")){
System.out.println("Login Success");
}
else {
System.out.println("Login Failed");
}
driver.findElement(By.partialLinkText("Product")).click();
System.out.println("Successful in proceeding to Product Page");
driver.findElement(By.id("createlink")).click();
System.out.println("Successful in proceeding to Create Product by Detailed");
driver.switchTo().alert().accept();
System.out.println("Successful in clicking alert button");
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
}
#Test (priority=1)
public void ProductDetails() {
WebElement product = driver.findElement(By.xpath(" //*[#id="text-product"]"));
product.sendKeys("superadmin");
}
}
Expected output should input superadmin to product textbox
You have a typo in your XPath expression:
WebElement product = driver.findElement(By.xpath(" //*[#id="text-product"]"));
^ remove this space break
It's better to use By.Id locator strategy where possible as this is the fastest and the most robust way of identifying elements in DOM
Consider using Explicit Wait to ensure that the element is present and can be interacted with as it might be the case the element becomes available after document.readyState becomes complete. Check out How to use Selenium to test web applications using AJAX technology article for more detailed explanation.
new WebDriverWait(driver, 10)
.until(ExpectedConditions.elementToBeClickable(By.id("text-product")))
.click();
Make sure that your selector matches an <input> because if the id belongs to other element type like <div> it doesn't make a lot of sense to send keys there.

Scrolling Google results using Selenium WebDriver 3.4.0

I am not able to scroll Google's results page to the end. Could anyone give me pointers on the below code 1. Tried to do using JS by the following
(a)j.executeScript("window.scrollTo(0,500)")
(b)j.executeScript("window.scrollBy(250,350)")
(c)j.executeScript("window.scrollTo(0,document.documentElement.scrollHeight")**
WebDriver driver = new ChromeDriver();
driver.navigate().to("https://www.google.com");
driver.manage().window().maximize();
// Google News
driver.findElement(By.id("lst-ib")).click();
driver.findElement(By.id("lst-ib")).sendKeys("News");
driver.findElement(By.id("lst-ib")).sendKeys(Keys.RETURN);
Thread.sleep(2000);
driver.findElement(By.xpath("//div[#class='rc']//a")).click();
Thread.sleep(4000);
JavascriptExecutor j = (JavascriptExecutor)driver;
for(int i=1;i<=3;i++)
{
j.executeScript("window.scrollTo(0,500)");
}
}
}
Use this:
((JavascriptExecutor) driver).executeScript("window.scrollBy(0,250)");
Scroll to particular element
js.executeScript("arguments[0].scrollIntoView(true);",element);
Here element is your Webelement from where you wanted to scroll
or you can use Robot class
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_PAGE_DOWN);
robot.keyRelease(KeyEvent.VK_PAGE_DOWN);
Change below code
for(var i=1;i<=3;i++)
{
j.executeScript("window.scrollTo(0,500)");
}
to
for(int i=1;i<=3;i++)
{
j.executeScript("window.scrollTo(0, arguments[0]*500)", i);
}
And it should work. 500 that you used is absolute value and not a delta for scroll. Or else use scrollBy
for(int i=1;i<=3;i++)
{
j.executeScript("window.scrollBy(0,500)");
}
j.executeScript("window.scrollBy(0,250)", "");
OR, you can do as follows:
j.executeScript("scroll(0, 250);");

Getting Exception : Element not found in the cache - perhaps the page has changed since it was looked up

I am reaching to a page after clicking on a link.I have not clicking anything on that page yet. Still, As soon as the page loaded it throws an error:
Element not found in the cache - perhaps the page has changed since it was looked up
List<WebElement> securityGroup = driver.findElements(By.cssSelector("td[class='button-col']>a:nth-of-type(2)"));
System.out.println(securityGroup.size());
Thread.sleep(5000);
for(WebElement link:securityGroup) {
String b= link.getAttribute("href");
boolean a= b.contains(data0);
if(a){
System.out.println(b);
Thread.sleep(5000);
System.out.println("before clicking link");
link.click();
//After this new page opens and above error comes.**
}else {
System.out.println("No match found");
}
}
Thread.sleep(5000);
Select sel = new Select(driver.findElement(By.xpath("//select[#name='groupId']")));
System.out.println(sel.getOptions().toString());
sel.selectByValue("TEST");
This is because of the for loop.
You are finding the securityGroup which is a list and you are iterating through the list. In this for loop, you look for a condition and if yes you proceed to click on the link. But the issue here is that the list iteration is not complete and the for loop continues. But it wont find the String b= link.getAttribute("href"); of the next iteration because you are on a new page.
Use a break to break the loop once the condition is satisfied.
if(a){
System.out.println(b);
Thread.sleep(5000);
System.out.println("before clicking link");
link.click();
break;
}else {
System.out.println("No match found");
}
there is not enough time to load the page and take the element:
driver.findElement(By.xpath("//select[#name='groupId']"))
try to do ImplicitlyWait after you init the driver
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
and Thread.sleep(5000); is bad idea using with selenium, for waiting you have selenium methods
When you click on link and redirected to another page the driver looses securityGroup. That's what causing the exception.
You need to relocate securityGroup each itreation
List<WebElement> securityGroup = driver.findElements(By.cssSelector("td[class='button-col']>a:nth-of-type(2)"));
int size = securityGroup.size();
for (int i = 0 ; i < size ; ++i) {
securityGroup = driver.findElements(By.cssSelector("td[class='button-col']>a:nth-of-type(2)"));
WebElement link = securityGroup.get(i);
String b = link.getAttribute("href");
boolean a = b.contains(data0);
if(a) {
System.out.println(b);
Thread.sleep(5000);
System.out.println("before clicking link");
link.click();
}
else {
System.out.println("No match found");
}
}

How to locate search links in google in Selenium for testing

I am trying to search Google for Selenium, then run down the list of links by clicking each one, printing the page title, then navigating back.
List<WebElement> linkElements = driver.findElements( **<insert code here>** );
for(WebElement elem: linkElements)
{
String text = elem.getText();
driver.findElement(By.linkText(text)).click();
System.out.println("Title of link\t:\t" + driver.getTitle());
driver.navigate().back();
}
To find the elements, I have tried By.tagName("a") which doesn't work because it gets ALL the links, not just the search ones. Using Firebug, I see that each search link has a class of r used on the header h3, and the a tag nested inside it.
See the following:
<h3 class="r">
<a href="/url sa=t&rct=j&q=selenium&source=web&cd=1&cad=rja&ved=0CC8QFjAA&url=http%3A%2F%2Fseleniumhq.org%2F&ei=y4eNUYiIGuS7iwL-r4DADA&usg=AFQjCNHCelhj_BWssRX2H0HZCcPqhgBrRg&sig2=WBhmm65gCH7RQxIv9vgrug&bvm=bv.46340616,d.cGE" onmousedown="return rwt(this,'','','','1','AFQjCNHCelhj_BWssRX2H0HZCcPqhgBrRg','WBhmm65gCH7RQxIv9vgrug','0CC8QFjAA','','',event)"><em>Selenium</em> - Web Browser Automation
</a></h3>
What code can I insert to make this work?
You have a lot of solution for doing it. There's mine. You keep your way like
// You get all links in a list
List<WebElement> linkElements = driver.findElements(By.xpath("//h3/a"));
// for each element(link) you click() on it
for(WebElement elem: linkElements)
{
elem.click();
// i suggest to put a wait right there
System.out.println("Title of link\t:\t" + driver.getTitle());
driver.navigate().back();
}
i don't know why you were trying to complicate with getText() etc.
Try below New Code
WebDriver driver;
driver = new FirefoxDriver();
driver.get("http://www.google.com");
driver.findElement(By.id("gbqfq")).sendKeys("Selenium");
Thread.sleep(1500L);
driver.findElement(By.id("gbqfb")).click();
Thread.sleep(1500L);
List<WebElement> linkElements = driver.findElements(By.xpath("//h3[#class='r']/a"));
for(int i=0;i<=linkElements.size();i++)
{
String text = linkElements.get(i).getText();
driver.findElement(By.linkText(text)).click();
Thread.sleep(2000L);
System.out.println("Title of link\t:\t" + driver.getTitle());
Thread.sleep(2000L);
driver.navigate().back();
linkElements = driver.findElements(By.xpath("//h3[#class='r']/a"));
}
try searching for this selector:
'.g:nth-child('+clickPosition+') h3.r a'
where "clickPosition" is the SERP result array key. Careful though, google now implements an "onmousedown" event that will change the href attribute to their redirect.