mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
Add section about custom selectors to README
This commit is contained in:
parent
d995bfba42
commit
fed2c5ba94
1 changed files with 32 additions and 5 deletions
37
README.rdoc
37
README.rdoc
|
|
@ -364,7 +364,7 @@ For ultimate control, you can instantiate and use a session manually.
|
|||
end
|
||||
session.click_link 'Sign in'
|
||||
|
||||
== XPath and CSS
|
||||
== XPath, CSS and selectors
|
||||
|
||||
Capybara does not try to guess what kind of selector you are going to give it,
|
||||
if you want to use XPath with your 'within' declarations for example, you'll need
|
||||
|
|
@ -379,24 +379,51 @@ Alternatively you can set the default selector to XPath:
|
|||
Capybara.default_selector = :xpath
|
||||
find('//ul/li').text
|
||||
|
||||
Capybara allows you to add custom selectors, which can be very useful if you
|
||||
find yourself using the same kinds of selectors very often:
|
||||
|
||||
Capybara::Selector.add(:id) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
|
||||
Capybara::Selector.add(:row) { |num| ".//tbody/tr[#{num}]" }
|
||||
|
||||
These must always return an XPath expression as a String, or an XPath expression
|
||||
generated through the XPath gem. You can now use these selectors like this:
|
||||
|
||||
find(:id, 'post_123')
|
||||
find(:row, 3)
|
||||
|
||||
You can specify an optional :for option which will automatically use the
|
||||
selector if it matches the argument to find using ===:
|
||||
|
||||
Capybara::Selector.add(:id, :for => Symbol) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
|
||||
|
||||
Now use it like this:
|
||||
|
||||
find(:post_123)
|
||||
|
||||
This :id selector is already built into Capybara by default, so you don't
|
||||
need to add it yourself.
|
||||
|
||||
== Beware the XPath // trap
|
||||
|
||||
In XPath the expression // means something very specific, and it might not be what
|
||||
you think. Contrary to common belief, // means "anywhere in the document" not "anywhere
|
||||
in the current context". As an example:
|
||||
|
||||
page.find('//body').all('//script')
|
||||
page.find(:xpath, '//body').all(:xpath, '//script')
|
||||
|
||||
You might expect this to find all script tags in the body, but actually, it finds all
|
||||
script tags in the entire document, not only those in the body! What you're looking
|
||||
for is the .// expression which means "any descendant of the current node":
|
||||
|
||||
page.find('//body').all('.//script')
|
||||
page.find(:xpath, '//body').all(:xpath, './/script')
|
||||
|
||||
The same thing goes for within:
|
||||
|
||||
within('//body') do
|
||||
page.find('.//script')
|
||||
within(:xpath, '//body') do
|
||||
page.find(:xpath, './/script')
|
||||
within(:xpath, './/table/tbody') do
|
||||
...
|
||||
end
|
||||
end
|
||||
|
||||
== Gotchas:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue