I'm getting Selenium exception stale element reference: element is not attached to the page document after the first iteration of the for loop. My code is :
for gc in grpCommune:
self.driver.execute_script("return arguments[0].scrollIntoView(true);", gc)
self.driver.execute_script("window.scrollTo(0, 0);")
e=gc.find_element_by_xpath('//a[2]')
e.click()
sleep(1)
...
genertaeCSV()
self.driver.back()
how can I resolve it?
Stale Element exception occurs when the selenium reference bound to the element is no more valid, generally, this happens when you either navigate away from the page or refresh the page or the contents on the page is reloaded. In your case, you are trying to refer to the gc element which was captured with a reference before clicking the e element. The moment you clicked on e element using e.click() button, all the references in grpCommune is no longer valid. So, you will be able to run only the first iteration successfully with your code.
How do I fix this code:
Get the gc element within the for loop. Rather than using for each use for loop with the index.
Stale element exception occuring when element in on page but selenium driver instance could not interect with that element.
Following actions can be resolve stale element exception
1.Refresh page by using "navigate(). refresh()" method in selenium
2.using loop try to click or check visible of that element if that element visible or already clicked exit from loop.
Related
I am trying to learn the PageFactory model. I understood the fact that when we do a initElements, the WebElements are located. Say for example, I click on a webelement and because of which there is a change in one of the other webelements in DOM. Now, obviously I would get a StaleElementReferenceException here. How would I resolve this issue?
Should I find that specific WebElement again knowing the fact that there can be a change in the WebElement's properties in the DOM? or is there an another way to handle this?
StaleElementReferenceException
StaleElementReferenceException extends WebDriverException and indicates that the previous reference of the element is now stale and the element reference is no longer present on the DOM of the page.
Common Reasons
The common reasons behind facing StaleElementReferenceException are as follows:
The element has been deleted entirely.
The element is no longer attached to the DOM.
The webpage on which the element was part of has been refreshed.
The (previous) element has been deleted by a JavaScript or AjaxCall and is replaced by a (new) element with the same ID or other attributes.
Solution : If an (old) element has been replaced with new identical one, the simple strategy would be to use findElement() or findElements to look out for the element again.
Answering your queries
When we do a initElements, the WebElements are located : When you call initElements() method, all the WebElements of that page will get initialized. For example,
LoginPageNew login_page = PageFactory.initElements(driver, LoginPageNew.class);
This line of code will initialize all the static WebElements defined within the scope of the LoginPageNew.class whenever and wherever it is invoked from your Automation Script.
I click on a webelement and because of which there is a change in one of the other webelements in DOM : This is pretty much possible.
As an example, in general invoking click() on a <input> tag wouldn't trigger any change of any of the WebElements on the HTML DOM.
Where as invoking click() on a <button> tag or <a> tag may call a JavaScript or a Ajax which inturn may delete an element or can replace the (previous) element by a (new) element with the same ID or other attributes.
Conclusion
So, if WebDriver throws a StaleElementReferenceException, that implies even though the element still exists, the reference is lost. We should discard the current reference we have and replace it by locating the WebElement once again when it gets attached to the DOM. That means you have to again reinitialize the class through initElements() method which inturn reinitializes all the WebElements defined in that page.
Solution
If a old element has been replaced with new identical one, the simple strategy would be to invoke WebDriverWait inconjunction with ExpectedConditions to look out for the element.
You can find relevant detailed discussions in:
How to add explicit wait in PageFactory in PageObjectModel?
References
Here are the references of this discussion:
Stale Element Reference Exception
Class StaleElementReferenceException
Selenium: How to tell if RemoteWebDriver.findElements(By) can throw StaleElementReferenceException at all?
This is a known problem with the PageFactory implementation.
If you are unlucky enough for the element to become stale in the instant between the element being found, and then the element being clicked upon, you will get this error. Unfortunately the PageFactory code does not try to find the element again if it has become stale and it throws an Exception.
I would classify this as a bug with PageFactory, it should auto re-find the element if it ever becomes stale (unless the #CacheLookup annotation is used).
The suggestion to recall initElements isn't going to fix anything, you only need to init the elements once because that binds a Java proxy class to the element in question. The page factory implementation is supposed to remove the possibility of StaleElementReferenceExceptions (hence why this is a bug)
Stale element exception is thrown in two cases
The element is no longer attached to the DOM.
The element has been deleted entirely.
When this happen you wrap your code in try catch block then you can loop and retry as many times as you need until it succeeds.
public void waitForElementPresent(final By by, int timeout){
WebDriverWait wait = (WebDriverWait)new WebDriverWait(driver,timeout)
.ignoring(StaleElementReferenceException.class);
wait.until(new ExpectedCondition<Boolean>(){
#Override
public Boolean apply(WebDriver webDriver) {
WebElement element = webDriver.findElement(by);
return element != null && element.isDisplayed();
}
});
}
I've initialized all the WebElements in the project using PageFactory. For logging purpose I am trimming the logs of the elements. But I faced some difficulty while trimming. So when I tried to print the elements, I found that most of the times an element is printed in this manner:
[[ChromeDriver: chrome on XP (d96cf99661f5d938b75f8448dad62d3b)] -> xpath: //button[#ng-reflect-label='Add']]
but in extremely minor cases, it is printed this way:
Proxy element for: DefaultElementLocator 'By.xpath: //div[contains(#class,'ui-growl-icon-close')]'
My trimming method looks for "->" in the element so most of the times it works, but rarely it fails when it changes to "Proxy element for..."
Thing is there is no consistency in the elements when they get printed. Element getting printed as "Proxy element for..." would get printed as "[[ChromeDriver.." in the next iteration
Browser used: chrome (only)
When you use PageFactory for initializing webelement it initializes it with a Proxy object. Only when you access the element from your code, like a sendkeys, is the actual webelement retrieved and initialized fully.
For a code level discussion of how selenium pagefactory initializes refer to this. http://www.alechenninger.com/2014/07/a-case-study-of-javas-dynamic-proxies_14.html
I am clicking on the text box displayed on first page
WebElement txtBox = driver.findElement(By.xpath("---xpath---"));
txtBox.click();
Then after some block of execution I am getting the same textbox in new page on same window.
Here also I want to click on the text box.
I used JavascriptExecutor to do this scripting.
((JavascriptExecutor)driver).executeScript("arguments[0].click();", txtBox );
But while running the script I am getting an error message saying:
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
You need to execute driver.findElement() every time you reload the page.
This method returns WebElement which is integral part of current page. If you refresh browser or navigate to some other URL or even if element is deleted and attached again by some javascript on same page, previously found element cannot be used anymore.
Here you have official explanation of this exception: http://www.seleniumhq.org/exceptions/stale_element_reference.jsp
Stale Element exception comes after you want to interact with an element loaded previously. If you get webelement and then reload the page it gives this exception because it is not in a newly created page. It is better to click the web element without assigning it to a variable like:
driver.findElement(By.xpath("---xpath---")).click();
I have this issue with selenium; I cannot find i textinput : it always raises this exeception:
Element is not currently interactable and may not be manipulated
in this line:
Driver.FindElement(By.Id("ctl00")).Clear();
I try to put waiting like this:
Waiting.Until(driver =>(By.Id("ctl00")));
and
Waiting.Until(ExpectedConditions.ElementExists(By.Id("ctl00")));
but no luck.
If the exception gets thrown on Clear(),
the element is most likely present on the page and the input in a readonly state.
Try to validate XPath first as might be that targeting more than one element.
Due to this, element not currently interactable and may not be manipulated.
I faced same issue and found solution with above as my XPath was locating multiple element which exists on DOM but not page.
Correct the element XPath, error will resolve automatically with adding webdriver wait.
I hit the same error, was also a bit confused, but resolved it using the below wait condition. The elementToBeClickable condition checks that the element is both visible and enabled. Perhaps visibility is enough, but Selenium throws an explicit ElementNotVisibleException, so I'm not sure why I wouldn't get that...
Anyways, I opted to use a more robust wait condition, and it has worked well for me.
wait.until(ExpectedConditions.elementToBeClickable(By.id("myElementId"))).clear();
This happens sometimes when element is not visible. It would happen even when element is visible also.
Try using with different tags like xpath or etc.
You can check the element status using below script
driver.findElement(By.className("")).isEnabled()
It is due to element not visible so apply more wait while performing the action or you can use hardcoded sleep cause sometimes webdriver's wait doesn't work.
You are trying to perform .clear() on a WebElement, which is not an input tag. For example, if you try to do clear on a Span WebElement, You will get Selenium Invalid Element State error.
Waiting.Until(ExpectedConditions.ElementExists(By.Id("ctl00"))); should work.
Set break point at Waiting.Until() line and input $$("#ctl00") in Chrome console to check if the element is existing.
Make the driver to wait until an element is visible.
WebDriverWait wait = new WebDriverWait(driver, timeout);
wait.until(ExpectedConditions.visibilityOf(element));
Hope this helps!
If waiting for visibilityOf(), elementToBeClickable(), element.isEnabled() doesn't do the trick, try to look at the attributes of your element.
It may have some attributes responsible for read only state, in my case this was aria-readonly and aria-disabled, Hence I created custom wait like this:
webDriverWait.until(webDriver -> webElement.getAttribute("aria-readonly").equals("false") && webElement.getAttribute("aria-disabled").equals("false"));
Use this you will not get this error(might be scroll is not working here so use keypad TAB to move on, my problem got resolved by this)
Actions act = new Actions(driver);
act.sendKeys(Keys.TAB).build().perform();
act.sendKeys(Keys.RETURN).build().perform();
You might be asking an element with the same attribute like duplicate id, name etc.
I My case i was entering password in confirm password TextBox whose Id was "confirmPassword" but the same Id is used for the "Confirm Password" label for that TextBox.
So selenium was trying to perform sendKeys on the label instead of TextBox so getting "InvalidElementStateException", After that i changed the xpath and it worked.
So when you get "InvalidElementStateException" you should first check whether there are any duplicate element available with the xpath you have generated, and that not-interactive element could be a Button, Label or disabled element that causes the exception occurred.
I was clicking on a div element or label to element to clear the text in input tag. Changed my xpath to input tag and then I did not received any exception and the test was clear.
I'm getting collection of links. Then I click first link, do something, moving back (driver.navigate().back();), getting second link and then link.click(); throws an exception org.openqa.selenium.StaleElementReferenceException: Element not found in the cache.
What am I doing wrong?
As soon as you navigate away from the page the element variables become invalid. The trick is to find the first element, click, go back and then find the second element and click.