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.
Related
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.
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();
So this is a bit of a performance question regarding Selenium Webdriver (Chromedriver) and Capybara.
I have some react-select dropdowns with quite a bit of data in them. For some reason the react-selects take a VERY VERY long time to pick out the option in them. The code is pretty simple and I grabbed it from here: https://github.com/JedWatson/react-select/issues/832
But it basically comes down to:
page.find('.Select-control').click
page.find('.Select-option', text: 'the text').click
Thing is, this works fine. But it takes an extremely long time (Upwards of a minute a dropdown). Now...in Capybaras defense these dropdowns have a LOT of options to select from, so I thought selecting from the top-most item would be the fastest, but that doesn't seem to affect it.
Does Capybara/Selenium hold the "options" in a different sorted list somewhere or something? Since i'd assume selecting from a top option in the dropdown would be faster, but it doesn't seem to be?
Generally, when using the text option, find first finds all the elements that match using the locator with the current selector type. In your case your selector type is defaulting to :css, and the locator is .Select-option. So Capybara will find all elements with the class Select-option and then it will go through each of those elements comparing the text to see what matches (and checking visibility), but it will have to compare all of them to make sure the selector isn't ambiguous.
One way to speed that up would be to use first with a minimum option
page.first('.Select-option', text: 'the text', minimum: 1).click
which can skip some of the text and visibility checking since it doesn't have to worry about ambiguous elements. Another solution would be to skip the text option altogether and write it into an XPath along the lines of
page.find(:xpath, XPath.css('.Select-option')[XPath.string.n.is('the text')]).click # Haven't verified this is 100% correct but it should be close
If you're doing this a lot in your app you may want to consider creating a custom selector for this
Capybara.add_selector(:react_option) do
xpath do |locator|
XPath.css('.Select-option')[XPath.string.n.is(locator)]
end
# You can add other filters in here - see https://github.com/teamcapybara/capybara/blob/master/lib/capybara/selector.rb
end
which would then allow you to do
page.find(:react_option, 'the text').click
Note, if you can limit the element types it will also make the query more efficient, so if all of the elements are <li> elements you might want to do something like
XPath.css('li.Select-option')[XPath.string.n.is(locator)]
In String Template one can easily get an element of a Java Map within the template.
Is it possible to get the n-th element of an array in a similar way?
According to the String Template Cheat Sheet you can easily get the first or second element:
You can combine operations to say things like first(rest(names)) to get second element.
but it doesn't seem possible to get the n-th element easily. I usually transform my list into a map with list indexes as keys and do something like
map.("25")
Is there some easier/more straightforward way?
Sorry, there is no mechanism to get a[i].
There is no easy way getting n-th element of the list.
In my opinion this indicates that your view and business logic are not separated enough: knowledge of what magic number 25 means is spread in both tiers.
One possible solution might be converting list of values to object which provides meaning to the elements. For example, lets say list of String represents address lines, in which case instead of map.("3") you would write address.street.
Which way is better: $('#item1 img[src]').qtip( {..}); -OR- $('#item1').qtip( {..}); ?
It works both ways. Would you recommend to use img[src] as a part of the selector? Is it normal?
Thank you.
Those are two separate things:
$('#item1 img[src]').qtip( {..});
Selects an image element within an element with id item1.
$('#item1').qtip( {..});
Selects an element with id item1.
Also
What does img[src] do?
I only know that format when adding a src to it. Otherwise it does just nothing if it works.
$('img[src*="you_src_you_want_to_select"]')
With Sizzle in jQuery 1.3.x+, selects are performed from outer to inner (bottom to top, or right to left). jQuery is optimized for finding by ID, so by descending from an ID and adding more specific matching rules on the right without being overly specific, it is fair to say that you may see performance improvements.
I recommend checking out this presentation by Paul Irish for more details on selector performance:
http://paulirish.com/2009/perf/