From 66b6aed8b2a1ecd820e5e7d1b2f346747713f676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Nicklas=20and=20Nicklas=20Ramh=C3=B6j?= Date: Fri, 8 Jun 2012 16:47:01 +0200 Subject: [PATCH] Move failure message generatio to result class --- lib/capybara.rb | 1 + lib/capybara/node/finders.rb | 28 ++++++--------------- lib/capybara/node/matchers.rb | 30 +++++++++++++++-------- lib/capybara/node/simple.rb | 8 +++--- lib/capybara/query.rb | 45 +++++++--------------------------- lib/capybara/result.rb | 44 +++++++++++++++++++++++++++++++++ lib/capybara/rspec/matchers.rb | 19 +++----------- lib/capybara/session.rb | 3 ++- 8 files changed, 92 insertions(+), 86 deletions(-) create mode 100644 lib/capybara/result.rb diff --git a/lib/capybara.rb b/lib/capybara.rb index cd0f5b33..e21e9826 100644 --- a/lib/capybara.rb +++ b/lib/capybara.rb @@ -305,6 +305,7 @@ module Capybara autoload :Session, 'capybara/session' autoload :Selector, 'capybara/selector' autoload :Query, 'capybara/query' + autoload :Result, 'capybara/result' autoload :VERSION, 'capybara/version' module Node diff --git a/lib/capybara/node/finders.rb b/lib/capybara/node/finders.rb index d843760d..289ef168 100644 --- a/lib/capybara/node/finders.rb +++ b/lib/capybara/node/finders.rb @@ -24,13 +24,7 @@ module Capybara # @raise [Capybara::ElementNotFound] If the element can't be found before time expires # def find(*args) - query = query(*args) - query.find = true - synchronize do - results = resolve(query) - query.verify!(results) - results.first - end + synchronize { all(*args).find! } end ## @@ -115,7 +109,13 @@ module Capybara # @return [Array[Capybara::Element]] The found elements # def all(*args) - resolve(query(*args)) + query = Capybara::Query.new(*args) + elements = synchronize do + base.find(query.xpath).map do |node| + Capybara::Node::Element.new(session, node, self, query) + end + end + Capybara::Result.new(elements, query) end ## @@ -132,18 +132,6 @@ module Capybara def first(*args) all(*args).first end - - def query(*args) - Capybara::Query.new(self, *args) - end - - def resolve(query) - synchronize do - base.find(query.xpath).map do |node| - Capybara::Node::Element.new(session, node, self, query) - end.select { |node| query.matches_filters?(node) } - end - end end end end diff --git a/lib/capybara/node/matchers.rb b/lib/capybara/node/matchers.rb index 6e471605..35c738bf 100644 --- a/lib/capybara/node/matchers.rb +++ b/lib/capybara/node/matchers.rb @@ -33,15 +33,19 @@ module Capybara # @return [Boolean] If the expression exists # def has_selector?(*args) - synchronize do - results = all(*args) - query(*args).matches_count?(results) or raise Capybara::ExpectationNotMet - results - end + assert_selector!(*args) rescue Capybara::ExpectationNotMet return false end + def assert_selector!(*args) + synchronize do + result = all(*args) + result.matches_count? or raise Capybara::ExpectationNotMet, result.failure_message + end + return true + end + ## # # Checks if a given selector is not on the page or current node. @@ -51,15 +55,19 @@ module Capybara # @return [Boolean] # def has_no_selector?(*args) - synchronize do - results = all(*args) - query(*args).matches_count?(results) and raise Capybara::ExpectationNotMet - results - end + assert_no_selector!(*args) rescue Capybara::ExpectationNotMet return false end + def assert_no_selector!(*args) + synchronize do + result = all(*args) + result.matches_count? and raise Capybara::ExpectationNotMet, result.negative_failure_message + end + return true + end + ## # # Checks if a given XPath expression is on the page or current node. @@ -162,6 +170,7 @@ module Capybara normalize_whitespace(text).include?(normalized_content) or raise ExpectationNotMet end + return true rescue Capybara::ExpectationNotMet return false end @@ -185,6 +194,7 @@ module Capybara !normalize_whitespace(text).include?(normalized_content) or raise ExpectationNotMet end + return true rescue Capybara::ExpectationNotMet return false end diff --git a/lib/capybara/node/simple.rb b/lib/capybara/node/simple.rb index aa04a007..f4c94912 100644 --- a/lib/capybara/node/simple.rb +++ b/lib/capybara/node/simple.rb @@ -122,10 +122,12 @@ module Capybara yield # simple nodes don't need to wait end - def resolve(query) - native.xpath(query.xpath).map do |node| + def all(*args) + query = Capybara::Query.new(*args) + elements = native.xpath(query.xpath).map do |node| self.class.new(node) - end.select { |node| query.matches_filters?(node) } + end + Capybara::Result.new(elements, query) end end end diff --git a/lib/capybara/query.rb b/lib/capybara/query.rb index e591c815..b4a22779 100644 --- a/lib/capybara/query.rb +++ b/lib/capybara/query.rb @@ -1,9 +1,8 @@ module Capybara class Query - attr_accessor :node, :selector, :locator, :options, :xpath, :find, :negative + attr_accessor :selector, :locator, :options, :xpath, :find, :negative - def initialize(node, *args) - @node = node + def initialize(*args) @options = if args.last.is_a?(Hash) then args.pop.dup else {} end unless options.has_key?(:visible) @options[:visible] = Capybara.ignore_hidden_elements @@ -21,18 +20,6 @@ module Capybara @xpath = @selector.call(@locator).to_s end - def failure_message - if find - "Unable to find #{description}" - else - "expected #{description} to return something" - end - end - - def negative_failure_message - "expected #{description} not to return anything" - end - def name; selector.name; end def label; selector.label or selector.name; end @@ -54,34 +41,20 @@ module Capybara true end - def verify!(results) - if find and results.length != 1 - raise Capybara::ElementNotFound, failure_message - end - end - - def error(results) - if negative - negative_failure_message - else - failure_message - end - end - - def matches_count?(nodes) + def matches_count?(count) case - when nodes.empty? + when count.zero? false when options[:between] - options[:between] === nodes.size + options[:between] === count when options[:count] - options[:count].to_i == nodes.size + options[:count].to_i == count when options[:maximum] - options[:maximum].to_i >= nodes.size + options[:maximum].to_i >= count when options[:minimum] - options[:minimum].to_i <= nodes.size + options[:minimum].to_i <= count else - nodes.size > 0 + count > 0 end end end diff --git a/lib/capybara/result.rb b/lib/capybara/result.rb new file mode 100644 index 00000000..4daa13ca --- /dev/null +++ b/lib/capybara/result.rb @@ -0,0 +1,44 @@ +module Capybara + class Result + include Enumerable + + def initialize(elements, query) + @unfiltered_elements = elements + @filtered_elements = elements.select { |node| query.matches_filters?(node) } + @query = query + end + + def each(&block) + @filtered_elements.each(&block) + end + + def first + @filtered_elements.first + end + + def matches_count? + @query.matches_count?(@filtered_elements.size) + end + + def find! + raise Capybara::ElementNotFound, failure_message(true) if @filtered_elements.count != 1 + @filtered_elements.first + end + + def failure_message(find=false) + if find + "Unable to find #{@query.description}" + else + "expected #{@query.description} to return something" + end + end + + def negative_failure_message + "expected #{@query.description} not to return anything" + end + + def empty? + @filtered_elements.empty? + end + end +end diff --git a/lib/capybara/rspec/matchers.rb b/lib/capybara/rspec/matchers.rb index 04bca4af..217e8eef 100644 --- a/lib/capybara/rspec/matchers.rb +++ b/lib/capybara/rspec/matchers.rb @@ -6,24 +6,11 @@ module Capybara end def matches?(actual) - @actual = wrap(actual) - @actual.has_selector?(*@args) + wrap(actual).assert_selector!(*@args) end def does_not_match?(actual) - @actual = wrap(actual) - @actual.has_no_selector?(*@args) - end - - def failure_message_for_should - results = @actual.resolve(query) - query.error(results) - end - - def failure_message_for_should_not - results = @actual.resolve(query) - query.negative = true - query.error(results) + wrap(actual).assert_no_selector!(*@args) end def description @@ -39,7 +26,7 @@ module Capybara end def query - @query ||= @actual.query(*@args) + @query ||= Capybara::Query.new(*@args) end end diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb index 046cd02a..0f67ca82 100644 --- a/lib/capybara/session.rb +++ b/lib/capybara/session.rb @@ -34,7 +34,8 @@ module Capybara :has_no_button?, :has_field?, :has_no_field?, :has_checked_field?, :has_unchecked_field?, :has_no_table?, :has_table?, :unselect, :has_select?, :has_no_select?, :has_selector?, :has_no_selector?, - :click_on, :has_no_checked_field?, :has_no_unchecked_field?, :query + :click_on, :has_no_checked_field?, :has_no_unchecked_field?, :query, + :assert_selector!, :assert_no_selector! ] SESSION_METHODS = [ :body, :html, :current_url, :current_host, :evaluate_script, :source,