Learning 'capybara' and bumped into issue of finding the hidden elements through capybara.
In HTML, we have an file field which is 'display: none' by default. HTML element is:
<input class="some_class" id="some_id" name="some_name" type="file">
Now, while I was writing the test cases in capybara using cucumber, I could not find this element in my capybara script. My capybara script is finding the element just like this :
find(:xpath, "//input[#name='some_name']")
Read about the hidden elements and go to know that setting
Capybara.ignore_hidden_elements = false
should solve my problem. But I read somewhere else that above setting is by default. So, tried other option of passing it explicitly. Like:
find(:xpath, "//input[#name='some_name']", :visible => false)
That did not work too. Is there anything else I should try? Will be happy to share more details in case anyone is interested.
The visible option has a few potential values
true or :visible => finds only visible elements
false or :all => finds visible and non-visible elements
:hidden => only find non-visible elements
Therefore if your attempt of find(:xpath, "//input[#name='some_name']", :visible => false) isn't returning an element, there is no element matching that XPath in the page and you need to check that the contents of the page is what you think it is (page.html, page.save_screenshot, etc)
Beyond that your example has a few issues. Firstly, you're falling into the XPath // trap. If (and it should be a big if) you're going to be using XPath queries a lot for finding your elements, get used to starting your queries with .// rather than just // - if you don't you are defeating all of Capybara's scoping on the page (within, chained find, etc). Using CSS selectors doesn't have that issue so makes more sense for most queries where you're not using one of Capybara's built-in selector types.
find("input[name='some_name']", visible: false)
Knowing we are looking for a file input we can go one better by using Capybara's built-in file_field selector and doing
find(:file_field, 'some_name', visible: false)
which is easier to read and explains exactly what you're looking for. Next, since you're finding a file field I assume you'll want to actually add a file to it. This can be problematic since non-visible elements can't generally be interacted with. However since file fields are so often hidden, to allow for styling, there is an option to help with that.
attach_file('some_name', file_path, make_visible: true)
The make_visible: true option will temporarily change the elements CSS to make it visible (you can set it to a hash of CSS values to set rather than true if the default CSS doesn't work on your page), attach the file to it, and then revert the CSS changes.
As a final point, setting Capybara.ignore_hidden_elements = false is a terrible idea if you're testing an app (if just doing automation it's fine) since it leads to tests that aren't actually testing what a user can see/do.
Related
I would like to know how I could program in VBA using Selenium to click/choose on website the first autosuggestion, for example as you can see in the screenshot from amazon.es
Do you have any suggestions?
Tom
Since your situation is replicable I managed to test this two (2) approaches to your situation. I'll just remind you that is always good to show us some code you've tried in your question, so it does not feel like we are helping you from scratch, also try not to rely on images to show us your situation, unless is something that does not change much «like in this case, Amazon.es page». That reminded, let's go to the good part:
1) Advanced 1:
a. Spaces in class are change for dots (if there is any)
b. Requires to understand tag's meaning (a tag is like an object)
'Example
'Clicking first element under tag ("div" alone is a tag)
Selenium.FindElementByCss("div.autocomplete-results-container > div").Click
2) Advanced 2:
a. Requires to understand what ":nth-child" (CSS selector) is
'Example:
'Clicking first child of "div" (Everything inside "div" is a child - starts in 1)
Selenium.FindElementByCss("div.autocomplete-results-container > div:nth-child(1)").Click
I used Firefox to get the xPath property of that suggestion made by the web page. To quickly compare, I copied and pasted, one at a time, the xPath of the first 3 suggestions shown:
/html/body/div[1]/header/div/div[2]/div/div[2]/div[1]/div/div[1]/span[1]
/html/body/div[1]/header/div/div[2]/div/div[2]/div[2]/div/div[1]/span[1]
/html/body/div[1]/header/div/div[2]/div/div[2]/div[3]/div/div[1]/span[1]
So, for the first item, just use the first xPath. If you want to select, for example, the second, just vary the index of the sixth DIV, as we can see in the samples above. Assuming you already have part of the code that navigates to the page, use this, adapting the name of the WebDriver:
objSeleniumDriver.FindElementByXPath("/html/body/div[1]/header/div/div[2]/div/div[2]/div[1]/div/div[1]/span[1]"). click
This is my xpath "//div[#class='city']/h4[text()='Newyork']"
xpaths I can use in Geb but I want to write similar expression in CSS or better Groovy-ish, Gebish locator.
I have tried
.city>h4:'Newyork'
.city>h4:contains('Newyork')
but none worked.
I have referred https://sqa.stackexchange.com/questions/362/a-way-to-match-on-text-using-css-locators
Geb has an ability to further filter down the elements matched using a CSS selector by passing a map of element attributes to its methods together with that selector. It also introduces a special attribute for matching text of a node. Your selector would look like this:
$('div.city > h4', text: 'Newyork')
Please note that this works by fetching text for every matched element and checking it against the provided value, that is it does the work on the JVM side and not in the browser, which means that you want your css selector to be as specific as possible and match as little elements as possible otherwise the selector will be very slow.
Is there a way to tell Capybara to ignore a div when searching a page.
Something like
page.assert_no_selector('a', :unless => '.an-excused-class a')
Alternatively, is there a way in a specific step to tell Capybara to not count hidden elements. I've seen some ways to do that globally, but that's not what I want.
TIA
There is no way in Capybaras default assertions to tell it to ignore some elements that match a selector.
By default Capybara won't find hidden elements, if you have overridden that by changing the Capybara.ignore_hidden_elements option you can specify the :visible option in the assertion
page.assert_no_selector('a', visible: true)
the visible option can take a number of values:
true or :visible => only find visible elements
false or :all => find elements no matter their visibility
:hidden => only find non-visible elements
If there are two divs that are the same, but one is hidden, capybara will automatically only look for the visible div.
However if you have the opposite value in the global settings for capybara using the option:
:visible
ie.
page.should have_css("ol li", :visible => true)
Will force it to only check for the visible div.
However if using the visibility option is a complete no go, there could be other ways to tell if its there.
Using a count method could tell you if the correct number of the named div are on the page:
page.should have_css("ol li", :count => 2)
Or if you know the div is always going to be, say the third:
page.all("ol li")[3]
Finally, if those divs are enclosed in separate blocks of HTML that are labelled differently - you can look within the HTML to find them by chaining with capybara:
page.find('#foo').find('.bar')
A good source of this information :
http://www.rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Finders#find-instance_method
The validator at http://jigsaw.w3.org/css-validator/ says that the value 'text' for 'user-select' is not valid. For a css rule with this code in it:
user-select: text;
the validator says:
text is not a user-select value : text text
Presumably this is because of this behavior, specified at (the outdated) http://www.w3.org/TR/2000/WD-css3-userint-20000216#user-select:
This property is not inherited, but it does affect children in the
same way that display: none does, it limits it. That is if an element
is user-select: none, it doesn't matter what the user-select value is
of its children, the element's contents or it's childrens contents
cannot be selected.
Also, I only see the attribute value 'text' specified in that out-of-date css3 doc from w3.org:
http://www.w3.org/TR/2000/WD-css3-userint-20000216#user-select
and not in the latest one: http://www.w3.org/TR/css3-ui/
Additionally, searching 'whatwg.org' yields nothing.
Any ideas if 'user-select: text' is valid css3, and if not, what should be used instead?
This would be used, for example, when overriding 'user-select: none' rules applied to containers of text and ancestor containers.
You are getting this wrong. user-select:text doesn't mean it would select text only. It's default value of user-select property. W3C describe it this way:
The element's contents follow a standard text content selection model.
And Also MDN syas something same:
-moz-none The text of the element and sub-elements cannot be selected,
but selection can be enabled on sub-elements using
-moz-user-select:text .
So I don't think this should prevent selecting images or boxes.
As far as I know user-select:text is useful when you have user-select:none for most or all of your elements and you have a textbox or text area that is kind of output and you want it be selectable for copying and pasting.
It seems if you use -webkit- prefix it works for me. I'm sure it works with -moz- prefix too. Test this fiddle in your browser. I don't know why user-select:text is not working on my Chrome 13 Mac?
I would like to dump all css key/value pairs for an html tag.
In particular, I would like to learn the css properties for <audio> tag, so I can try to customize the look.
document.getElementById('myaudio').style returns a CSSStyleDeclaration object but length returns 0 and I cannot figure out to iterate over the key/value pairs.
Thank you
Try Firebug for firefox. It allows you to view the CSS and properties of any element on a webpage and allows in-page editing so you can customise it on the fly until you are happy without having to create hard and fast changes
You can't iterate over the keys in the style object. It's simply impossible.
The best answer is what Chris said. Use Firebug in Firefox, or similar tools in the other browsers, which can do the work for you and tell you exactly what CSS properties apply to the element.
(Make sure that you tell the tool to show you "user agent styles", not just styles you've added, so you can see what styles the browser applies automatically.)