Permalink
Browse files

Merge branch 'patch-2' of git://github.com/abotalov/capybara into abo…

…talov-patch-2

Conflicts:
	lib/capybara.rb
  • Loading branch information...
jnicklas committed Mar 17, 2013
2 parents 03761db + 7c00c53 commit e5809138e125e2d5510ce92aee80ed5958c019eb
View
@@ -291,13 +291,13 @@ module Driver; end
module RackTest; end
module Selenium; end
+ require 'capybara/helpers'
require 'capybara/session'
require 'capybara/dsl'
require 'capybara/server'
require 'capybara/selector'
require 'capybara/query'
require 'capybara/result'
- require 'capybara/helpers'
require 'capybara/version'
require 'capybara/node/finders'
View
@@ -1,6 +1,8 @@
# encoding: UTF-8
module Capybara
+
+ # @api private
module Helpers
class << self
##
@@ -25,7 +27,7 @@ def normalize_whitespace(text)
# @return [String] Escaped text
#
def to_regexp(text)
- text.is_a?(Regexp) ? text : Regexp.escape(normalize_whitespace(text))
+ text.is_a?(Regexp) ? text : Regexp.new(Regexp.escape(normalize_whitespace(text)))
end
##
@@ -47,4 +49,46 @@ def inject_asset_host(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
+ 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
+ end
+
+ def declension(singular, plural, count)
+ if count == 1
+ singular
+ else
+ plural
+ end
+ end
+ end
+ end
end
@@ -63,12 +63,12 @@ def reload
# until a certain amount of time passes. The amount of time defaults to
# {Capybara.default_wait_time} and can be overriden through the `seconds`
# argument. This time is compared with the system time to see how much
- # time has passed. If the return value of {Time.now} is stubbed out,
+ # time has passed. If the return value of `Time.now` is stubbed out,
# Capybara will raise `Capybara::FrozenInTime`.
#
- # @param [Integer] seconds Number of seconds to retry this block
+ # @param [Integer] seconds Number of seconds to retry this block
# @return [Object] The result of the given block
- # @raise [Capybara::FrozenInTime] If the return value of {Time.now} appears stuck
+ # @raise [Capybara::FrozenInTime] If the return value of `Time.now` appears stuck
#
def synchronize(seconds=Capybara.default_wait_time)
start_time = Time.now
@@ -28,8 +28,12 @@ module Matchers
# page.has_selector?(:xpath, XPath.descendant(:p))
#
# @param (see Capybara::Node::Finders#all)
- # @option options [Integer] :count (nil) Number of times the expression should occur
- # @return [Boolean] If the expression exists
+ # @param options a customizable set of options
+ # @option options [Integer] :count (nil) Number of times the text should occur
+ # @option options [Integer] :minimum (nil) Minimum number of times the text should occur
+ # @option options [Integer] :maximum (nil) Maximum number of times the text should occur
+ # @option options [Range] :between (nil) Range of times that should contain number of times text occurs
+ # @return [Boolean] If the expression exists
#
def has_selector?(*args)
assert_selector(*args)
@@ -71,7 +75,7 @@ def has_no_selector?(*args)
#
# page.assert_selector('li', :text => 'Horse', :visible => true)
#
- # {assert_selector} can also accept XPath expressions generated by the
+ # `assert_selector` can also accept XPath expressions generated by the
# XPath gem:
#
# page.assert_selector(:xpath, XPath.descendant(:p))
@@ -193,18 +197,26 @@ def has_no_css?(path, options={})
# Checks if the page or current node has the given text content,
# ignoring any HTML tags and normalizing whitespace.
#
- # This only matches displayable text and specifically excludes text
- # contained within non-display nodes such as script or head tags.
+ # By default it will check if the text occurs at least once,
+ # but a different number can be specified.
+ #
+ # page.has_text?('lorem ipsum', between: 2..4)
#
- # @param [:all, :visible] type Whether to only check for visible or all text
- # @param [String] content The text to check for
- # @return [Boolean] Whether it exists
+ # This will check if the text occurs from 2 to 4 times.
#
- def has_text?(type=nil, content)
+ # @overload has_text?([type], text, [options])
+ # @param [:all, :visible] type Whether to check for only visible or all text
+ # @param [String, Regexp] text The text/regexp to check for
+ # @param [Hash] options additional options
+ # @option options [Integer] :count (nil) Number of times the text should occur
+ # @option options [Integer] :minimum (nil) Minimum number of times the text should occur
+ # @option options [Integer] :maximum (nil) Maximum number of times the text should occur
+ # @option options [Range] :between (nil) Range of times that should contain number of times text occurs
+ # @return [Boolean] Whether it exists
+ #
+ def has_text?(*args)
synchronize do
- unless Capybara::Helpers.normalize_whitespace(text(type)).match(Capybara::Helpers.to_regexp(content))
- raise ExpectationNotMet
- end
+ raise ExpectationNotMet unless text_found?(*args)
end
return true
rescue Capybara::ExpectationNotMet
@@ -217,17 +229,12 @@ def has_text?(type=nil, content)
# Checks if the page or current node does not have the given text
# content, ignoring any HTML tags and normalizing whitespace.
#
- # This only matches displayable text and specifically excludes text
- # contained within non-display nodes such as script or head tags.
- #
- # @param [String] content The text to check for
- # @return [Boolean] Whether it doesn't exist
+ # @param (see #has_text?)
+ # @return [Boolean] Whether it doesn't exist
#
- def has_no_text?(type=nil, content)
+ def has_no_text?(*args)
synchronize do
- if Capybara::Helpers.normalize_whitespace(text(type)).match(Capybara::Helpers.to_regexp(content))
- raise ExpectationNotMet
- end
+ raise ExpectationNotMet if text_found?(*args)
end
return true
rescue Capybara::ExpectationNotMet
@@ -451,8 +458,16 @@ def ==(other)
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 : {}
+ count = Capybara::Helpers.normalize_whitespace(text(type)).scan(Capybara::Helpers.to_regexp(content)).count
+
+ Capybara::CountHelpers.matches_count?(count, options)
+ end
end
end
end
View
@@ -53,21 +53,6 @@ def matches_filters?(node)
end
end
- def matches_count?(count)
- case
- when options[:between]
- options[:between] === count
- when options[:count]
- options[:count].to_i == count
- when options[:maximum]
- options[:maximum].to_i >= count
- when options[:minimum]
- options[:minimum].to_i <= count
- else
- count > 0
- end
- end
-
def visible
if options.has_key?(:visible)
case @options[:visible]
View
@@ -32,23 +32,13 @@ def initialize(elements, query)
def_delegators :@result, :each, :[], :at, :size, :count, :length, :first, :last, :empty?
def matches_count?
- @query.matches_count?(@result.size)
+ Capybara::CountHelpers.matches_count?(@result.size, @query.options)
end
def failure_message
- message = if @query.options[:count]
- "expected #{@query.description} to be found #{@query.options[:count]} #{declension("time", "times", @query.options[:count])}"
- elsif @query.options[:between]
- "expected #{@query.description} to be found between #{@query.options[:between].first} and #{@query.options[:between].last} times"
- elsif @query.options[:maximum]
- "expected #{@query.description} to be found at most #{@query.options[:maximum]} #{declension("time", "times", @query.options[:maximum])}"
- elsif @query.options[:minimum]
- "expected #{@query.description} to be found at least #{@query.options[:minimum]} #{declension("time", "times", @query.options[:minimum])}"
- else
- "expected to find #{@query.description}"
- end
+ message = Capybara::CountHelpers.failure_message(@query.description, @query.options)
if count > 0
- message << ", found #{count} #{declension("match", "matches")}: " << @result.map(&:text).map(&:inspect).join(", ")
+ message << ", found #{count} #{Capybara::CountHelpers.declension("match", "matches", count)}: " << @result.map(&:text).map(&:inspect).join(", ")
else
message << " but there were no matches"
end
@@ -60,17 +50,7 @@ def failure_message
end
def negative_failure_message
- "expected not to find #{@query.description}, but there #{declension("was", "were")} #{count} #{declension("match", "matches")}"
- end
-
- private
-
- def declension(singular, plural, count=count)
- if count == 1
- singular
- else
- plural
- end
+ failure_message.sub(/(to be found|to find)/, 'not \1')
end
end
end
@@ -33,38 +33,41 @@ def query
end
class HaveText < Matcher
- attr_reader :text, :type
+ attr_reader :type, :content, :options
- def initialize(type, text)
- @type = type
- @text = text
+ def initialize(*args)
+ @type = args.shift if args.first.is_a?(Symbol)
+ @content = args.shift
+ @options = (args.first.is_a?(Hash))? args.first : {}
end
def matches?(actual)
@actual = wrap(actual)
- @actual.has_text?(type, text)
+ @actual.has_text?(type, content, options)
end
def does_not_match?(actual)
@actual = wrap(actual)
- @actual.has_no_text?(type, text)
+ @actual.has_no_text?(type, content, options)
end
def failure_message_for_should
- "expected there to be text #{format(text)} in #{format(@actual.text(type))}"
+ message = Capybara::CountHelpers.failure_message(description, options)
+ message << " in #{format(@actual.text(type))}"
+ message
end
def failure_message_for_should_not
- "expected there not to be text #{format(text)} in #{format(@actual.text(type))}"
+ failure_message_for_should.sub(/(to find)/, 'not \1')
end
def description
- "have text #{format(text)}"
+ "text #{format(content)}"
end
- def format(text)
- text = Capybara::Helpers.normalize_whitespace(text) unless text.is_a? Regexp
- text.inspect
+ def format(content)
+ content = Capybara::Helpers.normalize_whitespace(content) unless content.is_a? Regexp
+ content.inspect
end
end
@@ -106,17 +109,14 @@ def have_xpath(xpath, options={})
HaveSelector.new(:xpath, xpath, options)
end
- def have_css(css, options={})
+ def have_css(css, options={})
HaveSelector.new(:css, css, options)
end
- def have_content(type=nil, text)
- HaveText.new(type, text)
- end
-
- def have_text(type=nil, text)
- HaveText.new(type, text)
+ def have_text(*args)
+ HaveText.new(*args)
end
+ alias_method :have_content, :have_text
def have_title(title)
HaveTitle.new(title)
Oops, something went wrong.

0 comments on commit e580913

Please sign in to comment.