Looping through with List<WebElement> with Selenium - java

I get a list of anchors using the code below, and then I want to go to each link. I have came up with the code below, but after the first loop I get the following exception
org.openqa.selenium.StaleElementReferenceException: stale element
reference: element is not attached to the page document (Session
info: chrome=55.0.2883.87)
List<WebElement> listingAnchorList = driver.findElements(By.xpath("//div[contains(#class,'cat')]/a"));
for (WebElement listingAnchor : listingAnchorList) {
driver.get(listingAnchor.getAttribute("href"));
System.out.println(driver.getTitle());
}
Is there anyway to do this without having go to back to the page every time?

You can collect your href attributes in some new List, and then iterate over it and open each page.

Related

Selenium Error : org.openqa.selenium.InvalidElementStateException: invalid element state

I am getting invalid element state when I try to clear element after click.
Following are operations I am doing on element:
inputField.click();
inputField.clear();
inputField.sendKeys("name");
The first step click is working fine, but clear is giving exception:
org.openqa.selenium.InvalidElementStateException: invalid element state
There is another test case, which calls the method which has above three steps and it works fine.What can be potential issue?
InvalidElementStateException
InvalidElementStateException implies that a WebElement is in a certain state when actions cannot be performed with it. One of the most frequently encountered examples would include an element being obscured by another when clicking, or perhaps not being visible on the HTML DOM.
This usecase
As you are trying to click(), clear() and sendKeys() within the WebElement ideally you need to induce WebDriverWait for the elementToBeClickable() and you can use the following solution:
WebElement inputField = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//elementXpath")));
inputField.click();
inputField.clear();
inputField.sendKeys("name");

Selenium can't find iframe after postback inside the iframe after finding one element inside the frame

I am trying to create a test where I have to fill out some information inside an iframe. Getting access to the iframe work fine and I can fill out information inside the frame. The issue is that when I find out a element 'A' it has a postback attached to it which reloads the content inside the iframe, to find out another element 'B'. So i am not able to find that element.I am getting below error:
org.openqa.selenium.WebDriverException: unknown error: Element <iframe style="overflow-x:hidden;" id="t5" height="1350" frameborder="0" width="98%" src="https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1&days=7" cd_frame_id_="7da8f2aea5a580b3a6e90a9d5016fa0d">...</iframe> is not clickable at point (554, 7). Other element would receive the click: <div class="topnav2014" style="border-bottom: none;">...</div>
(Session info: chrome=85.0.4183.83)
Here are my observations: When I first locate the iframe it looks like this:
<iframe style="overflow-x:hidden;" id="t5" height="1350" frameborder="0" width="98%" src="https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1&days=7">
After the postback has occurred it looks like this:
<iframe style="overflow-x:hidden;" id="t5" height="1350" frameborder="0" width="98%" src="https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1&days=7" cd_frame_id_="a5006acf28d8c288313681ab9ad7a4fa">
I can easily find element A:
But element B i am not able to find
The code fails when I try to get hold of the iframe element.
How can I get hold of the iframe again, after the postback inside the frame?
I have tried this suggestion also but it is not working
//Ensure that you are back to the base frame
driver.SwitchTo().DefaultContent();
//SwitchTo the intended frame
driver.SwitchTo().Frame(driver.FindElement(By.XPath("//iframe[contains(#src,'<removed for clearity>')]")));
Use a driver.executescript() for the first problem since another element is receiving the click.
element = driver.findElement(By.id(""));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();", element);
This error message...
org.openqa.selenium.WebDriverException: unknown error: Element <iframe style="overflow-x:hidden;" id="t5" height="1350" frameborder="0" width="98%" src="https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1&days=7" cd_frame_id_="7da8f2aea5a580b3a6e90a9d5016fa0d">...</iframe> is not clickable at point (554, 7). Other element would receive the click: <div class="topnav2014" style="border-bottom: none;">...</div>
(Session info: chrome=85.0.4183.83)
...implies that the WebDriverException was raised as you tried to invoke click() on the <iframe> element.
Factually, instead of clicking on the <iframe> element you would invoke click() on an element within the <iframe>. Moreover, as the the desired element is within a <iframe> so you have to:
Induce WebDriverWait for the desired frameToBeAvailableAndSwitchToIt.
Induce WebDriverWait for the desired elementToBeClickable.
You can use either of the following Locator Strategies:
Using xpath:
new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe_xpath")));
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("element_xpath"))).click();
References
You can find a couple of relevant discussions in:
Ways to deal with #document under iframe
Is it possible to switch to an element in a frame without using driver.switchTo().frame(“frameName”) in Selenium Webdriver Java?
I am able to extract the data of the active cases rise and fall for every state. There is a single frame which contains both the locators shared by you. Check below working code.
driver.get("https://www.ndtv.com/coronavirus");
driver.manage().window().maximize();
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(By.className("tab-wrapper")));
driver.switchTo().frame(driver.findElement(By.xpath("//iframe[contains(#src,'https://edata.ndtv.com/coronavirus/table/india_table.html?shgraph=1')]")));
//cases down
List<WebElement> eleCasesUp = driver.findElements(By.xpath("//tr//td[3]//p//span[#class='data-up']"));
List<String> casesUpList = new ArrayList<String>();
for (WebElement element : eleCasesUp) {
casesUpList.add(element.getText());
}
//cases up
List<WebElement> eleCasesDown = driver.findElements(By.xpath("//tr//td[3]//p//span[#class='data-down']"));
List<String> casesDownList = new ArrayList<String>();
for (WebElement element : eleCasesDown) {
casesDownList.add(element.getText());
}
System.out.println("Cases Up List -->" + casesUpList);
System.out.println("Cases Down List -->" + casesDownList);

