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.
Related
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.
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
I'm considering the use of the <span> tag for grouping a set of arbitrary elements together, but I don't want it to have any visual impact in the structure of the document whatsoever.
I want to use that tag for later manipulating the set of elements within it with JavaScript in some way, such as e.g. detecting whether the mouse entered or left the region, etc.
My question is whether there are cases when the presence of the span tag will disrupt the flow of the document, making the elements within it or the elements around it behave differently from when it's absent.
Of course, I'm aware the presence of an additional node on the DOM can disrupt some CSS selectors which are not expecting the span, and I'm also aware that styling the span can cause the layout to change (e.g. if I added a border I could cause elements to wrap to the next line, etc.). But aside from that, is the span tag neutral? If not, how should I go about figuring in what cases it is not?
Thanks in advance!
-- edit --
I tend to forget that it's wrong to put block-level elements inside inline elements like span, so I can't use span to wrap just everything the way I intended.
So, in case one or more of the elements I'm grouping is block-level, should I use a div instead?
The <span> element is defined to be an inline (text-level) element. Otherwise, it is semantically empty and layout-neutral.
By HTML syntax, the <span> element must not contain block elements, such as <div>. If you violate this, there is no specification of what browsers should no. It sounds pointless to play with that, when you can use the <div> element. It is defined to be a block element, which means that in rendering it by default starts on a new line and any content after it starts on a new line (but no empty lines are generated by this behavior). Otherwise, it is semantically empty and layout-neutral.
Directly of http://www.w3.org/wiki/HTML/Elements/span
The element doesn't mean anything on its own, but can be useful when used together with the global attributes, e.g. class, lang, or dir. It represents its children.
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 used set to insert a value in a text field under a div.
Below is the approach that I've used without success. This is the only way I was able to identify the element. When I tried to identify text field by name was not recognized.
#browser.div(:evaluation, :id => "evaluation_form_attributes").text_field(:id => "evaluation_form_name")
#browser.set('Teacher Evaluation Form')
The following error was displayed:
undefined method `set' for #<Watir::IE:0x4dd9348>
This is the HTML:
div id="evaluation_form_attributes"
Evaluation name:
input id="evaluation_form_name" type="text" size="50" name="evaluation_form[name]" maxlength="30"
Try this:
browser.text_field(:id => "evaluation_form_name").set 'Teacher Evaluation Form'
Is there an iframe involved perhaps? if you know the thing is there, and you are sure of the ID, and watir cannot locate it, then usually it's because that part of the page is inside of a frame.
To work with elements that are inside of a frame, you must specify the frame, then the element
browser.frame(:how, what).element(:how, what).method etc.
see http://wiki.openqa.org/display/WTR/Frames for more info
To set a value for a text field you simply need to find it and set it. The setting part you already know (set), so you need to string together something that finds the text field.
if Zejiko's answer doesn't work because of "unable to locate element" then it's not the setting that's failing, it's finding the text field. Use Firebug (in Firefox) or some kind of DOM toolkit (Tools>Developer Tools or F12 in IE8) to find the text field and see what kind of attributes it has.
Ensure the id is really "evaluation_form_name". This is case sensitive and sensitive to leading/trailing spaces. You could try the following to make your search broader:
#browser.text_field(:id => /evaluation/).set 'Teacher Evaluation Form'
This uses a regular expression to identify the id. You can search by many things, not just :id, and you can use more than one. For example:
#browser.text_field(:id => /eval/, :index => 2)
finds the second text field whose id contains "eval".
What you can use to identify the text field can be found here: https://github.com/watir/watir/wiki/HTML-Elements-Supported-by-Watir