teamcapybara--capybara/lib/capybara/node/finders.rb

163 lines
5.6 KiB
Ruby
Raw Normal View History

module Capybara
class Node
module Finders
2010-07-17 17:05:00 +00:00
##
#
# Find an Element based on the given arguments. +locate+ is a stricter version of +find+.
# Find simply returns nil if the element is not found, in contrast +locate+ will raise an
# error if the element is not found. The error message can be customized through the
# +:message+ option.
#
# If the driver is capable of executing JavaScript, locate will wait for a set amount of time
# and continuously retry finding the element until either the element is found or the time
# expires. The length of time +locate+ will wait is controlled through Capybara.default_wait_time
# and defaults to 2 seconds.
#
# Locate takes the same options as +find+ and +all+.
#
# page.locate('#foo').locate('.bar')
# page.locate(:xpath, '//div[contains("bar")]')
# page.locate('li', :text => 'Quox').click_link('Delete')
#
# @param (see Capybara::Node::Finders#all)
# @return [Capybara::Element] The found element
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
#
def locate(*args)
node = wait_conditionally_until { find(*args) }
ensure
options = if args.last.is_a?(Hash) then args.last else {} end
raise Capybara::ElementNotFound, options[:message] || "Unable to locate '#{args[1] || args[0]}'" unless node
return node
end
2010-07-17 17:05:00 +00:00
##
#
# Find works identically to all, except that it returns only the first element found. If the element
# cannot be found on the page, find returns nil. See also +locate+ for a stricter variation of find.
#
# page.find('#contact_form').fill_in('Name', :with => 'John')
#
# @param (see Capybara::Node::Finders#all)
# @return [Capybara::Element] The found element
#
def find(*args)
all(*args).first
end
2010-07-17 17:05:00 +00: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
#
def find_field(locator)
find(:xpath, XPath.field(locator))
end
alias_method :field_labeled, :find_field
2010-07-17 17:05:00 +00: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
#
def find_link(locator)
find(:xpath, XPath.link(locator))
end
2010-07-17 17:05:00 +00: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
#
def find_button(locator)
find(:xpath, XPath.button(locator))
end
2010-07-17 17:05:00 +00:00
##
#
# Find a element on the page, given its id.
#
# @param [String] locator Which element to find
# @return [Capybara::Element] The found element
#
def find_by_id(id)
find(:css, "##{id}")
end
2010-07-17 17:05:00 +00: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
# Capybara.default_selector. It's set to :css by default.
#
# 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
# @option options [String] text Only find elements which contain this text
# @option options [Boolean] visible Only find elements that are visible on the page
# @return [Capybara::Element] The found elements
#
def all(*args)
options = if args.last.is_a?(Hash) then args.pop else {} end
results = XPath.wrap(normalize_locator(*args)).paths.map do |path|
base.find(path)
end.flatten
2010-07-10 00:32:43 +00:00
if text = options[:text]
text = Regexp.escape(text) unless text.kind_of?(Regexp)
2010-07-10 00:32:43 +00:00
results = results.select { |node| node.text.match(text) }
end
if options[:visible] or Capybara.ignore_hidden_elements
2010-07-10 00:32:43 +00:00
results = results.select { |node| node.visible? }
end
results.map { |n| Capybara::Element.new(session, n) }
end
protected
def normalize_locator(kind, locator=nil)
kind, locator = Capybara.default_selector, kind if locator.nil?
locator = XPath.from_css(locator) if kind == :css
locator
end
def wait_conditionally_until
2010-07-10 10:43:29 +00:00
if driver.wait? then session.wait_until { yield } else yield end
end
end
end
end