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
|
2010-07-19 14:18:16 -04:00
|
|
|
# is not found. The error message can be customized through the +:message+ option.
|
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')
|
|
|
|
# page.find(:xpath, '//div[contains("bar")]')
|
|
|
|
# page.find('li', :text => 'Quox').click_link('Delete')
|
2010-07-17 13:05:00 -04:00
|
|
|
#
|
|
|
|
# @param (see Capybara::Node::Finders#all)
|
2010-08-27 14:52:06 -04:00
|
|
|
# @option options [String] :message An error message in case the element can't be found
|
2010-07-17 13:05:00 -04:00
|
|
|
# @return [Capybara::Element] The found element
|
|
|
|
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
|
|
|
|
#
|
2010-07-19 14:18:16 -04:00
|
|
|
def find(*args)
|
|
|
|
node = wait_conditionally_until { all(*args).first }
|
2010-12-10 08:27:26 -05:00
|
|
|
unless node
|
|
|
|
options = if args.last.is_a?(Hash) then args.last else {} end
|
|
|
|
raise Capybara::ElementNotFound, options[:message] || "Unable to find '#{args[1] || args[0]}'"
|
|
|
|
end
|
2010-07-09 20:20:32 -04:00
|
|
|
return node
|
|
|
|
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
|
|
|
|
#
|
2010-07-09 20:20:32 -04:00
|
|
|
def find_field(locator)
|
2010-08-14 12:35:46 -04:00
|
|
|
find(:xpath, XPath::HTML.field(locator))
|
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
|
|
|
|
#
|
2010-07-09 20:20:32 -04:00
|
|
|
def find_link(locator)
|
2010-08-14 12:35:46 -04:00
|
|
|
find(:xpath, XPath::HTML.link(locator))
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
|
2010-07-17 13:05:00 -04:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Find a button on the page. The link can be found by its id, name or value.
|
|
|
|
#
|
|
|
|
# @param [String] locator Which button to find
|
|
|
|
# @return [Capybara::Element] The found element
|
|
|
|
#
|
2010-07-09 20:20:32 -04:00
|
|
|
def find_button(locator)
|
2010-08-14 12:35:46 -04:00
|
|
|
find(:xpath, XPath::HTML.button(locator))
|
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.
|
|
|
|
#
|
|
|
|
# @param [String] locator Which element to find
|
|
|
|
# @return [Capybara::Element] The found element
|
|
|
|
#
|
2010-07-09 20:20:32 -04:00
|
|
|
def find_by_id(id)
|
|
|
|
find(:css, "##{id}")
|
|
|
|
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)
|
|
|
|
#
|
|
|
|
# @param [:css, :xpath, String] kind_or_locator Either the kind of selector or the selector itself
|
|
|
|
# @param [String] locator The selector
|
|
|
|
# @param [Hash{Symbol => Object}] options Additional options
|
2010-09-06 18:32:22 -04:00
|
|
|
# @option options [String, Regexp] text Only find elements which contain this text or match this regexp
|
2010-07-17 13:05:00 -04:00
|
|
|
# @option options [Boolean] visible Only find elements that are visible on the page
|
|
|
|
# @return [Capybara::Element] The found elements
|
|
|
|
#
|
2010-07-09 20:20:32 -04:00
|
|
|
def all(*args)
|
|
|
|
options = if args.last.is_a?(Hash) then args.pop else {} end
|
|
|
|
|
2010-10-06 15:07:26 -04:00
|
|
|
results = Capybara::Selector.normalize(*args).map do |path|
|
2010-11-12 15:46:46 -05:00
|
|
|
find_in_base(path)
|
2010-07-09 20:20:32 -04:00
|
|
|
end.flatten
|
|
|
|
|
2010-07-09 20:32:43 -04:00
|
|
|
if text = options[:text]
|
|
|
|
text = Regexp.escape(text) unless text.kind_of?(Regexp)
|
2010-07-09 20:20:32 -04:00
|
|
|
|
2010-07-09 20:32:43 -04:00
|
|
|
results = results.select { |node| node.text.match(text) }
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
|
2010-12-22 10:10:42 -05:00
|
|
|
ignore_hidden = if options.has_key?(:visible)
|
|
|
|
options[:visible]
|
|
|
|
else
|
|
|
|
Capybara.ignore_hidden_elements
|
|
|
|
end
|
|
|
|
|
|
|
|
if ignore_hidden
|
2010-07-09 20:32:43 -04:00
|
|
|
results = results.select { |node| node.visible? }
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
|
2010-11-12 15:46:46 -05:00
|
|
|
convert_elements(results)
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
2010-11-12 15:46:46 -05:00
|
|
|
def find_in_base(xpath)
|
|
|
|
base.find(xpath)
|
|
|
|
end
|
|
|
|
|
|
|
|
def convert_elements(elements)
|
2010-11-21 08:37:36 -05:00
|
|
|
elements.map { |element| Capybara::Node::Element.new(session, element) }
|
2010-11-12 15:46:46 -05:00
|
|
|
end
|
|
|
|
|
2010-07-09 20:20:32 -04:00
|
|
|
def wait_conditionally_until
|
2010-11-12 15:46:46 -05:00
|
|
|
if wait? then session.wait_until { yield } else yield end
|
2010-07-09 20:20:32 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|