Scenario: Open website, obtain a reference to Webelement "About" , click About , navigate back and use the variable reference again -- Results in StaleElementReference Exception. This happens only with Selenium Java, however when using Watir, it works fine. Both the code snippets are posted below. Anyone got a damn clue what is going on ?
# Below Java code produces StaleElementReferenceException
public class StaleElementException {
public static void main(String[] args) {
ChromeDriver driver = new ChromeDriver();
driver.get("http://seleniumframework.com");
WebElement about = driver.findElementByLinkText("ABOUT");
System.out.println(about.getText());
about.click();
driver.navigate().back();
System.out.println(about.getText());
}
}
#Below Ruby Watir Code works fine
require 'watir-webdriver'
#browser = Watir::Browser.new :chrome
#browser.goto "http://seleniumframework.com"
about = #browser.link(text: 'ABOUT')
puts about.text
about.click
#browser.back
puts about.text
Watir automatically does another find element call after the refresh, which webdriver does not do, so you need to do what Saifur suggested.
I am not sure how Watir works here. But if you find an element click on it it navigates you to a different page and the DOM refreshes. You therefore going back with driver.navigate().back(); and try to use same about element to perform your action which is not valid anymore. The DOM refreshed means the reference to the element is lost and that's not a valid element anymore. What you should be doing is finding the same element again on the fly and perform your action. The complete code should look like the following:
public class StaleElementException {
public static void main(String[] args) {
ChromeDriver driver = new ChromeDriver();
driver.get("http://seleniumframework.com");
WebElement about = driver.findElementByLinkText("ABOUT");
System.out.println(about.getText());
about.click();
driver.navigate().back();
System.out.println(driver.findElementByLinkText("ABOUT").getText());
}
}
Note: The change in last line
Related
I am trying to click on cart icon on top right corner from Appium in chrome browser mobile.
Code to click :
driver.findElement(By.xpath("//a[#href='/viewcart']")).click();
URL : https://www.2gud.com/?cmpid=2G108229
Note: Please open this URL in mobile device and verify.
Error : Code is clicking somewhere else on mobile device.
This is working. Checked in Android 7.1 emulator
driver.findElement(By.xpath("//a[#href='/rv/viewcart']")).click();
public class Demo {
public static WebDriver driver = null;
public static void main(String args[]) throws InterruptedException {
System.out.println("Launching the chrome driver ");
System.setProperty("webdriver.chrome.driver","src\\test\\resources\\drivers\\chromedriver40.exe");
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("androidPackage", "com.android.chrome");
driver = new ChromeDriver(options);
driver.manage().timeouts().pageLoadTimeout(20,TimeUnit.SECONDS);
driver.get("https://www.2gud.com/?cmpid=2G108229");
Thread.sleep(3000);
driver.findElement(By.xpath("//a[#href='/rv/viewcart']")).click();
Thread.sleep(3000);
System.out.println(driver.getTitle());
driver.quit();
}
Try to click using mouse actions or JavaScript executor.
Try using the following code.
Xpath to find the view cart: //a[contains(#href,'viewcart')]
Executing a click via JavaScript has some behaviors of which you should be aware. If, for example, the code bound to the onclick event of your element invokes window.alert(), you may find your Selenium code hanging, depending on the implementation of the browser driver. That said, you can use the JavascriptExecutor class to do this. My solution differs from others proposed, however, in that you can still use the WebDriver methods for locating the elements.
// Assume driver is a valid WebDriver instance that has been properly instantiated elsewhere.
WebElement viewCart = driver.findElement(By.xpath("//a[contains(#href,'viewcart')]"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", viewCart);
You should also note that you might be better off using the click() method of the WebElement interface, but disabling native events before instantiating your driver. This would accomplish the same goal (with the same potential limitations), but not force you to write and maintain your own JavaScript.
I am working for a mouse hover and i want to test all the links working condition by clicking each and every link using for loop.In my program the iteration is going once and for the next iteration it is not working and showing the "StaleElementReferenceException"..........
Please do modification in the code if required....
public static void main(String[] args) throws IOException
{
WebDriver driver = new FirefoxDriver();
Autoit.Authenti(driver);
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(20,TimeUnit.SECONDS);
driver.get("http://staging.zenrays.com");
Actions a1=new Actions(driver);
WebElement cl=driver.findElement(By.xpath(".//*[#id='menu-450-2']/a"));
a1.moveToElement(cl).perform();
WebDriverWait wait =new WebDriverWait(driver, 30);
List<WebElement> links=driver.findElements(By.xpath("//a[contains(#class,'sf-depth-2')]"));
for(int i=0;i<=links.size()-1;i++)
{
links.get(i).click();
driver.navigate().back();
}
}
}
Understand one fundamental thing: staleElementReferenceException, by it's name suggests that the reference to your elements on the page is stale (lost). You just have to refer to those elements again, if they are available, which is apt in this case as the page has been refreshed. Do 2 things:
once the page is refreshed (when you navigate back), use an explicit wait until an element you expect is visible
Then, newly refer to your elements(xpath locator that you have used) you wanna work with again
As a clean and elegant code use try-catch block in these scenarios
I'm not gonna give you the code directly:)Try it and come back with your code.
Refer here
for it's clear explanation of possible scenarios for this particular exception
One more thing: Your for loop gives IndexOutOfBoundsException. Modify that as well
You can use following modification in your code:-
List<WebElement> links=driver.findElements(By.xpath("//a[contains(#class,'sf-depth-2')]"));
for(int i=0;i<links.size();i++)
{
List<WebElement> allLinks=driver.findElements(By.xpath("//a[contains(#class,'sf-depth-2')]"));
allLinks.get(i).click();
driver.navigate().back();
}
I am trying to type a string in capital letters (using KeyDown) into amazon.in website search bar using sendKeys() but I don't see the text on the search bar. I don't see any error. I use debug mode then I also I can find any error.
Question:
How can I resolve this?
How can I debug it myself and find issue?
For debug I put a breakpoint on below line and then use step over option to run each line.
mouseAction.moveToElement(elementLocation).build().perform();
public class MouseActions {
public static void main (String [] args){
System.setProperty ("webdriver.chrome.driver","C:\\Users\\tokci\\Documents\\Selenium\\drivers\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.amazon.in/");
Actions mouseAction = new Actions(driver);
//this mouse action works
WebElement elementLocation = driver.findElement(By.xpath("//a[#id='nav-link-yourAccount']"));
mouseAction.moveToElement(elementLocation).build().perform();
//below code does not work
WebElement keysLocation = driver.findElement(By.xpath("//input[#id='twotabsearchtextbox']"));
mouseAction.keyDown(Keys.SHIFT).moveToElement(keysLocation).sendKeys("shoes").build().perform();
}
}
keysLocation is a input element here you can use .sendKeys() without using mouseAction as below and it works :-
keysLocation.sendKeys(Keys.SHIFT, "shoes");
Hope it will help you..:)
You can try using click before you use sendKeys. moveToElement function just moves the cursor over and .click() function will ensure that the element has been selected
Try this
WebElement keysLocation = driver.findElement(By.xpath("//input[#id='twotabsearchtextbox']"));
mouseAction.keyDown(Keys.SHIFT).moveToElement(keysLocation).click().sendKeys("shoes").build().perform();
firefox driver does not respond to keydown command.
so my work around was not use actions class. Here's example of code:
driver.findElement(By.name("q")).sendKeys(Keys.SHIFT + "big");
I am using Java and Selenium to write a test, I use the code below to get into Chrome:setting
driverChrome.manage().window().maximize();
driverChrome.get("chrome://settings");
But when the page is open I can not find any of its web Elements, for example when I try to find "show advanced setting...." by this code
driverChrome.findElement(By.xpath("//a[#id='advanced-settings-expander']")).click();
it throws an error saying that "no such element: Unable to locate element"
I tried to located other elements, but they all failed. I saw this post here but it did not help.
Find the code below:
driverChrome.manage().window().maximize();
driverChrome.get("chrome://settings");
Thread.sleep(5000);
WebElement w = driverChrome.findElement(By
.xpath("//iframe[#name='settings']"));
driverChrome = driverChrome.switchTo().frame(w);
Thread.sleep(1000);
while (true) {
try {
WebElement we = w.findElement(By
.xpath("//a[text()='Show advanced settings...']"));
if (we.isDisplayed()) {
we.click();
Thread.sleep(1000);
break;
}
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println("=========================");
}
}
I haven't tested this but I took your code snippet and cleaned it up a bit. Try this and see if it works. This should be pretty close.
Once you switch to the IFRAME context, you don't need to reference the IFRAME as you did with w.findElement().
In general, Thread.sleep() is not a good practice. You should prefer to use WebDriverWait with ExpectedConditions. Check the docs for all the different things you can wait for using ExpectedConditions. I used .elementToBeClickable() in my code below. This is perfect since you want to click an element. The .until() returns the element waited for so you can just append .click() on the end of the statement... or you can store the element in a WebElement variable and use it elsewhere.
driverChrome.manage().window().maximize();
driverChrome.get("chrome://settings");
WebElement w = driverChrome.findElement(By.xpath("//iframe[#name='settings']"));
driverChrome = driverChrome.switchTo().frame(w);
WebDriverWait wait = new WebDriverWait(driverChrome, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[text()='Show advanced settings...']"))).click();
// alternative example... store returned element and then click on a separate line... or use the variable elsewhere, etc.
// WebElement link = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[text()='Show advanced settings...']")));
// link.click();
You will need to identify Shadow roots to interact with a lot of Chromes native pages including the Settings page.
See this Thread on how to work with them properly:
How to interact with the elements within #shadow-root (open) while Clearing Browsing Data of Chrome Browser using cssSelector
I am trying to automate test scripts in selenium. Scenario of the activity to be automated:
It should open automatically a page URL first.
Click on the left navigation.
The page then gets populated with a drop-down, it should select a fixed value from the drop down(say = company)
Click a create button at the bottom of the page.
In my case the code is working until the population of drop down but after that the code fails to click the create button as the next action. The error message which I got in the command console is as follows:
Element name = create not found on session c48334c30....96ed
Here is my code:
public class testing {
Selenium selenium = null;
#Test
public void submit() throws Exception {
selenium = new DefaultSelenium("localhost", 4545, "*firefox", "URL");
selenium.start();
selenium.open("URL");
selenium.windowFocus();
selenium.windowMaximize();
selenium.click("link=Work with company names");
selenium.waitForPageToLoad("30000");
selenium.select("//select[#name='company_id']", "label=company");
selenium.waitForPageToLoad("3000");
selenium.click("name = create");
}
}
Please provide me your suggestions to solve this, since I am not able to understand why it is failing to click the button named "create". I also tried to use selenium.click("xpath=//button[matches(#id,'.*create')]"); instead of selenium.click("name = create") but it didnt work as well.
Please let me know what can be the issue for this error and how can I resolve it? Thanks.
1) it would be good if you provide html code of your page.
2) before clicking any element (which is loaded after some action) I recommend using WaitForElementPresent (from Selenium IDE), i.e. be sure that element really exists. Selenium works rather fast and it may try clicking the element before the element actually loaded.
You may use something like this:
public bool waitForElementPresent(string Xpath) {
bool present = false;
for (int second = 0; ; second++) {
if (second >= 5) {
break;
}
if (IsElementPresent(Xpath)) {
present = true;
break;
}
Thread.Sleep(1000);
}
return present;
}
try with this
selenium.click("//*[contains(#name,'create')]");
As you are using: selenium.waitForPageToLoad("3000");
Selenium is waiting for page to load. You want to add a pause, though thread.sleep isn't the best practise it can still work for you.