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.
Related
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
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();
i'm stuck in a funny situation.
Whenever I use implicit wait in my code, my driver is able to locate the elements via its XPath. However when I comment out the implicit wait command, then is not able to locate the element.
Then I was doing some research, and later when I executed the code, I got a different kind of bug. It said "unknown error: cannot get automation extension".
This is really funny because, the wait commands are impacting the way the WebDriver is looking for element on the page.
Please suggest why this is happening and do share your experience if it has happened to any of you before.
The code that is throwing the error is below:-
package xyz;
//import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class Asnmnt11
{
public static void main(String[] args) //throws InterruptedException
{
System.setProperty("webdriver.chrome.driver", "C:\\Users\\Vardhan\\workspace\\SeleniumProject\\files\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://facebook.com");
//driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.findElement(By.cssSelector("input.inputtext")).sendKeys("user#gmail.com");
driver.findElement(By.cssSelector("input[tabindex='2']")).sendKeys("password");
//Thread.sleep(2000);
driver.findElement(By.xpath(".//*[#id='u_0_2']")).click();
//driver.manage().timeouts().implicitlyWait(5000, TimeUnit.SECONDS);
driver.quit();
}
}
Thanks in advance.
When you remove implicit wait then the driver doesn't know how long it should look for the element. It does a quick search and if the element is not present then it will throw the element not found exception.
Xpath elements take more time to find. So it is always good to have an implicit wait. Why?
Searching elements can take time
Website is still loading
Elements are still loading
When I ran your test without any implicit wait the driver gave up finding the element quite fast.
org.openqa.selenium.NoSuchElementException:
no such element: Unable to locate element: {"method":"xpath","selector":".//*[#id='u_0_2']"}
Command duration or timeout: 0 milliseconds
This indicates that the driver was looking for the element for 0 milliseconds and it didn't find it. So it is always a good idea to have an implicit wait.
unknown error: cannot get automation extension
This issue is mostly an chromedriver and chrome issue. Usually is caused by using an older chromedriver version that is not compatible with your current chrome version. Chrome is automatically updated so try to update your chromedriver as well.
If you search element by xpath then it take more time to locate so that it is better to use Implicit or explicit wait. When I used your code without wait some time it throw NoSuchElementException.
AS facebook page take littile time to load and you are trying xpath to locate the elements so it is well and good to use Implicit or explicit wait.
Now as you got the issue
unknown error: cannot get automation extension
it is chromedriver issue, sometime I also got it when i used ChromeOptions. So It is totally irrelevant issue relate with Implicit wait
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");
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