Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: twalpole/capybara
...
head fork: twalpole/capybara
  • 8 commits
  • 4 files changed
  • 0 commit comments
  • 2 contributors
Commits on Jan 17, 2014
tmertens Allow expectations on element count in Finders#all().
- all() will now wait for the number of elements returned to match
  the expected :count, :minimum, :maximum, :between query options.
- Helpers#matches_count? returns true if none of the count  query
  options are specified.
- Helpers#matches_count? tests multiple conditions if more than one
  is specified. If :count is specified, however, it ignores others.
- Matchers#assert_selector allows checking for 0 matches when
  the query options include {:count => 0}
828bc2e
tmertens Fix spec failures d1e8828
tmertens Add specs for new query options on Finders#all method c94e44b
tmertens Un-DRY specs b43fadc
Commits on Jan 31, 2014
tmertens Use let instead of tap cdd3184
tmertens Remove options hash 850292f
Commits on Feb 03, 2014
tmertens Use options hash from query object 5ae5fb0
Commits on Feb 20, 2014
@jnicklas jnicklas Merge pull request #1232 from centro/fix-count-query-options
Enable use of count query options with Capybara::Node::Finders#all
595cd4a
View
32 lib/capybara/helpers.rb
@@ -51,8 +51,10 @@ def inject_asset_host(html)
##
#
- # Checks if the given count matches the given count options. By default,
- # when no options are given, count should be larger than zero.
+ # Checks if the given count matches the given count options.
+ # Defaults to true if no options are specified. If multiple
+ # options are provided, it tests that all conditions are met;
+ # however, if :count is supplied, all other options are ignored.
#
# @param [Integer] count The actual number. Should be coercible via Integer()
# @option [Range] between Count must be within the given range
@@ -61,17 +63,23 @@ def inject_asset_host(html)
# @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
+ return (Integer(options[:count]) == count) if options[:count]
+ return false if options[:maximum] && (Integer(options[:maximum]) < count)
+ return false if options[:minimum] && (Integer(options[:minimum]) > count)
+ return false if options[:between] && !(options[:between] === count)
+ return true
+ end
+
+ ##
+ #
+ # Checks if a count of 0 is valid for the given options hash.
+ # Returns false if options hash does not specify any count options.
+ #
+ def expects_none?(options={})
+ if [:count, :maximum, :minimum, :between].any? { |k| options.has_key? k }
+ matches_count?(0,options)
else
- count > 0
+ false
end
end
View
23 lib/capybara/node/finders.rb
@@ -116,17 +116,38 @@ def find_by_id(id, options={})
# page.all('a', :text => 'Home')
# page.all('#menu li', :visible => true)
#
+ # By default if no elements are found, an empty array is returned;
+ # however, expectations can be set on the number of elements to be
+ # found using:
+ #
+ # page.assert_selector('p#foo', :count => 4)
+ # page.assert_selector('p#foo', :maximum => 10)
+ # page.assert_selector('p#foo', :minimum => 1)
+ # page.assert_selector('p#foo', :between => 1..10)
+ #
+ # See {Capybara::Helpers#matches_count?} for additional information about
+ # count matching.
+ #
# @overload all([kind], locator, options)
# @param [:css, :xpath] kind The type of selector
# @param [String] locator The selector
# @option options [String, Regexp] text Only find elements which contain this text or match this regexp
# @option options [Boolean] visible Only find elements that are visible on the page. Setting this to false
# finds invisible _and_ visible elements.
+ # @option options [Integer] count Exact number of matches that are expected to be found
+ # @option options [Integer] maximum Maximum number of matches that are expected to be found
+ # @option options [Integer] minimum Minimum number of matches that are expected to be found
+ # @option options [Range] between Number of matches found must be within the given range
# @option options [Boolean] exact Control whether `is` expressions in the given XPath match exactly or partially
# @return [Capybara::Result] A collection of found elements
#
def all(*args)
- resolve_query(Capybara::Query.new(*args))
+ query = Capybara::Query.new(*args)
+ synchronize(query.wait) do
+ result = resolve_query(query)
+ raise(Capybara::ExpectationNotMet, result.failure_message) unless result.matches_count?
+ result
+ end
end
##
View
29 lib/capybara/node/matchers.rb
@@ -68,7 +68,11 @@ def has_no_selector?(*args)
#
# page.assert_selector('p#foo', :count => 4)
#
- # This will check if the expression occurs exactly 4 times.
+ # This will check if the expression occurs exactly 4 times. See
+ # {Capybara::Node::Finders#all} for other available result size options.
+ #
+ # If a :count of 0 is specified, it will behave like {#assert_no_selector};
+ # however, use of that method is preferred over this one.
#
# It also accepts all options that {Capybara::Node::Finders#all} accepts,
# such as :text and :visible.
@@ -88,7 +92,7 @@ def assert_selector(*args)
query = Capybara::Query.new(*args)
synchronize(query.wait) do
result = all(*args)
- result.matches_count? or raise Capybara::ExpectationNotMet, result.failure_message
+ raise Capybara::ExpectationNotMet, result.failure_message if result.size == 0 && !Capybara::Helpers.expects_none?(query.options)
end
return true
end
@@ -98,14 +102,29 @@ def assert_selector(*args)
# Asserts that a given selector is not on the page or current node.
# Usage is identical to Capybara::Node::Matchers#assert_selector
#
+ # Query options such as :count, :minimum, :maximum, and :between are
+ # considered to be an integral part of the selector. This will return
+ # true, for example, if a page contains 4 anchors but the query expects 5:
+ #
+ # page.assert_no_selector('a', :minimum => 1) # Found, raises Capybara::ExpectationNotMet
+ # page.assert_no_selector('a', :count => 4) # Found, raises Capybara::ExpectationNotMet
+ # page.assert_no_selector('a', :count => 5) # Not Found, returns true
+ #
# @param (see Capybara::Node::Finders#assert_selector)
# @raise [Capybara::ExpectationNotMet] If the selector exists
#
def assert_no_selector(*args)
query = Capybara::Query.new(*args)
synchronize(query.wait) do
- result = all(*args)
- result.matches_count? and raise Capybara::ExpectationNotMet, result.negative_failure_message
+ begin
+ result = all(*args)
+ rescue Capybara::ExpectationNotMet => e
+ return true
+ else
+ if result.size > 0 || (result.size == 0 && Capybara::Helpers.expects_none?(query.options))
+ raise(Capybara::ExpectationNotMet, result.negative_failure_message)
+ end
+ end
end
return true
end
@@ -471,7 +490,7 @@ def text_found?(*args)
content, options = args
count = Capybara::Helpers.normalize_whitespace(text(type)).scan(Capybara::Helpers.to_regexp(content)).count
- Capybara::Helpers.matches_count?(count, options || {})
+ Capybara::Helpers.matches_count?(count, {:minimum=>1}.merge(options || {}))
end
end
end
View
71 lib/capybara/spec/session/all_spec.rb
@@ -67,6 +67,77 @@
end
end
+ context 'with element count filters' do
+ context ':count' do
+ it 'should succeed when the number of elements founds matches the expectation' do
+ expect { @session.all(:css, 'h1, p', :count => 4) }.to_not raise_error
+ end
+ it 'should raise ExpectationNotMet when the number of elements founds does not match the expectation' do
+ expect { @session.all(:css, 'h1, p', :count => 5) }.to raise_error(Capybara::ExpectationNotMet)
+ end
+ end
+ context ':minimum' do
+ it 'should succeed when the number of elements founds matches the expectation' do
+ expect { @session.all(:css, 'h1, p', :minimum => 0) }.to_not raise_error
+ end
+ it 'should raise ExpectationNotMet when the number of elements founds does not match the expectation' do
+ expect { @session.all(:css, 'h1, p', :minimum => 5) }.to raise_error(Capybara::ExpectationNotMet)
+ end
+ end
+ context ':maximum' do
+ it 'should succeed when the number of elements founds matches the expectation' do
+ expect { @session.all(:css, 'h1, p', :maximum => 4) }.to_not raise_error
+ end
+ it 'should raise ExpectationNotMet when the number of elements founds does not match the expectation' do
+ expect { @session.all(:css, 'h1, p', :maximum => 0) }.to raise_error(Capybara::ExpectationNotMet)
+ end
+ end
+ context ':between' do
+ it 'should succeed when the number of elements founds matches the expectation' do
+ expect { @session.all(:css, 'h1, p', :between => 2..7) }.to_not raise_error
+ end
+ it 'should raise ExpectationNotMet when the number of elements founds does not match the expectation' do
+ expect { @session.all(:css, 'h1, p', :between => 0..3) }.to raise_error(Capybara::ExpectationNotMet)
+ end
+ end
+
+ context 'with multiple count filters' do
+ it 'ignores other filters when :count is specified' do
+ o = {:count => 4,
+ :minimum => 5,
+ :maximum => 0,
+ :between => 0..3}
+ expect { @session.all(:css, 'h1, p', o) }.to_not raise_error
+ end
+ context 'with no :count expectation' do
+ it 'fails if :minimum is not met' do
+ o = {:minimum => 5,
+ :maximum => 4,
+ :between => 2..7}
+ expect { @session.all(:css, 'h1, p', o) }.to raise_error(Capybara::ExpectationNotMet)
+ end
+ it 'fails if :maximum is not met' do
+ o = {:minimum => 0,
+ :maximum => 0,
+ :between => 2..7}
+ expect { @session.all(:css, 'h1, p', o) }.to raise_error(Capybara::ExpectationNotMet)
+ end
+ it 'fails if :between is not met' do
+ o = {:minimum => 0,
+ :maximum => 4,
+ :between => 0..3}
+ expect { @session.all(:css, 'h1, p', o) }.to raise_error(Capybara::ExpectationNotMet)
+ end
+ it 'succeeds if all combineable expectations are met' do
+ o = {:minimum => 0,
+ :maximum => 4,
+ :between => 2..7}
+ expect { @session.all(:css, 'h1, p', o) }.to_not raise_error
+ end
+ end
+ end
+ end
+
context "within a scope" do
before do
@session.visit('/with_scope')

No commit comments for this range

Something went wrong with that request. Please try again.