Use custom selectors in matchers

This continues the centralization of XPath generation
and failure messages.
This commit is contained in:
Adam McCrea 2011-08-27 17:54:55 -04:00 committed by Anders Törnqvist and Kim Burgestrand
parent 7a383b4251
commit fd7cf4a4bc
3 changed files with 49 additions and 51 deletions

View File

@ -109,7 +109,7 @@ module Capybara
# @return [Array[Capybara::Element]] The found elements # @return [Array[Capybara::Element]] The found elements
# #
def all(*args) def all(*args)
options = extract_normalized_options(args) args, options = extract_normalized_options(args)
selector = Capybara::Selector.normalize(*args) selector = Capybara::Selector.normalize(*args)
selector.xpaths. selector.xpaths.
@ -132,7 +132,7 @@ module Capybara
# @return [Capybara::Element] The found element or nil # @return [Capybara::Element] The found element or nil
# #
def first(*args) def first(*args)
options = extract_normalized_options(args) args, options = extract_normalized_options(args)
found_elements = [] found_elements = []
selector = Capybara::Selector.normalize(*args) selector = Capybara::Selector.normalize(*args)
@ -150,10 +150,11 @@ module Capybara
protected protected
def raise_find_error(*args) def raise_find_error(*args)
options = extract_normalized_options(args) args, options = extract_normalized_options(args)
normalized = Capybara::Selector.normalize(*args) normalized = Capybara::Selector.normalize(*args)
message = options[:message] || "Unable to find #{normalized.name} #{normalized.locator.inspect}" message = options[:message] || "Unable to find #{normalized.name} #{normalized.locator.inspect}"
message = normalized.failure_message.call(self, normalized) if normalized.failure_message message = normalized.failure_message.call(self, normalized) if normalized.failure_message
raise Capybara::ElementNotFound, message raise Capybara::ElementNotFound, message
end end
@ -178,7 +179,7 @@ module Capybara
options[:selected] = [selected].flatten options[:selected] = [selected].flatten
end end
options [args.push(options), options]
end end
def matches_options(node, options) def matches_options(node, options)

View File

