2010-07-09 20:20:32 -04:00
|
|
|
module Capybara
|
2010-11-21 08:37:36 -05:00
|
|
|
module Node
|
2010-07-09 20:20:32 -04:00
|
|
|
module Finders
|
2010-07-17 13:05:00 -04:00
|
|
|
|
|
|
|
##
|
|
|
|
#
|
2010-08-27 14:52:06 -04:00
|
|
|
# Find an {Capybara::Element} based on the given arguments. +find+ will raise an error if the element
|
2012-11-20 00:53:13 -05:00
|
|
|
# is not found.
|
2010-07-17 13:05:00 -04:00
|
|
|
#
|
2010-07-19 14:18:16 -04:00
|
|
|
# If the driver is capable of executing JavaScript, +find+ will wait for a set amount of time
|
2010-07-17 13:05:00 -04:00
|
|
|
# and continuously retry finding the element until either the element is found or the time
|
2010-08-27 14:52:06 -04:00
|
|
|
# expires. The length of time +find+ will wait is controlled through {Capybara.default_wait_time}
|
2010-07-17 13:05:00 -04:00
|
|
|
# and defaults to 2 seconds.
|
|
|
|
#
|
2010-07-19 14:18:16 -04:00
|
|
|
# +find+ takes the same options as +all+.
|
2010-07-17 13:05:00 -04:00
|
|
|
#
|
2010-07-19 14:18:16 -04:00
|
|
|
# page.find('#foo').find('.bar')
|
2011-06-27 19:01:46 -04:00
|
|
|
# page.find(:xpath, '//div[contains(., "bar")]')
|
2010-07-19 14:18:16 -04:00
|
|
|
# page.find('li', :text => 'Quox').click_link('Delete')
|
2010-07-17 13:05:00 -04:00
|
|
|
#
|
|
|
|
# @param (see Capybara::Node::Finders#all)
|
2013-02-25 14:34:58 -05:00
|
|
|
# @option options [Boolean] match The matching strategy to use.
|
|
|
|
# @option options [false, Numeric] wait How long to wait for the element to appear.
|
2013-02-24 11:47:53 -05:00
|
|
|
#
|
2013-02-25 14:34:58 -05:00
|
|
|
# @return [Capybara::Element] The found element
|
|
|
|
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
|
2010-07-17 13:05:00 -04:00
|
|
|
#
|
2010-07-19 14:18:16 -04:00
|
|
|
def find(*args)
|
2013-02-25 14:34:58 -05:00
|
|
|
query = Capybara::Query.new(*args)
|
|
|
|
synchronize(query.wait) do
|
2013-02-15 15:43:30 -05:00
|
|
|
if query.match == :smart or query.match == :prefer_exact
|
2013-02-15 14:32:05 -05:00
|
|
|
result = resolve_query(query, true)
|
2013-02-17 10:09:14 -05:00
|
|
|
result = resolve_query(query, false) if result.size == 0 and not query.exact?
|
2013-02-15 14:32:05 -05:00
|
|
|
else
|
|
|
|
result = resolve_query(query)
|
|
|
|
end
|
|
|
|
if query.match == :one or query.match == :smart and result.size > 1
|
|
|
|
raise Capybara::Ambiguous.new("Ambiguous match, found #{result.size} elements matching #{query.description}")
|
|
|
|
end
|
|
|
|
if result.size == 0
|
|
|
|
raise Capybara::ElementNotFound.new("Unable to find #{query.description}")
|
|
|
|
end
|
|
|
|
result.first
|
|
|
|
end.tap(&:allow_reload!)
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
2010-07-19 14:40:28 -04:00
|
|
|
|
2010-07-17 13:05:00 -04:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Find a form field on the page. The field can be found by its name, id or label text.
|
|
|
|
#
|
|
|
|
# @param [String] locator Which field to find
|
|
|
|
# @return [Capybara::Element] The found element
|
|
|
|
#
|
2013-02-24 11:47:53 -05:00
|
|
|
def find_field(locator, options={})
|
|
|
|
find(:field, locator, options)
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
alias_method :field_labeled, :find_field
|
|
|
|
|
2010-07-17 13:05:00 -04:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Find a link on the page. The link can be found by its id or text.
|
|
|
|
#
|
|
|
|
# @param [String] locator Which link to find
|
|
|
|
# @return [Capybara::Element] The found element
|
|
|
|
#
|
2013-02-24 11:47:53 -05:00
|
|
|
def find_link(locator, options={})
|
|
|
|
find(:link, locator, options)
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
|
2010-07-17 13:05:00 -04:00
|
|
|
##
|
|
|
|
#
|
2012-10-26 04:28:27 -04:00
|
|
|
# Find a button on the page. The button can be found by its id, name or value.
|
2010-07-17 13:05:00 -04:00
|
|
|
#
|
|
|
|
# @param [String] locator Which button to find
|
|
|
|
# @return [Capybara::Element] The found element
|
|
|
|
#
|
2013-02-24 11:47:53 -05:00
|
|
|
def find_button(locator, options={})
|
|
|
|
find(:button, locator, options)
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
|
2010-07-17 13:05:00 -04:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Find a element on the page, given its id.
|
|
|
|
#
|
2012-07-10 01:07:38 -04:00
|
|
|
# @param [String] id Which element to find
|
2010-07-17 13:05:00 -04:00
|
|
|
# @return [Capybara::Element] The found element
|
|
|
|
#
|
2013-02-24 11:47:53 -05:00
|
|
|
def find_by_id(id, options={})
|
|
|
|
find(:id, id, options)
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
|
2010-07-17 13:05:00 -04:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Find all elements on the page matching the given selector
|
|
|
|
# and options.
|
|
|
|
#
|
|
|
|
# Both XPath and CSS expressions are supported, but Capybara
|
|
|
|
# does not try to automatically distinguish between them. The
|
|
|
|
# following statements are equivalent:
|
|
|
|
#
|
|
|
|
# page.all(:css, 'a#person_123')
|
|
|
|
# page.all(:xpath, '//a[@id="person_123"]')
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# If the type of selector is left out, Capybara uses
|
2010-08-27 14:52:06 -04:00
|
|
|
# {Capybara.default_selector}. It's set to :css by default.
|
2010-07-17 13:05:00 -04:00
|
|
|
#
|
|
|
|
# page.all("a#person_123")
|
|
|
|
#
|
|
|
|
# Capybara.default_selector = :xpath
|
|
|
|
# page.all('//a[@id="person_123"]')
|
|
|
|
#
|
|
|
|
# The set of found elements can further be restricted by specifying
|
|
|
|
# options. It's possible to select elements by their text or visibility:
|
|
|
|
#
|
|
|
|
# page.all('a', :text => 'Home')
|
|
|
|
# page.all('#menu li', :visible => true)
|
|
|
|
#
|
2011-12-28 16:31:49 -05:00
|
|
|
# @overload all([kind], locator, options)
|
|
|
|
# @param [:css, :xpath] kind The type of selector
|
|
|
|
# @param [String] locator The selector
|
|
|
|
# @option options [String, Regexp] text Only find elements which contain this text or match this regexp
|
|
|
|
# @option options [Boolean] visible Only find elements that are visible on the page. Setting this to false
|
2013-02-24 11:47:53 -05:00
|
|
|
# finds invisible _and_ visible elements.
|
|
|
|
# @option options [Boolean] exact Control whether `is` expressions in the given XPath match exactly or partially
|
2013-01-28 18:58:15 -05:00
|
|
|
# @return [Capybara::Result] A collection of found elements
|
2010-07-17 13:05:00 -04:00
|
|
|
#
|
2010-07-09 20:20:32 -04:00
|
|
|
def all(*args)
|
2013-02-15 14:32:05 -05:00
|
|
|
resolve_query(Capybara::Query.new(*args))
|
2010-12-22 22:24:20 -05:00
|
|
|
end
|
2010-07-09 20:20:32 -04:00
|
|
|
|
2010-12-22 22:24:20 -05:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Find the first element on the page matching the given selector
|
|
|
|
# and options, or nil if no element matches.
|
|
|
|
#
|
2011-12-28 16:31:49 -05:00
|
|
|
# @overload first([kind], locator, options)
|
|
|
|
# @param [:css, :xpath] kind The type of selector
|
|
|
|
# @param [String] locator The selector
|
|
|
|
# @param [Hash] options Additional options; see {all}
|
|
|
|
# @return [Capybara::Element] The found element or nil
|
2010-12-22 22:24:20 -05:00
|
|
|
#
|
|
|
|
def first(*args)
|
2012-01-31 10:28:28 -05:00
|
|
|
all(*args).first
|
2010-12-22 22:24:20 -05:00
|
|
|
end
|
2013-02-15 14:32:05 -05:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def resolve_query(query, exact=nil)
|
|
|
|
elements = synchronize do
|
2013-02-19 12:30:16 -05:00
|
|
|
if query.selector.format==:css
|
2013-02-19 12:03:26 -05:00
|
|
|
base.find_css(query.css)
|
2013-02-16 16:26:01 -05:00
|
|
|
else
|
2013-02-19 12:03:26 -05:00
|
|
|
base.find_xpath(query.xpath(exact))
|
2013-02-16 16:26:01 -05:00
|
|
|
end.map do |node|
|
2013-02-15 14:32:05 -05:00
|
|
|
Capybara::Node::Element.new(session, node, self, query)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
Capybara::Result.new(elements, query)
|
|
|
|
end
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|