Given that I have the following XPath:
//table[#title="someTitle"]//td[#id="someId"][3]
When I try to click on this element using WebDriver's element(By.xpath(someXpathString)).click(); I get the "ElementNotFound" exception.
However, when I try finding the element using the SAME XPath but using the console in Chrome DevTools it returns exactly the element that I'm looking for. The call looks like this:
$x('//table[#title="someTitle"]//td[#id="someId"][3]');
Now, I know that if I use THIS XPath:
(//table[#title="someTitle"]//td[#id="someId"])[3]
in WebDriver, the element is found and click works.
Please note that I want to be able to find the 2nd, 3rd or even 4th element by that selector. This is a workaround for interacting with table cells on the same column but different rows.
My question is: why does the Chrome console recognize the element using the XPath without parenthesis while the Find function does not, and what is the actual difference between the two XPaths?
I've noticed on other elements that the parenthesis notation is NOT needed in order to select the 2nd or higher element of that type, so I would like a clear explanation on how this type of XPath works, what is the logic behind it.
Both xpaths are different.
//table[#title="someTitle"]//td[#id="someId"][3] -- will select only 3 column elements
(//table[#title="someTitle"]//td[#id="someId"])[3] -- selects all columns and then returns only one element indexed at 3.
For example assume a table with 4 rows and 4 columns.
First xpath selects only elements in the third column of each row (total 4).
But second xpath slect only one element, ie column number 3 at row 1, irrespective of number rows in the table.
if we use find element, both will return only one element. But if we use find elements, first will return 4 elements but second xpath returns only one element.
If you are going to the page where your element is from another page, try refreshing -
driver.navigate().refresh();
Related
I'm trying to find the xpath for an element that contains three dots instead of text. Once I expand the element by clicking on arrow in DOM model html it returns the text.
The following xpath returns nothing unfortunately:
//button[contains(text(),'Pending')]
What's the right solution?
The text content of that element is not a three dots but Pending (). You see the ... only because there is no room to present the text there until you expand the element. So, generally this //button[contains(text(),'Pending')] should work.
You can also try this XPath expression:
//button[contains(.,'Pending')]
It means "a button element with any attribute containing Pending value"
It is more general and should work.
To understand why //button[contains(text(),'Pending')] did not work see this post or this. There are more explanations about this.
I am new to selenium and aware of how implicit wait works with FindElement. But curious to know about how would it work with FindELements.
Say I have a list of elements which will be identified using FindElements method. Now these elements may take a time gap to load one after another.
Element 1: 4th Second
Element 2: 7th Second
Element 3: 11th Second
Now if I mention implicit wait as
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS) ;
what would FindElements() return- Exception or a list with 2 elements? I have never come across such scenario so could not evaluate it.
In that case, there is one search of the elements (of all the elements) and than the implicitlyWait will come, so in that case it will find the 1st element only!
if no element was found will return empty list
the browser working in one thread so once there is element - even one that return, the list is full from that side.
if need other condition you can use wait until atleast
In this case your findElements method will return 1 element only since it is waiting to locate element(s) according to the passed locator and once it finds some element(s) it will return the list containing elements located by that locator.
So it will return list containing the first element only.
In that scenario, FindElements() would return a list with two elements.
But in a case where none of the elements were found, FindElements(), unlike FindElement() would not return an exception, it would return an empty list.
I test an application which use non-unique resourse-id for elements.
Is there any way to find such elements by xpath like
//*[#resourse-id='non-unique-id'][2]
I mean the second element with same resourse-id.
I'd recommend avoiding xpath in mobile automation since this is the most time-consuming strategy to find elements.
If you don't have any other anchors for your elements but you confident in its order, you can stick to the following approach: Appium driver can return a list of elements with the same locator, in case of Page Object model you can either do this way:
#AndroidFindBy(uiAutomator = "resourceIdMatches(\".*whatever\")")
private List<MobileElement> elements;
so, once your page is initialized, you can access an element by index:
elements.get(1).click();
or, in case of manual managenemt, you can do this way:
List<MobileElement> elements = driver.findElements(MobileBy.AndroidUIAutomator("resoureceIdMatches(\".*whatever\")"));
elements.get(3).click();
Hope this helps.
As far as my understanding goes, you need to select the second element with the path as mentioned: //*[#resourse-id='non-unique-id']
To do that, you need to first grab all the elements with the same non-unique resource ID and then get() them. So, your code should be:
driver.findElements(By.xpath("//*[#resourse-id='non-unique-id']")).get(1).click();
The index for any list starts at 0. So, the second element can be accessed through the value of 1.
Hope this helps.
Try following approach:
(//*[#resourse-id='non-unique-id'])[2]
HTML with non-unique ids is not a valid HTML document.
So, for the sake of future testability, ask the developers to fix the ids.
I would want to select the first instance of an element in a page where many number of such elements are present with 'ID' which will not be same always.
for example, visit, http://www.sbobet.com/euro which lists lot of sports and odds, where I want to click on the first odds.
and the html structure would be like this,
I want to click on this first span value and proceed with some test case.
Any help on how to achieve this ?
There could be two approaches two the problem:
1. If you are sure you will always need only the first instance:
driver.FindElementsByClassName("OddsR")[0];
If not, then you have collection of elemets and you can access an of those
2. Also, you can first identify any closest enclosing div and then you can use the same snippet as above:
driver.FindElementsByClassName("OddsR")[0];
This one is a better approach if page is a bit dynamic in nature
Use #class attribute. If OddsR class you are intrested in is the 1st one on the page then just use Driver.FindElement(By.ClassName("OddsR")). Webdriver will pick the 1st occurence (no matter if there are more)
Have checked your link and I agree with alecxe, you should probably start with div. But i would suggest a simpler selector :
css = "div.MarketBd span.OddsR"
The above selector will always point to the first span of "OddsR" class within div of "MarketBd" class.
Thanks for the response.
I am finally able to click on the element, by this XPATH,
"//span[#class='OddsR']"
This clicks on the first occurrence of 'OddsR' values, without giving any index.
How to count the number of elements are matching with for the given xpath expression
xpath: driver.findElement(By.xpath("//div[contains(#id,'richedittext_instance')]"))
all i need is the count.
Try this code:
//Assume driver is intialized properly.
int iCount = 0;
iCount = driver.findElements(By.xpath("Xpath Value")).size());
The iCount has the number of elements having the same xpath value.
Another option
If you are basing your requirements strictly on the need to use Selenium, you might be able to do something like this using WebElements and getting the size of the returned list:
List<WebElement> myListToCheck=currentDriver.findElements(By.xpath("somePath"));
if(myListToCheck.size()>0){
//do this
}else{
//do something else
}
Or just simply returning the size of the returned list; if that's all you really want to get from it...
int mySize=myListToCheck.size()
I believe once you have an established WebElements list, you can also use iterators to go over that list.
Helpful, I dunno... just providing another way to get to the same end-game.
Not working in Selenium, which only allows to return nodes from XPath, not primitives like the number returned by count(...). Kept for reference and is valid for most other tools offering a more complete XPath API.
You should only return least possible amount of data from the query. count(//div[contains(#id,'richedittext_instance')]) counts the number of results within XPath and thus is faster as all the elements do not have to be passed from the XPath engine to Selenium.
I can't help you with how to fetch this as n int out of selenium, but this should be easy stuff.
Do the following:
from selenium.webdriver.common.by import By
elements = driver.find_elements(By.XPATH, "Your_XPath")
This outputs a list of selenium.webdriver.firefox.webelement.FirefoxWebElements (in my Firefox browser).
Finally, find out the length of the list:
len(elements)
NB.: Please note that I have written find_elements() (plural) and NOT find_element(). Both of them are different. find_element() only returns the first matched web element, but to find the list of all the matched web elements, we have to use find_elements().