@ -157,7 +157,7 @@ module Capybara
# @return [Boolean] If the selector exists # @return [Boolean] If the selector exists
# #
def has_css?(path, options={}) def has_css?(path, options={})
has_xpath?(XPath.css(path), options) has_selector?(:css, path, options)
end end
## ##
@ -169,7 +169,7 @@ module Capybara
# @return [Boolean] # @return [Boolean]
# #
def has_no_css?(path, options={}) def has_no_css?(path, options={})
has_no_xpath?(XPath.css(path), options) has_no_selector?(:css, path, options)
end end
## ##
@ -181,7 +181,7 @@ module Capybara
# @return [Boolean] Whether it exists # @return [Boolean] Whether it exists
# #
def has_content?(content) def has_content?(content)
has_xpath?(XPath::HTML.content(normalize_whitespace(content))) has_selector?(:content, normalize_whitespace(content))
end end
## ##
@ -193,7 +193,7 @@ module Capybara
# @return [Boolean] Whether it exists # @return [Boolean] Whether it exists
# #
def has_no_content?(content) def has_no_content?(content)
has_no_xpath?(XPath::HTML.content(normalize_whitespace(content))) has_no_selector?(:content, normalize_whitespace(content))
end end
## ##
@ -251,7 +251,7 @@ module Capybara
# @return [Boolean] Whether it exists # @return [Boolean] Whether it exists
# #
def has_link?(locator, options={}) def has_link?(locator, options={})
has_xpath?(XPath::HTML.link(locator, options)) has_selector?(:link, locator, options)
end end
## ##
@ -263,7 +263,7 @@ module Capybara
# @return [Boolean] Whether it doesn't exist # @return [Boolean] Whether it doesn't exist
# #
def has_no_link?(locator, options={}) def has_no_link?(locator, options={})
has_no_xpath?(XPath::HTML.link(locator, options)) has_no_selector?(:link, locator, options)
end end
## ##
@ -275,7 +275,7 @@ module Capybara
# @return [Boolean] Whether it exists # @return [Boolean] Whether it exists
# #
def has_button?(locator) def has_button?(locator)
has_xpath?(XPath::HTML.button(locator)) has_selector?(:button, locator)
end end
## ##
@ -287,7 +287,7 @@ module Capybara
# @return [Boolean] Whether it doesn't exist # @return [Boolean] Whether it doesn't exist
# #
def has_no_button?(locator) def has_no_button?(locator)
has_no_xpath?(XPath::HTML.button(locator)) has_no_selector?(:button, locator)
end end
## ##
@ -306,8 +306,7 @@ module Capybara
# @return [Boolean] Whether it exists # @return [Boolean] Whether it exists
# #
def has_field?(locator, options={}) def has_field?(locator, options={})
options, with = split_options(options, :with) has_selector?(:field, locator, options)
has_xpath?(XPath::HTML.field(locator, options), with)
end end
## ##
@ -320,8 +319,7 @@ module Capybara
# @return [Boolean] Whether it doesn't exist # @return [Boolean] Whether it doesn't exist
# #
def has_no_field?(locator, options={}) def has_no_field?(locator, options={})
options, with = split_options(options, :with) has_no_selector?(:field, locator, options)
has_no_xpath?(XPath::HTML.field(locator, options), with)
end end
## ##
@ -334,7 +332,7 @@ module Capybara
# @return [Boolean] Whether it exists # @return [Boolean] Whether it exists
# #
def has_checked_field?(locator) def has_checked_field?(locator)
has_xpath?(XPath::HTML.field(locator), :checked => true) has_selector?(:field, locator, :checked => true)
end end
## ##
@ -347,7 +345,7 @@ module Capybara
# @return [Boolean] Whether it doesn't exists # @return [Boolean] Whether it doesn't exists
# #
def has_no_checked_field?(locator) def has_no_checked_field?(locator)
has_no_xpath?(XPath::HTML.field(locator), :checked => true) has_no_selector?(:field, locator, :checked => true)
end end
## ##
@ -360,7 +358,7 @@ module Capybara
# @return [Boolean] Whether it exists # @return [Boolean] Whether it exists
# #
def has_unchecked_field?(locator) def has_unchecked_field?(locator)
has_xpath?(XPath::HTML.field(locator), :unchecked => true) has_selector?(:field, locator, :unchecked => true)
end end
## ##
@ -373,7 +371,7 @@ module Capybara
# @return [Boolean] Whether it doesn't exists # @return [Boolean] Whether it doesn't exists
# #
def has_no_unchecked_field?(locator) def has_no_unchecked_field?(locator)
has_no_xpath?(XPath::HTML.field(locator), :unchecked => true) has_no_selector?(:field, locator, :unchecked => true)
end end
## ##
@ -400,8 +398,7 @@ module Capybara
# @return [Boolean] Whether it exists # @return [Boolean] Whether it exists
# #
def has_select?(locator, options={}) def has_select?(locator, options={})
options, selected = split_options(options, :selected) has_selector?(:select, locator, options)
has_xpath?(XPath::HTML.select(locator, options), selected)
end end
## ##
@ -413,8 +410,7 @@ module Capybara
# @return [Boolean] Whether it doesn't exist # @return [Boolean] Whether it doesn't exist
# #
def has_no_select?(locator, options={}) def has_no_select?(locator, options={})
options, selected = split_options(options, :selected) has_no_selector?(:select, locator, options)
has_no_xpath?(XPath::HTML.select(locator, options), selected)
end end
## ##
@ -435,7 +431,7 @@ module Capybara
# @return [Boolean] Whether it exist # @return [Boolean] Whether it exist
# #
def has_table?(locator, options={}) def has_table?(locator, options={})
has_xpath?(XPath::HTML.table(locator, options)) has_selector?(:table, locator, options)
end end
## ##
@ -447,14 +443,7 @@ module Capybara
# @return [Boolean] Whether it doesn't exist # @return [Boolean] Whether it doesn't exist
# #
def has_no_table?(locator, options={}) def has_no_table?(locator, options={})
has_no_xpath?(XPath::HTML.table(locator, options)) has_no_selector?(:table, locator, options)
end
protected
def split_options(options, key)
options = options.dup
[options, if options.has_key?(key) then {key => options.delete(key)} else {} end]
end end
## ##

View File

