WebDriver.getAccessibleName() throws StaleElement Exception using Selenium - java

I have a simple <a> element which is inside an iframe. I want to click it and if I first try to use getAccessibleName() method on it and then click it I got StaleElementReferenceException. If I try to direct click the element there isn't any problems. At the same time I am able to use methods like getText() or getLocation(), but If I try call getAccessibleName() then unknow error is provided and 32000 is the code. After that the element becoms stale and can't be used anymore.
Where is the problem and why this method provide such an error? I'm using this method to create something like a detailed report for test execution and is important for me. I don't have any other problems and I using this method all the time and this is the first case with errors? If someone else is having an issue like this please let me know, will appreciate all comments and suggestions.

getAccessibleName()
getAccessibleName() gets result of a Accessible Name and Description Computation for the Accessible Name of the WebElement.
Ideally before extracting the Accessible Name you have to induce WebDriverWait for the visibilityOfElementLocated() and you can use the following solution:
driver.get("https://www.selenium.dev/");
System.out.println(new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//h2[text()='Getting Started']"))).getAccessibleName());
Console Output:
Getting Started

Related

xpath tested and correct but i recieve the error : no such element: Unable to locate element

My Xpath is correct & no iFrame and I can locate element in Chrome console but my program still fails. I have used explicit wait also.
no such element: Unable to locate element: {"method":"xpath","selector":"//*[contains(#ng-click,'authenticationCtrl.onSubmitMage()')]"}
i tested my xpath with Try xpath and it works but when i compile my code i still recieve the error
the page Object :
package com.orange.pageObject;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class MageReferentiel {
WebDriver webdriver;
public MageReferentiel(WebDriver rwebDriver) {
webdriver = rwebDriver;
PageFactory.initElements(webdriver, this);
}
#FindBy(xpath = "//*[contains(#ng-click,'authenticationCtrl.onSubmitMage()')]")
#CacheLookup
WebElement connexion;
public void clickConnexion() {
connexion.click();
}
The step definition :
#When("l utilisateur choisi le referentiel")
public void l_utilisateur_choisi_le_referentiel() throws Exception {
mr.clickConnexion();
Thread.sleep(3000);
}
im looking to click in button
thanks
I agree with #Prophet, it could be because of some JS call the button, //*[contains(#ng-click,'authenticationCtrl.onSubmitMage()')] changing it's state to some other state. so what we can do about is that, to try with different locator.
such as :
//button[#translate ='LOGIN']
and see if that works, even if it doesn't try changing it to css.
Since ng elements are going very well with Protractor (Angular), better to use in Protractor in that case, so it suppose to be something like element(by.click('authenticationCtrl.onSubmitMage').click();
I guess the ng-click attribute value is dynamically updated on the page, so when you trying to access that element this element is changed, not having it's initial state.
Instead of locator you are using try this XPath:
//button[contains(text(),'Connexion')]
or this
//button[#translate='LOGIN']
The second element with this locator will be
(//button[#translate='LOGIN'])[2]
Looks like the element is not rendering on time. Try using explicit wait. Following gif shows how it is done using Cucumber:
https://nocodebdd.live/waitime-cucumber
Same been implemented using NoCodeBDD:
https://nocodebdd.live/waittime-nocodebdd
Disclaimer: I am the founder of NoCodeBDD so BDD automation can be achieved in minutes and without code. Through NoCodeBDD you could automate majority of the scenarios and it allows you to write your own code if there are edge cases. Would love to get some feedback on the product from the community. Basic version (https://www.nocodebdd.com/download) is free to use.
The default wait strategy in selenium is just that the page is loaded.
You've got an angular page so after your page is loaded there is a short delay while the JS runs and the element is finally ready in the DOM - this delay is causing your script to fail.
Check out the selenium docs here for wait strategies .
Your options are:
An explicit wait - This needs to be set per element you need to sync on.
I note you say you've used an explicit wait - but where? - It's not present in the code you shared and it might be that you've used the wrong expected condition.
Try something like this:
WebElement button = new WebDriverWait(rwebDriver, Duration.ofSeconds(10))
.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[contains(#ng-click,'authenticationCtrl.onSubmitMage()')]")));
button.click();
Use an implicit wait - you only use this once when you initialise driver and it will wait the specified amount of time for all element interaction.
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
There are other reasons that selenium returns a NoSuchElement but synchronisation is the most common one. Give the wait a go and let me know if it is still giving you trouble.
Through discussion in the comments, the trouble is an iframe
If you google it - there are lots of answers out there.
With frames, you need to identify it, switch to it, do your action(s) then switch back:
//find and switch - update the By.
driver.switchTo().frame(driver.findElement(By.id("your frame id")));
//actions go here
//back to normal
driver.switchTo().defaultContent();

Error occured on trying to use double click () for editing a field on saas

Using the below Code i am trying to double click a text field and edit it with a value.
The error occured when running the script says-
Heading
Exception in thread "main" org.openqa.selenium.NoSuchElementException:Unable to locate element: {"method":"id","selector":".//[#id='00N28000001bbuD']"}
Below is the set of code used-
WebElement Fieldvalue;
Fieldvalue= driver.findElement(By.xpath(".//*[#id='00N28000001bbuD_ilecell']"));
//Fieldvalue= driver.findElement(By.xpath(".//*[#id='00N28000001bbuD']"));
action.moveToElement(Fieldvalue).doubleClick().perform();
driver.findElement(By.id(".//*[#id='00N28000001bbuD']")).sendKeys("60000");
driver.findElement(By.xpath(".//*[#id='bottomButtonRow']/input[1]")).click();
You might observe one thing that the xpath used to find the element is different than the webelement where i want to perform the edit.
The reason for this is -
Fieldvalue= driver.findElement(By.xpath(".//*[#id='00N28000001bbuD_ilecell']"));
Helps me find the complete row
and
driver.findElement(By.id(".//*[#id='00N28000001bbuD']")).sendKeys("60000");
is the section in the above selected row where the edit should occur.
I did try keeping both the ids same, but in both the occassions the script failed.
Can anyone assist?
You're using By.id with an xpath locator, that's why it fails. Change this:
driver.findElement(By.id(".//*[#id='00N28000001bbuD']")).sendKeys("60000");
To this:
driver.findElement(By.xpath(".//*[#id='00N28000001bbuD']")).sendKeys("60000");
Or this:
driver.findElement(By.id("00N28000001bbuD")).sendKeys("60000");

How do I check if the selenium selector was successful?

I am currently developing automated UI tests with Appium for a website.
I run my tests with many devices on testobject and there are some problems I try to solve.
My sample code is this:
WebElement lexiconCollapsible = mDriver.findElement(By.xpath("//*[#id='1014']/a"));
assertNotNull(lexiconCollapsible);
ScrollHelper.scrollToElement(mDriver,lexiconCollapsible);
Thread.sleep(1000);
lexiconCollapsible.click();
This is working for many devices but not for all of them.
On some I get the following error code:
org.openqa.selenium.InvalidSelectorException: Argument was an invalid selector (e.g. XPath/CSS). (WARNING: The server did not provide any stacktrace information)
The exception is thrown at the position where I want to click the element, so the object is not null.
So my question is:
Has anybody found a solution to check if the device is capable of finding the object? Is there something like a isObjectFound method for this?
I tried with css selector, id, etc. too but the results are the same.
From Selenium Docs,
exception selenium.common.exceptions.InvalidSelectorException(msg=None, screen=None, stacktrace=None)[source]
Thrown when the selector which is used to find an element does not return a WebElement. Currently this only happens when the selector is an xpath expression and it is either syntactically invalid (i.e. it is not a xpath expression) or the expression does not select WebElements (e.g. “count(//input)”).
So it looks like your Selector is incorrect and since it only happens with XPATH, you should try css selector.
Try,
WebElement lexiconCollapsible = mDriver.findElement(By.cssSelector("#1014 a")).click();
Regarding your isObjectFound method, it looks like the WebElement is found when you did findElement, you are getting an exception only on click(). I suggest you switch to CSS selectors to avoid this exception.
Answer provided by JeffC.
It was a problem with the timeout and wait time in between the functions.
Utility.implicitlyWaitForElementPresent(mDriver,By.xpath("//*[#id='1014']/a"));
WebElement lexiconCollapsible = mDriver.findElement(By.xpath("//* [#id='1014']/a"));
assertNotNull(lexiconCollapsible);
ScrollHelper.scrollToElement(mDriver,lexiconCollapsible);
Thread.sleep(1000);
lexiconCollapsible.click();
It's working far better with xpath.

Selenium + Java error listener ext.js

How can I catch an error when I don't know when it happens?
I'm using Selenium + Java. Creating tests for a JS web page.
When an error occurs, the test continues clicking on the elements.
The error is visible in that moment, so it is not a messagebox or something like that. An errorbox just becomes visible. Then some time passes, and the test crashes saying that it cannot click some element.
How can I listen for any random element to be visible (or clickable) while my test is running? That would allow me to catch the error and the test would not fail.
Should I put my test into two threads, one listening for errors, and another running my test case?
I would suggest to use the following
List<WebElement> Elements = getDriver().findElements(method);
First, when you entry to the page you just prepare the list of the page elements.
Then you include this procedure several time in your code. You compare your list with the new list and see if the error element is appears, means you will have one more element in the new list. Then you catch it.
The best option is to understand and resolve the underlying error condition.
If the error is only something that occurs exclusively in testing, or otherwise cannot be resolved I would suggest looking at your driver configuration and insure that the dialog you're seeing wouldn't be covered by the Driver setting for Unexpected_Alert_Behavior. If you've got that turned off, I'd try turning it on and see how it impacts your behavior.
How to handle an Alert with "UnexpectedAlertBehaviour" capability in Selenium?
https://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/ie/InternetExplorerDriver.html
I'm not entirely certain that will solve the listed problem bc the dialog you mention is part of the dom and the 'unexpected' alert behavior is typically not visible in that context from what I've seen. I believe this is also very specific to the IE implementation.
Finally, I think I would resort to using a method in my class to perform all findbys for me. In that method, I would use an explicit wait to check for the random addition and have it fall-through to resolve the actual requested object if the wait fails to resolve the 'error reference'.
/** By identifier for the error dialog addition.*/
private static final By ERR_DLG = By.className("error");
/**
* Delegate method that will attempt to resolve the occasional page error condition prior to performing the delegate lookup on the WebDriver.
* <p/>
* This method will fail on Assert behavior if the error dialog is present on the page.
*
* #param driver WebDriver referenced for the test instance.
* #param lookup By reference to resolve the desired DOM reference.
* #return WebElement of the specified DOM.
*/
private final WebElement safeResolve(WebDriver driver, By lookup) {
WebDriverWait wait = new WebDriverWait(driver, 1);
WebElement errDlgRef = null;
try {
errDlgRef = wait.until(ExpectedConditions.visibilityOfElementLocated(ERR_DLG));
} catch (TimeoutException te) {
//This is actually OK, in that in the majority of cases this is the expected behavior.
//Granted this is bad form for Unit-Testing, but Selenium at an Integration-Test level changes the rules.
}
Assert.assertNull("Unexpected Error Dialog exists in DOM", errDlgRef);
return driver.findElement(lookup);
}
This solution is kind of a hammer, but I think it would work. All lookups would need to go through this method. You'd probably also need an analogous method if you use the List WebDriver.findElements(By) function in your test, or a way to abstract it from this one.

:first / :first-child doesn't seem to work with Selenium 2

While migrating from Selenium 1 to Selenium 2 I am running into a problem.
I have the structural equivalent of the following:
<ul id="documentType">
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
Previously I would in Selenium 1 use the following css selector to find the first anchor link:
#documentType li:first-child a
This would work great, however, when I switch to selenium 2 and try and use the equivalent I get element not found. The following does work but is less precise then I would like.
#documentType li a
I have tried but could not get to work the following:
#documentType li:first a
For greater detail I'm using HtmlUnitDriver with the following code:
driver.findElementByCssSelector("#documentType li a");
Any help on getting the equivalent of the original selector working I would greatly appreciate it!
I be confused :)
EDIT: Phill Sacre brought up a good point on the fact I'm directly using HtmlUnitDriver which could be the source of the problem since it's a pure java implementation. I do this specifically for the ability to deal with a nasty Ajax problem of how to know when Ajax is done running. You can do this with the following code:
protected void waitForAjaxToComplete() {
long result = jQueryActive();
while (result != 0) {
result = (Long) driver.executeScript("return jQuery.active;");
}
}
This is obviously advantageous over using the technique of waiting for an element to appear which can be very inaccurate. I wish WebDriver would expose the executeScript method which would resolve this problem.
Further I noted that by default HtmlUnitDriver does use a java based implementation to parse the css selector supplied and I'm guessing this is the source of the problem. The parser is com.steadystate.css.parser.SACParserCSS21.SACParserCSS21 which may not properly take into account the :first and :first-child qualifiers.
What seems to make this ok is that the behavior of HtmlUnitDriver seems to return the first element by default. It's sister method findElementsByCssSelector seems to return an ordered list.
As a result while this appears to be a bug I may have answered my own question by learning how HtmlUnitDriver operates.
Which browser were you doing your Selenium 1 testing on? Looking in the Selenium documentation, the HtmlUnit driver is a pure-Java solution (i.e. it doesn't run in a browser, obviously).
Now I think there are some differences in selectors between browsers, so if you were using the Firefox browser before it may be worth using the FirefoxDriver to run your Selenium 2 tests?
Similar to Phill's answer- HtmlUnit parser the page differently than FF. I would start the debugging process by running the same test using the FF driver and see if it passes there. If it does pass, then the next step I would do is get the HTML from the HtmlUnit driver (I guess the command would be driver.getPageHtml() or something similar). I would compare that html with the html you get when you look at the html through a real browser (FF, chrome,..). Sometimes you see that tags have been put in by the real browser (i.e., by its parser) or by the HtmlUnit browser. You can either correct your selector or use a different driver (or go tell the developers to fix their html because that what usually causes these problems :-)
I had the same problem with this selector (using Spock/Geb). This has been resolved in the new version of Geb which is 0.9.2 (which has the changes to the HTML unit driver too). Now $('tr:first-child a') works fine with HTMLUnitDriver
I can provide the following CSS Selectors
1. css=#documentType > li > a -- First Link
2. css=#documentType > li+li > a -- Second Link
3. css=#documentType > li+li+li > a -- Third Link
else, you can try
1.css=#documentType > li:nth-child(2) > a -- Second Link
2.css=#documentType > li:nth-child(3) > a -- Third Link

Categories

Resources