Selenium - iterate over elements

My goal is:
Iterate on WebElements in a webpage
Click on all elements founded and open link in same session
Parse the new page with some other logic
Return back to prev page and continue the loop for all prev matched id
I have this code:
List<WebElement> links = driver.findElements(By.cssSelector("div[data-sigil='touchable']"));
// this will display list of all images exist on page
for(WebElement ele:links)
{
System.out.println("test->"+ele.getAttribute("id"));
ele.click();
Thread.sleep(500);
System.out.println("URI->"+driver.getCurrentUrl());
js.executeScript("window.history.go(-1)");
}
return "ok";
Which is working fine and it finds correct elements id, "ele.click()" is actually working, but I'm always failing when I execute js.executeScript("window.history.go(-1)")
This is my error message:
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
(Session info: chrome=73.0.3683.103)
(Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.17134 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 0 milliseconds
So basically I'm not able to continue the loop.
Is it there any useful technique to "click into new tab" and manage different Selenium driver session?
Thanks a lot in advance for any suggestion.
What is happening is that when you proceed to another page it makes all the elements in the list stale. Those elements are not attached to the page when you come back to the page again. You need to find the elements every time you load the page.
Try this:
List<WebElement> links = driver.findElements(By.cssSelector("div[data-sigil='touchable']"));
// this will display list of all images exist on page
String address;
for(int i=0; i<links.size(); i++){
address = driver.getCurrentUrl();
links = driver.findElements(By.cssSelector("div[data-sigil='touchable']"));
System.out.println("size: "+links.size());
WebElement ele = links.get(i);
System.out.println("test->"+ele.getAttribute("id"));
ele.click();
Thread.sleep(500);
System.out.println("URI->"+driver.getCurrentUrl());
//js.executeScript("window.history.go(-1)");
//driver.navigate().back();
driver.get(address);
}
Edit:
Try the driver.get() as it waits for the page to load. Or you can directly add another sleep as you used after the click.
I think you need to create the js object, like so.
Reason being that you "lost" the reference to the JavascriptExecutor
List<WebElement> links = driver.findElements(By.cssSelector("div[data-sigil='touchable']"));
// this will display list of all images exist on page
for(WebElement ele:links){
System.out.println("test->"+ele.getAttribute("id"));
ele.click();
Thread.sleep(500);
System.out.println("URI->"+driver.getCurrentUrl());
// Re initialise js executor
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.history.go(-1)");
}
return "ok";

StaleElementReferenceException when trying to click an element

I'm implementing a Selenium test using Java. But, my tests fail due to a StaleElementReferenceException.I am doing the following
driver.get(URL);
List<WebElement> Anchors = driver.findElements(By.xpath("//div[not(contains(#style,'display:none'))]/a"));
//same URL again
driver.get(URL);
Anchors.get(0).click();
When I try to click any element from the Anchors list I get an error.
Every time the DOM is changing or refreshing, even if you still in the same page, the driver "losses" the WebElements it previously located and you get StaleElementReferenceException. If you really need to use driver.get(URL); again before the click you need to relocate the list.

Selenium how to click on this kind of link

I'm having trouble with this particular link because is dynamic, it doesn't have an specefic name or id, but i know that all those links are inside a span with has a class. I try to get a list of WebElements to get all the spans with the class "more" to get the bunch of links inside but i get this error:
org.openqa.selenium.WebDriverException: Element is not clickable at point (96, 21). Other element would receive the click: <div class="priceFinderHeaderLogoWrap"></div>
this how the html code looks likes:
<span class="more">
<a onclick="setPID(27272);ta.fireEvent('hotels_lists_engagement_tracking.fired', {type: 'ReviewCount', element: this});ta.setEvtCookie('Reviews', 'ReviewCount', '1461750', 1, '/Hotel_Review');" target="_blank" href="/Hotel_Review-g150800-d1461750-Reviews-City_Express_Plus_Reforma_El_Angel-Mexico_City_Central_Mexico_and_Gulf_Coast.html#REVIEWS">254 opiniones</a></span>
my java code:
List<WebElement> links = driver.findElements(By.className("more"));
System.out.println(links.isEmpty());
for (int i = 0; i < links.size(); i++) {
links.get(i).click();
// do something in the web page...
}
Try this
List<WebElement> links = driver.findElements(By.XPath("//span[#class='more']/a"));
As per provided information, links are dynamic which is inside span with class as more. So in the code you tried
List<WebElement> links = driver.findElements(By.className("more"));
asking to load all span webelements but actually you need links right?
So if you need to load all links in particular span with class more then try like below
List<WebElement> links = driver.findElements(By.xpath("//span[#class='more']/a"));
provided that page contains unique span which you trying to get links.Then go for 'for' loop and click on link.
if you still get same issue, then use Actions to click on element. for example like below
for(int i=0; i<links.size(); i++){
new Actions(driver).moveToElement(links.get(i)).click().build().perform();
}
if your intention is to click on span as per code you tried then try Actions as above to get out of the exception.
Please make a note that there is chance of getting stealelement exception as you are performing click which may leads to page loads and driver loose its references to collected webelements in for loop.
Thank You,
Murali

Categories