@ -35,7 +35,7 @@ module Capybara
end end
normalized.selector ||= all[Capybara.default_selector] normalized.selector ||= all[Capybara.default_selector]
xpath = normalized.selector.call(normalized.locator) xpath = normalized.selector.call(normalized.locator, normalized.options)
if xpath.respond_to?(:to_xpaths) if xpath.respond_to?(:to_xpaths)
normalized.xpaths = xpath.to_xpaths normalized.xpaths = xpath.to_xpaths
else else
@ -73,8 +73,8 @@ module Capybara
@failure_message @failure_message
end end
def call(locator) def call(locator, options={})
@xpath.call(locator) @xpath.call(locator, options)
end end
def match?(locator) def match?(locator)
@ -84,7 +84,7 @@ module Capybara
end end
Capybara.add_selector(:xpath) do Capybara.add_selector(:xpath) do
xpath { |xpath| xpath } xpath { |xpath, options| xpath }
end end
Capybara.add_selector(:css) do Capybara.add_selector(:css) do
@ -92,51 +92,51 @@ Capybara.add_selector(:css) do
end end
Capybara.add_selector(:id) do Capybara.add_selector(:id) do
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] } xpath { |id, options| XPath.descendant[XPath.attr(:id) == id.to_s] }
match { |value| value.is_a?(Symbol) } match { |value| value.is_a?(Symbol) }
end end
Capybara.add_selector(:field) do Capybara.add_selector(:field) do
xpath { |locator| XPath::HTML.field(locator) } xpath { |locator, options| XPath::HTML.field(locator) }
end end
Capybara.add_selector(:link_or_button) do Capybara.add_selector(:link_or_button) do
xpath { |locator| XPath::HTML.link_or_button(locator) } xpath { |locator, options| XPath::HTML.link_or_button(locator) }
failure_message { |node, selector| "no link or button '#{selector.locator}' found" } failure_message { |node, selector| "no link or button '#{selector.locator}' found" }
end end
Capybara.add_selector(:link) do Capybara.add_selector(:link) do
xpath { |locator| XPath::HTML.link(locator) } xpath { |locator, options| XPath::HTML.link(locator, options) }
failure_message { |node, selector| "no link with title, id or text '#{selector.locator}' found" } failure_message { |node, selector| "no link with title, id or text '#{selector.locator}' found" }
end end
Capybara.add_selector(:button) do Capybara.add_selector(:button) do
xpath { |locator| XPath::HTML.button(locator) } xpath { |locator, options| XPath::HTML.button(locator) }
failure_message { |node, selector| "no button with value or id or text '#{selector.locator}' found" } failure_message { |node, selector| "no button with value or id or text '#{selector.locator}' found" }
end end
Capybara.add_selector(:fillable_field) do Capybara.add_selector(:fillable_field) do
xpath { |locator| XPath::HTML.fillable_field(locator) } xpath { |locator, options| XPath::HTML.fillable_field(locator, options) }
failure_message { |node, selector| "no text field, text area or password field with id, name, or label '#{selector.locator}' found" } failure_message { |node, selector| "no text field, text area or password field with id, name, or label '#{selector.locator}' found" }
end end
Capybara.add_selector(:radio_button) do Capybara.add_selector(:radio_button) do
xpath { |locator| XPath::HTML.radio_button(locator) } xpath { |locator, options| XPath::HTML.radio_button(locator, options) }
failure_message { |node, selector| "no radio button with id, name, or label '#{selector.locator}' found" } failure_message { |node, selector| "no radio button with id, name, or label '#{selector.locator}' found" }
end end
Capybara.add_selector(:checkbox) do Capybara.add_selector(:checkbox) do
xpath { |locator| XPath::HTML.checkbox(locator) } xpath { |locator, options| XPath::HTML.checkbox(locator, options) }
failure_message { |node, selector| "no checkbox with id, name, or label '#{selector.locator}' found" } failure_message { |node, selector| "no checkbox with id, name, or label '#{selector.locator}' found" }
end end
Capybara.add_selector(:select) do Capybara.add_selector(:select) do
xpath { |locator| XPath::HTML.select(locator) } xpath { |locator, options| XPath::HTML.select(locator, options) }
failure_message { |node, selector| "no select box with id, name, or label '#{selector.locator}' found" } failure_message { |node, selector| "no select box with id, name, or label '#{selector.locator}' found" }
end end
Capybara.add_selector(:option) do Capybara.add_selector(:option) do
xpath { |locator| XPath::HTML.option(locator) } xpath { |locator, options| XPath::HTML.option(locator) }
failure_message do |node, selector| failure_message do |node, selector|
"no option with text '#{selector.locator}'".tap do |message| "no option with text '#{selector.locator}'".tap do |message|
message << " in the select box" if node.tag_name == 'select' message << " in the select box" if node.tag_name == 'select'
@ -145,6 +145,14 @@ Capybara.add_selector(:option) do
end end
Capybara.add_selector(:file_field) do Capybara.add_selector(:file_field) do
xpath { |locator| XPath::HTML.file_field(locator) } xpath { |locator, options| XPath::HTML.file_field(locator, options) }
failure_message { |node, selector| "no file field with id, name, or label '#{selector.locator}' found" } failure_message { |node, selector| "no file field with id, name, or label '#{selector.locator}' found" }
end end
Capybara.add_selector(:content) do
xpath { |content, options| XPath::HTML.content(content) }
end
Capybara.add_selector(:table) do
xpath { |locator, options| XPath::HTML.table(locator, options) }
end