I'm learning WebDriver and just trying to check the links on demoaut website. The code in the loop is supposed to recognize "Under Construction" page by its title, print out the first line, and then go back to base url. But that doesn't happen for some reason. The very first "under construction" link it gets to (featured vacation destinations) is not recognized as such, prompts the wrong line to be printed, and then instead of going back it crashes due to NoSuchElementException since it's looking for a link on the wrong page. Why is this happening? Why doesn't it act based on the title of "Under Construction" page?
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
public class CheckLinks {
public static void main(String[] args) {
String baseUrl = "http://newtours.demoaut.com/";
System.setProperty("webdriver.gecko.driver", "C:\\Workspace_e\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
String underConsTitle = "Under Construction: Mercury Tours";
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get(baseUrl);
List<WebElement> linkElements = driver.findElements(By.tagName("a"));
String[] linkTexts = new String[linkElements.size()];
int i = 0;
//extract the link texts of each link element
for (WebElement e : linkElements) {
linkTexts[i] = e.getText();
i++;
}
//test each link
for (String t : linkTexts) {
driver.findElement(By.linkText(t)).click();
if (driver.getTitle().equals(underConsTitle)) {
System.out.println("\"" + t + "\""
+ " is under construction.");
} else {
System.out.println("\"" + t + "\""
+ " is working.");
}
driver.navigate().back();
}
driver.quit();
}
}
After you click the first link, all the references in linkTexts will become stale... even if you return to the page. What you need to do is to store all the hrefs in a List and then navigate to each one and check the title of the page.
I would write it this way...
public class CheckLinks
{
public static void main(String[] args) throws UnsupportedFlavorException, IOException
{
String firefoxDriverPath = "C:\\Users\\Jeff\\Desktop\\branches\\Selenium\\lib\\geckodriver-v0.11.1-win32\\geckodriver.exe";
System.setProperty("webdriver.gecko.driver", firefoxDriverPath);
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
String baseUrl = "http://newtours.demoaut.com/";
driver.get(baseUrl);
List<WebElement> links = driver.findElements(By.tagName("a"));
List<String> hrefs = new ArrayList<>();
for (WebElement link : links)
{
hrefs.add(link.getAttribute("href"));
}
System.out.println(hrefs.size());
String underConsTitle = "Under Construction: Mercury Tours";
for (String href : hrefs)
{
driver.get(href);
System.out.print("\"" + href + "\"");
if (driver.getTitle().equals(underConsTitle))
{
System.out.println(" is under construction.");
}
else
{
System.out.println(" is working.");
}
}
driver.close();
driver.quit();
}
}
Your code works fine in my Chrome browser. Your problem could be the speed of the webdriver. You can use WebDriverWait which is an explicit wait for a particular element.
Try below modified code
for (String t : linkTexts) {
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.elementToBeClickable(driver.findElement(By.linkText(t))));
driver.findElement(By.linkText(t)).click();
if (driver.getTitle().equals(underConsTitle)) {
System.out.println("\"" + t + "\""
+ " is under construction.");
} else {
System.out.println("\"" + t + "\""
+ " is working.");
}
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
driver.navigate().back();
}
I am able to get the out as below
"Home" is working.
"Flights" is working.
"Hotels" is under construction.
"Car Rentals" is under construction.
"Cruises" is working.
"Destinations" is under construction.
"Vacations" is under construction.
"SIGN-ON" is working.
"REGISTER" is working.
"SUPPORT" is under construction.
"CONTACT" is under construction.
"your destination" is under construction.
"featured vacation destinations" is under construction.
"Register here" is working.
"Business Travel # About.com" is working.
"Salon Travel" is working.
I do not find anything wrong in your logic.Infact I copied your code and just replaced firefox driver with IE driver and it worked as expected.Below was the console output I got on running the code:
> Home" is working. "Flights" is working. "Hotels" is under
> construction. "Car Rentals" is under construction. "Cruises" is
> working. "Destinations" is under construction. "Vacations" is under
> construction. "SIGN-ON" is working. "REGISTER" is working. "SUPPORT"
> is under construction. "CONTACT" is under construction. "your
> destination" is under construction. "featured vacation destinations"
> is under construction. "Register here" is working. "Business Travel #
> About.com" is working.
Related
Below is the screenshot of the mouse hover event.
Style type
It is triggered only on mouse hover. Currently, I'm able to read the Style Type Text. I can select the first element without any issues, however, I'm unable to click the second and last element (Categorized and Graduated ).
UI Code for reference.
UI code
Below is the Selenium code for reference.
static void styletype() throws InterruptedException {
Thread.sleep(1000);
String sname = null;
// select style type
Actions action = new Actions(driver);
WebElement menu = driver.findElement(By.xpath("//*[#src = 'assets/images/down_arrow.svg']"));
action.moveToElement(menu).perform();
Thread.sleep(1500);
List<WebElement> rowsList = driver.findElements(By.xpath("//*[contains(#class,'dropdown-item')]"));
for (WebElement element : rowsList) {
try {
sname = element.getText();
// System.out.println("File Type is : " + sname);
int result = JOptionPane.showConfirmDialog(frame, "Layer Stype Type : '" + sname + "'",
"Do you want to continue", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == 0) {
element.click();
break;
}
action.moveToElement(menu).perform();
Thread.sleep(1000);
} catch (Exception e) {
}
}
}
Website: https://stores.lenskart.com/
In this website I want to list store name its address and mobile no
Below is my code which i tried.
public class fetchdata {
public void fetchbengaluru() {
suites.setupEnviroment();
WebDriver driver = suites.getWebDriver();
List<WebElement> div1 = driver.findElements(By.xpath("//div[#class='border-manage store-info-box']"));
System.out.println("No. of Stores: " + div1.size());
try {
for (int i = 0; i < div1.size(); i++) {
String storename = div1.get(i).findElement(By.xpath("//div[#class='store_name']")).getText();
System.out.println("Store Name" + storename);
}
} catch (Exception e) {
System.out.println(e);
}
}
}
In above code i am getting total no of store as 20 but not able to list their names and mobile no.
Element not found message is displayed
As per my understanding i am not able to locate the element because its coming under ul-li and a tag
Try the below code, we need to select Xpath in correct fashion to populate the data.
driver.get("https://stores.lenskart.com/");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.findElementById("OutletSearch").sendKeys("Chennai", Keys.ENTER);
List<WebElement> storedetails = driver.findElementsByXPath("//a[#title='Lenskart.com']/b");
int storecount = storedetails.size();
System.out.println(storecount);
for(int i=1;i<=storecount;i++) {
String storename = driver.findElementByXPath("//div[#class='border-manage store-info-box']["+i+"]/ul//b").getText();
String storephonenumber = driver.findElementByXPath("//div[#class='border-manage store-info-box']["+i+"]/ul/li[6]").getText();
System.out.println(storename + " : "+storephonenumber.substring(0, 13));
}
Output will be as follows
Lenskart.com at Purasawalkam : +91******
Lenskart.com at Nungambakkam : +91******
Lenskart.com at Tondiarpet : +91******
Lenskart.com at Royapuram : +91******
Lenskart.com at Mylapore : +91******
You can simply store it in list and print the elements one by one with the help of for loop.
I am getting the "total" as total=address.size() only once as it will be same for all the 3 elements and then printing all the value.
package newproj;
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;
public class Lenskart {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
String url="https://stores.lenskart.com";
System.setProperty("webdriver.chrome.driver", "D:\\Selenium\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get(url);
driver.manage().window().maximize();
Thread.sleep(5000);
List<WebElement> name=driver.findElements(By.xpath("//li[#class='store_name redirectHome']"));
List<WebElement> address=driver.findElements(By.xpath("//li[#class='store_address redirectHome']"));
List<WebElement> phone=driver.findElements(By.xpath("//li[#class='store_phone']"));
int total=address.size();
for(int i=0;i<total;i++)
{
System.out.println("\n");
System.out.println("New address="+i);
System.out.println(name.get(i).getText());
System.out.println(address.get(i).getText());
System.out.println(phone.get(i).getText());
System.out.println("\n");
}
driver.close();
}
}
Output will be in this pattern.
New address=0
Lenskart.com at Science City Road, Sola
Shop No 01, Ground Floor, Royal Square
Science City Road, Sola
Ahmedabad - 380060
+917428891186
CALL
New address=1
Lenskart.com at Gurukul Road, Memnagar
Shop No 1, Shilp Complex
Gurukul Road, Memnagar
Ahmedabad - 380052
+917428891192
CALL
....
and so on.
.
I hope it helps.
Hello i am trying to automate some process here . i am using 2captch to solve captcha , please check out image .
I have got site_key and api_key , now i am sending api_key + site_key and it is returning me response_token, i have added returned response token into g-recaptcha-response but it is not submitting form.
what i want is that : i can solve captcha and submit form .
Here is my current java code :
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
ChromeDriver driver;
driver = new ChromeDriver();
driver.manage().deleteAllCookies();
driver.manage().window().maximize();
driver.get("https://id.sonyentertainmentnetwork.com/signin/?client_id=fe1fdbfa-f1a1-47ac-b793-e648fba25e86&redirect_uri=https://secure.eu.playstation.com/psnauth/PSNOAUTHResponse/pdc/&service_entity=urn:service-entity:psn&response_type=code&scope=psn:s2s&ui=pr&service_logo=ps&request_locale=en_GB&error=login_required&error_code=4165&error_description=User+is+not+authenticated&no_captcha=false#/signin?entry=%2Fsignin");
Thread.sleep(5000);
driver.findElement(By.xpath("//input[#title='Sign-In ID (Email Address)']")).sendKeys("email");
Thread.sleep(2000);
driver.findElement(By.xpath("//input[#title='Password']")).sendKeys("password");
Thread.sleep(2000);
driver.findElement(By.xpath("//button[#class='primary-button row-button text-button touch-feedback']")).click();
Thread.sleep(3000);
By captcha = By.xpath("//iframe[#title='recaptcha challenge']");
String src = driver.findElement(captcha).getAttribute("src");
String key = getKey(src);
System.out.println(key);
String apiKey = "API_KEY";
String googleKey = key;
String pageUrl = "https://id.sonyentertainmentnetwork.com/signin/?client_id=fe1fdbfa-f1a1-47ac-b793-e648fba25e86&redirect_uri=https://secure.eu.playstation.com/psnauth/PSNOAUTHResponse/pdc/&service_entity=urn:service-entity:psn&response_type=code&scope=psn:s2s&ui=pr&service_logo=ps&request_locale=en_GB&error=login_required&error_code=4165&error_description=User+is+not+authenticated&no_captcha=false#/signin?entry=%2Fsignin";
String proxyIp = "183.38.231.131";
String proxyPort = "8888";
String proxyUser = "username";
String proxyPw = "password";
TwoCaptchaService service = new TwoCaptchaService(apiKey, googleKey, pageUrl, proxyIp, proxyPort, proxyUser, proxyPw, ProxyType.HTTP);
try {
String responseToken = service.solveCaptcha();
System.out.println("The response token is: " + responseToken);
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("document.getElementById(\"g-recaptcha-response\").innerHTML = \'"+responseToken+"\';");
} catch (InterruptedException e) {
System.out.println("ERROR case 1");
e.printStackTrace();
} catch (IOException e) {
System.out.println("ERROR case 2");
e.printStackTrace();
}
UPDATED CODE :
js.executeScript("document.getElementById(\"g-recaptcha-response\").innerHTML = \'" + responseToken + "\';");
Thread.sleep(500);
WebElement frameElement = driver.findElement(captcha);
driver.switchTo().frame(frameElement);
js.executeScript("document.getElementById('recaptcha-verify-button').click();");
it is clicking on button but , it shows Please select all matching images.
. please check out screenshot
All you need to do is submit it like this:
js.executeScript("document.getElementById('g-recaptcha-response').innerHTML='" + responseToken + "';");
Thread.sleep(500);
js.executeScript("document.getElementById('captcha-form').submit();");
also don't forget to check this ID : "captcha-form", it can be different
To reach to element "recaptcha-verify-button":
After you got the response from the API;
By frame = By.xpath("//iframe[#title='recaptcha challenge']");
WebElement frameElement = driver.findElement(frame);
driver.switchTo.frame(frameElement);
then you can execute your script. Finally, for your script if your captcha form is a button
you
cannot call submit();
you
can call click();
Final Answer:
Also check this: js.executeScript("widgetVerified('TOKEN');");
To find the function called widgetVerified() please run this code in the console.
___grecaptcha_cfg.clients[0]
this will return a json, inside of that json try to find the callback function in #Awais case it was wigdetVerified(e)
Warn : Don't use any adblocker
This question already has answers here:
Getting StaleElementReferenceException while trying print the link names
(3 answers)
Selenium Webdriver - Stale element exception when clicking on multiple dropdowns while HTML DOM doesn't change
(1 answer)
StaleElementReference Exception in PageFactory
(3 answers)
Closed 4 years ago.
I have try all available solving
WebDriverWait wait6 = new WebDriverWait(driver, 500);
wait6 .until(ExpectedConditions.presenceOfElementLocated(By.xpath("(//i[#class='material-icons'])[" + j + "]")));
I have application where I need to click on all item and get text of item name I am get Stale Element Reference Exception.
I have try to put different method to resolve it but nothing working.
public void page(WebDriver driver, String Filtername) throws InterruptedException {
waitForElementPresent(driver, 60, sidenavbutton);
click(driver, sidenavbutton);
Thread.sleep(2000);
click(driver, viewcopyportfolio);
Thread.sleep(1000);
click(driver, sidenavbutton);
waitForElementPresent(driver, 30, porfoliosheader);
clearText(driver, pagenumtextbox);
Thread.sleep(1000);
setText(driver, pagenumtextbox, Filtername);
Thread.sleep(1000);
List<WebElement> editicons1 = driver.findElements(By.xpath("//i[#class='material-icons']"));
for (int j = 1; j <= editicons1.size(); j++) {
editicons1 = driver.findElements(By.xpath("//i[#class='material-icons']"));
String porfolioName = driver.findElement(By.xpath("(//mat-table//mat-row)[" + j + "]//mat-cell[2]")).getText();
//Added to fix Stale Element Exception
WebElement editicon = driver.findElement(By.xpath("(//i[#class='material-icons'])[" + j + "]"));
//In click method attached code below this will loop for 5 times
click1(driver, editicon, porfolioName + " portfolio edit icon");
Thread.sleep(1000);
waitForElementPresent(driver, 30, buildportfolioheader);
}
}
This code for click1 method
public void click1(WebDriver driver, WebElement element, String name) throws InterruptedException {
int attempts = 0;
while(attempts < 5) {
try {
element.click();
Add_Log.info("Successfully clicked on " + name);
Reporter.log("Successfully clicked on " + name);
return;
} catch (Exception e) {
attempts++;
Thread.sleep(500);
try {
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].click();", element);
Add_Log.info("Successfully clicked on " + name);
Reporter.log("Successfully clicked on " + name);
return;
} catch (Exception e2) {
Add_Log.info("Not able to click " + name);
Reporter.log("Not able to click " + name);
TestResultStatus.Testfail = true;
Assert.fail("Not able to click " + name);
}
}
}
}
" editicons1 = driver.findElements(By.xpath("//i[#class='material-icons']"));" This line in the loop doesn't look like it's needed, you just wanted the initial count, I don't see a reason to re load the list of elements.
The problem with this wait logic is that if the element already exists it will just sleep a second, see that the element is there and then continue, and from what I've seen, the next page could then start loading and then your script will be in a world of hurt.
Thread.sleep(1000);
waitForElementPresent(driver, 30, buildportfolioheader);
IF the element isn't already on the page, I would swap the explicit wait to come first. The reason for that is that presence of an element doesn't really mean a whole lot, the page could still be in motion, so a little bit of a sleep after the explicit wait (assuming this is one of the last elements to appear on the page) usually stabilizes flakey scripts.
waitForElementPresent(driver, 30, buildportfolioheader);
Thread.sleep(1000);
I am using Selenium WebDriver with java.
I am fetching all links from webpage and trying to click each link one by one. I am getting below error:
error org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up
Command duration or timeout: 30.01 seconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html
Build info: version: '2.25.0', revision: '17482', time: '2012-07-18 21:09:54'
and here is my code :
public void getLinks()throws Exception{
try {
List<WebElement> links = driver.findElements(By.tagName("a"));
int linkcount = links.size();
System.out.println(links.size());
for (WebElement myElement : links){
String link = myElement.getText();
System.out.println(link);
System.out.println(myElement);
if (link !=""){
myElement.click();
Thread.sleep(2000);
System.out.println("third");
}
//Thread.sleep(5000);
}
}catch (Exception e){
System.out.println("error "+e);
}
}
actually, it's displaying in output
[[FirefoxDriver: firefox on XP (ce0da229-f77b-4fb8-b017-df517845fa78)] -> tag name: a]
as link, I want to eliminate these form result.
There is no such a good idea to have following scenario :
for (WebElement element : webDriver.findElements(locator.getBy())){
element.click();
}
Why? Because there is no guarantee that the element.click(); will have no effect on other found elements, so the DOM may be changed, so hence the StaleElementReferenceException.
It is better to use the following scenario :
int numberOfElementsFound = getNumberOfElementsFound(locator);
for (int pos = 0; pos < numberOfElementsFound; pos++) {
getElementWithIndex(locator, pos).click();
}
This is better because you will always take the WebElement refreshed, even the previous click had some effects on it.
EDIT : Example added
public int getNumberOfElementsFound(By by) {
return webDriver.findElements(by).size();
}
public WebElement getElementWithIndex(By by, int pos) {
return webDriver.findElements(by).get(pos);
}
Hope to be enough.
Credit goes to "loan".
I am also getting "stale exception" so I used 'loan' answer and works perfectly. Just if anyone need to know how to click on each link from results page try this (java)
clickAllHyperLinksByTagName("h3"); where "h3" tag contains hyperlink
public static void clickAllHyperLinksByTagName(String tagName){
int numberOfElementsFound = getNumberOfElementsFound(By.tagName(tagName));
System.out.println(numberOfElementsFound);
for (int pos = 0; pos < numberOfElementsFound; pos++) {
getElementWithIndex(By.tagName(tagName), pos).click();
driver.navigate().back();
}
}
public static int getNumberOfElementsFound(By by) {
return driver.findElements(by).size();
}
public static WebElement getElementWithIndex(By by, int pos) {
return driver.findElements(by).get(pos);
}
WebDriver _driver = new InternetExplorerDriver();
_driver.navigate().to("http://www.google.co.in/");
List <WebElement> alllinks = _driver.findElements(By.tagName("a"));
for(int i=0;i<alllinks.size();i++)
System.out.println(alllinks.get(i).getText());
for(int i=0;i<alllinks.size();i++){
alllinks.get(i).click();
_driver.navigate().back();
}
If you're OK using WebDriver.get() instead of WebElement.click() to test the links, an alternate approach is to save the href value of each found WebElement in a separate list. This way you avoid the StaleElementReferenceException because you're not trying to reuse subsequent WebElements after navigating away with the first WebElement.click().
Basic example:
List<String> hrefs = new ArrayList<String>();
List<WebElement> anchors = driver.findElements(By.tagName("a"));
for ( WebElement anchor : anchors ) {
hrefs.add(anchor.getAttribute("href"));
}
for ( String href : hrefs ) {
driver.get(href);
}
//extract the link texts of each link element
for (WebElement elements : linkElements) {
linkTexts[i] = elements.getText();
i++;
}
//test each link
for (String t : linkTexts) {
driver.findElement(By.linkText(t)).click();
if (driver.getTitle().equals(notWorkingUrlTitle )) {
System.out.println("\"" + t + "\""
+ " is not working.");
} else {
System.out.println("\"" + t + "\""
+ " is working.");
}
driver.navigate().back();
}
driver.quit();
}
For complete Explanation Read This POST
List <WebElement> links = driver.findElements(By.tagName("a"));
int linkCount=links.size();
System.out.println("Total number of page on the webpage:"+ linkCount);
String[] texts=new String[linkCount];
int t=0;
for (WebElement text:links){
texts[t]=text.getText();//extract text from link and put in Array
//System.out.println(texts[t]);
t++;
}
for (String clicks:texts) {
driver.findElement(By.linkText(clicks)).click();
if (driver.getTitle().equals("notWorkingUrlTitle" )) {
System.out.println("\"" + t + "\""
+ " is not working.");
} else {
System.out.println("\"" + t + "\""
+ " is working.");
}
driver.navigate().back();
}
driver.quit();