From 415e2db70d3b19b46a4d3d0fe62f50400f9d2b61 Mon Sep 17 00:00:00 2001 From: Jonas Nicklas Date: Sun, 17 Mar 2013 15:48:04 +0100 Subject: [PATCH] Refactor and document --- lib/capybara/helpers.rb | 175 +++++++++++++++++++-------------- lib/capybara/node/matchers.rb | 9 +- lib/capybara/result.rb | 6 +- lib/capybara/rspec/matchers.rb | 2 +- 4 files changed, 109 insertions(+), 83 deletions(-) diff --git a/lib/capybara/helpers.rb b/lib/capybara/helpers.rb index 22201630..185d92bb 100644 --- a/lib/capybara/helpers.rb +++ b/lib/capybara/helpers.rb @@ -4,90 +4,117 @@ module Capybara # @api private module Helpers - class << self - ## - # - # Normalizes whitespace space by stripping leading and trailing - # whitespace and replacing sequences of whitespace characters - # with a single space. - # - # @param [String] text Text to normalize - # @return [String] Normalized text - # - def normalize_whitespace(text) - text.to_s.gsub(/[[:space:]]+/, ' ').strip - end + extend self - ## - # - # Escapes any characters that would have special meaning in a regexp - # if text is not a regexp - # - # @param [String] text Text to escape - # @return [String] Escaped text - # - def to_regexp(text) - text.is_a?(Regexp) ? text : Regexp.new(Regexp.escape(normalize_whitespace(text))) - end + ## + # + # Normalizes whitespace space by stripping leading and trailing + # whitespace and replacing sequences of whitespace characters + # with a single space. + # + # @param [String] text Text to normalize + # @return [String] Normalized text + # + def normalize_whitespace(text) + text.to_s.gsub(/[[:space:]]+/, ' ').strip + end - ## - # - # Injects a `` tag into the given HTML code, pointing to - # `Capybara.asset_host`. - # - # @param [String] html HTML code to inject into - # @param [String] The modified HTML code - # - def inject_asset_host(html) - if Capybara.asset_host - if Nokogiri::HTML(html).css("base").empty? and match = html.match(//) - html.clone.insert match.end(0), "" - end - else - html + ## + # + # Escapes any characters that would have special meaning in a regexp + # if text is not a regexp + # + # @param [String] text Text to escape + # @return [String] Escaped text + # + def to_regexp(text) + text.is_a?(Regexp) ? text : Regexp.new(Regexp.escape(normalize_whitespace(text))) + end + + ## + # + # Injects a `` tag into the given HTML code, pointing to + # `Capybara.asset_host`. + # + # @param [String] html HTML code to inject into + # @param [String] The modified HTML code + # + def inject_asset_host(html) + if Capybara.asset_host + if Nokogiri::HTML(html).css("base").empty? and match = html.match(//) + html.clone.insert match.end(0), "" end + else + html end end - end - # @api private - module CountHelpers - class << self - def matches_count?(count, options={}) - case - when options[:between] - options[:between] === count - when options[:count] - Integer(options[:count]) == count - when options[:maximum] - Integer(options[:maximum]) >= count - when options[:minimum] - Integer(options[:minimum]) <= count - else - count > 0 - end + ## + # + # Checks if the given count matches the given count options. By default, + # when no options are given, count should be larger than zero. + # + # @param [Integer] count The actual number. Should be coercible via Integer() + # @option [Range] between Count must be within the given range + # @option [Integer] count Count must be exactly this + # @option [Integer] maximum Count must be smaller than or equal to this value + # @option [Integer] minimum Count must be larger than or equal to this value + # + def matches_count?(count, options={}) + case + when options[:between] + options[:between] === count + when options[:count] + Integer(options[:count]) == count + when options[:maximum] + Integer(options[:maximum]) >= count + when options[:minimum] + Integer(options[:minimum]) <= count + else + count > 0 end + end - def failure_message(description, options={}) - message = "expected to find #{description}" - if options[:count] - message << " #{options[:count]} #{declension('time', 'times', options[:count])}" - elsif options[:between] - message << " between #{options[:between].first} and #{options[:between].last} times" - elsif options[:maximum] - message << " at most #{options[:maximum]} #{declension('time', 'times', options[:maximum])}" - elsif options[:minimum] - message << " at least #{options[:minimum]} #{declension('time', 'times', options[:minimum])}" - end - message + ## + # + # Generates a failure message given a description of the query and count + # options. + # + # @param [String] description Description of a query + # @option [Range] between Count should have been within the given range + # @option [Integer] count Count should have been exactly this + # @option [Integer] maximum Count should have been smaller than or equal to this value + # @option [Integer] minimum Count should have been larger than or equal to this value + # + def failure_message(description, options={}) + message = "expected to find #{description}" + if options[:count] + message << " #{options[:count]} #{declension('time', 'times', options[:count])}" + elsif options[:between] + message << " between #{options[:between].first} and #{options[:between].last} times" + elsif options[:maximum] + message << " at most #{options[:maximum]} #{declension('time', 'times', options[:maximum])}" + elsif options[:minimum] + message << " at least #{options[:minimum]} #{declension('time', 'times', options[:minimum])}" end + message + end - def declension(singular, plural, count) - if count == 1 - singular - else - plural - end + ## + # + # A poor man's `pluralize`. Given two declensions, one singular and one + # plural, as well as a count, this will pick the correct declension. This + # way we can generate gramatically correct error message. + # + # @param [String] singular The singular form of the word + # @param [String] plural The plural form of the word + # @param [Integer] count The number of items + # + def declension(singular, plural, count) + if count == 1 + singular + else + plural end end end diff --git a/lib/capybara/node/matchers.rb b/lib/capybara/node/matchers.rb index ab95a6c6..b2be1003 100644 --- a/lib/capybara/node/matchers.rb +++ b/lib/capybara/node/matchers.rb @@ -458,15 +458,14 @@ module Capybara self.eql?(other) or (other.respond_to?(:base) and base == other.base) end - private + private def text_found?(*args) type = args.shift if args.first.is_a?(Symbol) or args.first.nil? - content = args.shift - options = (args.first.is_a?(Hash))? args.first : {} + content, options = args count = Capybara::Helpers.normalize_whitespace(text(type)).scan(Capybara::Helpers.to_regexp(content)).count - - Capybara::CountHelpers.matches_count?(count, options) + + Capybara::Helpers.matches_count?(count, options || {}) end end end diff --git a/lib/capybara/result.rb b/lib/capybara/result.rb index efd9c330..0dc43401 100644 --- a/lib/capybara/result.rb +++ b/lib/capybara/result.rb @@ -32,13 +32,13 @@ module Capybara def_delegators :@result, :each, :[], :at, :size, :count, :length, :first, :last, :empty? def matches_count? - Capybara::CountHelpers.matches_count?(@result.size, @query.options) + Capybara::Helpers.matches_count?(@result.size, @query.options) end def failure_message - message = Capybara::CountHelpers.failure_message(@query.description, @query.options) + message = Capybara::Helpers.failure_message(@query.description, @query.options) if count > 0 - message << ", found #{count} #{Capybara::CountHelpers.declension("match", "matches", count)}: " << @result.map(&:text).map(&:inspect).join(", ") + message << ", found #{count} #{Capybara::Helpers.declension("match", "matches", count)}: " << @result.map(&:text).map(&:inspect).join(", ") else message << " but there were no matches" end diff --git a/lib/capybara/rspec/matchers.rb b/lib/capybara/rspec/matchers.rb index 626285de..4267accc 100644 --- a/lib/capybara/rspec/matchers.rb +++ b/lib/capybara/rspec/matchers.rb @@ -52,7 +52,7 @@ module Capybara end def failure_message_for_should - message = Capybara::CountHelpers.failure_message(description, options) + message = Capybara::Helpers.failure_message(description, options) message << " in #{format(@actual.text(type))}" message end