Specify failure message for selectors

This commit is contained in:
Jonas Nicklas 2011-02-04 16:16:46 +01:00
parent bbcfd02eb7
commit 8c301cedb1
3 changed files with 38 additions and 12 deletions

View File

@ -29,8 +29,11 @@ module Capybara
rescue TimeoutError
end
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]}'"
options = extract_normalized_options(args)
normalized = Capybara::Selector.normalize(*args)
message = options[:message] || "Unable to find #{normalized[:selector].name} #{normalized[:locator].inspect}"
message = normalized[:selector].failure_message.call(self) if normalized[:selector].failure_message
raise Capybara::ElementNotFound, message
end
return node
end
@ -117,7 +120,7 @@ module Capybara
def all(*args)
options = extract_normalized_options(args)
Capybara::Selector.normalize(*args).
Capybara::Selector.normalize(*args)[:xpaths].
map { |path| find_in_base(path) }.flatten.
select { |node| matches_options(node, options) }.
map { |node| convert_element(node) }
@ -139,7 +142,7 @@ module Capybara
def first(*args)
options = extract_normalized_options(args)
Capybara::Selector.normalize(*args).each do |path|
Capybara::Selector.normalize(*args)[:xpaths].each do |path|
find_in_base(path).each do |node|
if matches_options(node, options)
return convert_element(node)

View File

@ -16,18 +16,24 @@ module Capybara
end
def normalize(name_or_locator, locator=nil)
xpath = if locator
all[name_or_locator.to_sym].call(locator)
result = {}
if locator
result[:selector] = all[name_or_locator]
result[:locator] = locator
else
selector = all.values.find { |s| s.match?(name_or_locator) }
selector ||= all[Capybara.default_selector]
selector.call(name_or_locator)
result[:selector] = all.values.find { |s| s.match?(name_or_locator) }
result[:locator] = name_or_locator
end
result[:selector] ||= all[Capybara.default_selector]
xpath = result[:selector].call(result[:locator])
if xpath.respond_to?(:to_xpaths)
xpath.to_xpaths
result[:xpaths] = xpath.to_xpaths
else
[xpath.to_s].flatten
result[:xpaths] = [xpath.to_s].flatten
end
result
end
end
@ -46,6 +52,11 @@ module Capybara
@match
end
def failure_message(&block)
@failure_message = block if block
@failure_message
end
def call(locator)
@xpath.call(locator)
end

View File

@ -79,6 +79,18 @@ shared_examples_for "find" do
end
end
context "with custom selector with failure_message option", :focus => true do
it "it should raise an error with the failure message if the element is not found" do
Capybara.add_selector(:monkey) do
xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
failure_message { |node| node.all(".//*[contains(@id, 'monkey')]").map { |node| node.text }.sort.join(', ') }
end
running do
@session.find(:monkey, '14').text.should == 'Monkey Paul'
end.should raise_error(Capybara::ElementNotFound, "Monkey John, Monkey Paul")
end
end
context "with css as default selector" do
before { Capybara.default_selector = :css }
it "should find the first element using the given locator" do
@ -97,7 +109,7 @@ shared_examples_for "find" do
it "should raise ElementNotFound with a useful default message if nothing was found" do
running do
@session.find(:xpath, '//div[@id="nosuchthing"]').should be_nil
end.should raise_error(Capybara::ElementNotFound, "Unable to find '//div[@id=\"nosuchthing\"]'")
end.should raise_error(Capybara::ElementNotFound, "Unable to find xpath \"//div[@id=\\\"nosuchthing\\\"]\"")
end
it "should accept an XPath instance and respect the order of paths" do