Why `nth-of-type` behaves differently in different browser versions? - selenium

Problem:
So I've run into a peculiar difference in behavior of :nth-of-type selector when applied to an element with tag type not being specified in selector.
Take the following HTML:
<div class="parent-class">
<header>...</header>
<div class="child-class">...</div>
<div class="child-class">...</div>
</div>
Now, this selector
.parent-class .child-class:nth-of-type(1)
should probably point to the first child div element, which it does in Chrome 59 and Firefox 54, but does not in Mink-drived Selenium browsers (Chrome 53 from selenium/hub:3.0.1-fermium and Firefox 50 from selenium/node-firefox-debug:2.53.0).
What nth-of-type does in those browsers is ignoring element types altogether - meaning, for selector to work one has to specify either:
.parent-class .child-class:nth-of-type(2)
or
.parent-class div.child-class:nth-of-type(1)
Question:
Why does the element type gets ignored in case of Selenium browsers?

Selenium is not known to have issues with :nth-of-type(). Perhaps it's a bug with Mink, since that behavior is clearly incorrect — :nth-of-type() should not require a type selector to work, as stated in my answer here.

It is a limitation of Symfony's CssSelector component which is used by Mink
Mink uses CssSelector to translate elements to xpath which is interpretable by the driver.
And this tool simply does not fully support several types of CSS selectors, which is actually stated in the official documentation:
Several pseudo-classes are not yet supported:
*:first-of-type, *:last-of-type, *:nth-of-type, *:nth-last-of-type, *:only-of-type. (These work with an element name (e.g. li:first-of-type) but not with *.

Related

Robot Framework - Locating input element with accept attribute fails

I am writing an automation script for an avatar upload module with the following CSS locator:
input[accept="image/png,image/jpeg,image/gif,image/bmp"]
I am using Robot Framework's Wait Until Element Is Visible keyword to look for the locator above but is unsuccessful with the error:
Element 'css=input[accept="image/png,image/jpeg,image/gif,image/bmp"]' not visible after 30 seconds.
Increasing the timeout also doesn't work. Using the same in Chrome Dev Tools would successfully find the element. My guess is that the commas/slashes are messing with Robot's locator parsing. My question is: What is the correct way to write the locator?
Though present in the DOM, an element may not be visible/rendered. This is very often the case with file upload input elements - the UI renders something different, a button, div that had applied styling and fits in better with the overall design.
Thus a check is it visible will rightfully fail. Change your pre-usage approach to validate the input is in the HTML - this is actually the same as what you did in the browser's dev tools - with the Page Should Contain Element keyword, and proceed on success.
There is no problem with the CSS locator your are using. Maybe the element is in another iframe?

How to click on checkbox on webpage using selenium vba

I have a query,how to click on checkbox on webpage using selenium vba.
Below is the screen shot where i want to click
Below is the html code.
<span name="locSpans[]" value="Nerul" style="display:block">
<input type="checkbox" name="locArr[]" value="8897" onclick="enableDisableLocality(); showSelectedLoc();">Nerul
<br>
<input type="hidden" name="locArrVal[]" disabled="disabled" value="Nerul">
</span>
FindElementByCss is generally faster unless using IE, and then it depends which version of IE and what type of traversal is required.
Repeated tests have proven FindElementByCss to be more performant than FindElementByXPath (Note: that if there is a unique id present then selecting by id is always the first choice!)
In benchmarked tests Chrome and FireFox saw faster matching using CSS consistently across different traversal paths. They are optimized with CSS in mind and using CSS selectors is advocated as selenium best practice. IE was more variable with most instances of XPath being slightly more performant, but there being some clear paths that favoured CSS selection. Long XPath selectors will be costly and prone to breakage. Later versions of IE saw more variability. Opera12 browser came in with mixed results.
I would use a CSS selector:
So, for a simple selection based on likely unique attribute, I would go with an attribute CSS selector of [value='8897'] to target the value attribute. The [] means attribute selector. So value attribute with value of 8897.
driver.FindElementByCss("[value='8897']").Click
If you want to be more selective you can throw in an additional attribute selector, as follows, to target the type attribute.
driver.FindElementByCss("[type=checkbox][value='8897']").Click
When should I use XPath then?
Older IE versions for sure.
Any requirement for walking up the DOM would point to XPath usage.
XPath has some great additional locator strategies for hard to find elements, but that is not necessary AFAIK here. You can see some of the additional considerations here.
You can use xpath below to get checkbox, it means: find input with type="checkbox" and parent SPAN with text "Nerul".
driver.FindElementByXPath("//input[ancestor::span[normalize-space(.)='Nerul'] and #type='checkbox']").Click
Try this if not go for CSS Selector Option
bot.Window.Maximize
bot.FindElementByName("locArrVal").Click
bot.Wait 1000

selenium + capybara: find selector anywhere within element

Assume we have a <div class='whatever'> and somewhere deep inside there is an element <div class='inside-whatever'>
What i need is a way to access that particular inside-whatever-div using Capybara's and/or Selenium's methods.
Problem is, there is another <div class='inside-whatever'> on the page not inside <div class='whatever'>, so
within(:xpath,'//div[#class="whatever"]') do
find(:xpath,'//div[#class="inside-whatever"])
end
returns an error basically saying that there are multiple inside-whatever divs on the page.
What works is to build the xpath from whatever like
'//div[#class="whatever"]/div/div[3]/div/div[5]'
but that is pure madness.
So, is there any better way to look for selector anywhere inside any given element without having to specify a direct path?
You can merge your xpaths like this:
//div[#class="whatever"]//div[#class="inside-whatever"]
The real issue here is that you've fallen into the XPath // trap
find(:xpath,'//div[#class="inside-whatever"])
searches globally rather than from the context node. Instead you should get used to starting your XPaths with .// which will search from the current context node
within(:xpath,'.//div[#class="whatever"]') do
find(:xpath,'.//div[#class="inside-whatever"])
end
and do what you expect. This is mentioned in the Capybara README - https://github.com/teamcapybara/capybara#beware-the-xpath--trap
Note: CSS selectors don't have this issue and for most elements people are selecting read cleaner, which is why Capybara defaults to the :css selector
within('div.whatever') do
find('div.inside-whatever")
end

Selenium css selectors on element with huge list of classes

I've been working on automation of a product that uses Dojo. The html I'm working with is very messy.. I need to click on div that has following css selector
div.dijit.dijitReset.dijitInline.dijitLeft.dijitTextBox.dijitComboBox.dijitDateTextBox.dijitValidationTextBox.dijitTextBoxError.dijitComboBoxError.dijitDateTextBoxError.dijitValidationTextBoxError.dijitError
I'm using firefinder plugin in Firefox and it can see the element all the time, out of 2 chrome plugins I have (CSS selector tester and CSS and Xpath checker) only the first one can find the element.
When I run my selenium code I get org.openqa.selenium.NoSuchElementException.
I tried selecting classes with . and with [class=".."] as well and both failed.
Is there some selenium limitation on how many classes you can have assigned to your element before it stops seeing an element? What stable approach can I use to make my tests work?
Use FirePath plugin in firefox and look for unique classes so you only have 1 unique selector. Also look up CSS selectors, they will help you in the long run
http://www.w3schools.com/cssref/css_selectors.asp

contenteditable nested browser differences

From what I read, there are quite a few browser differences in how contenteditable elements are handled. (i.e. link). When a 'contenteditable=true' element contains a 'contenteditable=false' element, the 'contenteditable=false' element can still be removed with a backspace. Firefox won't let you do that, but it is considered a bug link. Is there a cross-browser way to keep elements in a contenteditable container from ever being removed or modified?
May be Medium.js will be helpful, but that depends on what's your purpose of using contenteditable. At least they say "Medium.js is html5 compliant and has been tested in Firefox, Chrome, Safari, Opera, & IE8+. Browser support is constantly improving!" They have some demos with "widgets" (that's how they call insets with contenteditable="false") on the main page.