2016-03-07 19:52:19 -05:00
# frozen_string_literal: true
2018-01-08 15:23:54 -05:00
2010-07-09 20:20:32 -04:00
module Capybara
2010-11-21 08:37:36 -05:00
module Node
2010-07-09 20:20:32 -04:00
module Matchers
2010-08-24 06:37:35 -04:00
##
#
2016-09-16 13:50:49 -04:00
# Checks if a given selector is on the page or a descendant of the current node.
2010-08-24 06:37:35 -04:00
#
2010-10-12 07:26:24 -04:00
# page.has_selector?('p#foo')
# page.has_selector?(:xpath, './/p[@id="foo"]')
# page.has_selector?(:foo)
2010-08-24 06:37:35 -04:00
#
# By default it will check if the expression occurs at least once,
# but a different number can be specified.
#
2016-10-04 14:10:29 -04:00
# page.has_selector?('p.foo', count: 4)
2010-08-24 06:37:35 -04:00
#
# This will check if the expression occurs exactly 4 times.
#
# It also accepts all options that {Capybara::Node::Finders#all} accepts,
# such as :text and :visible.
#
2016-10-04 14:10:29 -04:00
# page.has_selector?('li', text: 'Horse', visible: true)
2010-08-24 06:37:35 -04:00
#
2010-10-12 07:26:24 -04:00
# has_selector? can also accept XPath expressions generated by the
2010-08-24 06:37:35 -04:00
# XPath gem:
#
2012-07-13 14:33:14 -04:00
# page.has_selector?(:xpath, XPath.descendant(:p))
2010-08-24 06:37:35 -04:00
#
2010-10-12 07:26:24 -04:00
# @param (see Capybara::Node::Finders#all)
2013-03-28 22:15:07 -04:00
# @param args
# @option args [Integer] :count (nil) Number of times the text should occur
# @option args [Integer] :minimum (nil) Minimum number of times the text should occur
# @option args [Integer] :maximum (nil) Maximum number of times the text should occur
# @option args [Range] :between (nil) Range of times that should contain number of times text occurs
# @return [Boolean] If the expression exists
2010-08-24 06:37:35 -04:00
#
2018-07-23 17:57:22 -04:00
def has_selector? ( * args , ** options , & optional_filter_block )
make_predicate ( options ) { assert_selector ( * args , options , & optional_filter_block ) }
2010-07-09 20:20:32 -04:00
end
2012-07-13 14:34:56 -04:00
##
#
2016-09-16 14:17:13 -04:00
# Checks if a given selector is not on the page or a descendant of the current node.
2012-07-13 14:34:56 -04:00
# Usage is identical to Capybara::Node::Matchers#has_selector?
#
# @param (see Capybara::Node::Finders#has_selector?)
# @return [Boolean]
#
2018-07-23 17:57:22 -04:00
def has_no_selector? ( * args , ** options , & optional_filter_block )
make_predicate ( options ) { assert_no_selector ( * args , options , & optional_filter_block ) }
2012-07-13 14:34:56 -04:00
end
2018-06-20 14:43:21 -04:00
##
#
# Checks if a an element has the specified CSS styles
#
# element.has_style?( 'color' => 'rgb(0,0,255)', 'font-size' => /px/ )
#
# @param styles [Hash]
# @return [Boolean] If the styles match
#
def has_style? ( styles , ** options )
2018-07-23 17:57:22 -04:00
make_predicate ( options ) { assert_style ( styles , options ) }
2018-06-20 14:43:21 -04:00
end
2012-07-13 14:33:14 -04:00
##
#
2016-09-16 13:50:49 -04:00
# Asserts that a given selector is on the page or a descendant of the current node.
2012-07-13 14:33:14 -04:00
#
# page.assert_selector('p#foo')
# page.assert_selector(:xpath, './/p[@id="foo"]')
# page.assert_selector(:foo)
#
# By default it will check if the expression occurs at least once,
# but a different number can be specified.
#
2016-10-04 14:10:29 -04:00
# page.assert_selector('p#foo', count: 4)
2012-07-13 14:33:14 -04:00
#
2014-01-17 14:00:45 -05:00
# 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.
2012-07-13 14:33:14 -04:00
#
# It also accepts all options that {Capybara::Node::Finders#all} accepts,
# such as :text and :visible.
#
2016-10-04 14:10:29 -04:00
# page.assert_selector('li', text: 'Horse', visible: true)
2012-07-13 14:33:14 -04:00
#
2013-03-04 16:35:11 -05:00
# `assert_selector` can also accept XPath expressions generated by the
2012-07-13 14:33:14 -04:00
# XPath gem:
#
# page.assert_selector(:xpath, XPath.descendant(:p))
#
# @param (see Capybara::Node::Finders#all)
# @option options [Integer] :count (nil) Number of times the expression should occur
# @raise [Capybara::ExpectationNotMet] If the selector does not exist
#
2016-09-23 18:03:36 -04:00
def assert_selector ( * args , & optional_filter_block )
2016-11-21 19:28:45 -05:00
_verify_selector_result ( args , optional_filter_block ) do | result , query |
2018-05-16 15:47:08 -04:00
unless result . matches_count? && ( result . any? || query . expects_none? )
2014-02-16 12:13:58 -05:00
raise Capybara :: ExpectationNotMet , result . failure_message
end
2012-06-08 10:47:01 -04:00
end
end
2018-06-20 14:43:21 -04:00
##
#
# Asserts that an element has the specified CSS styles
#
# element.assert_style( 'color' => 'rgb(0,0,255)', 'font-size' => /px/ )
#
# @param styles [Hash]
# @raise [Capybara::ExpectationNotMet] If the element doesn't have the specified styles
#
def assert_style ( styles , ** options )
query_args = _set_query_session_options ( styles , options )
query = Capybara :: Queries :: StyleQuery . new ( * query_args )
synchronize ( query . wait ) do
raise Capybara :: ExpectationNotMet , query . failure_message unless query . resolves_for? ( self )
end
true
end
2017-01-02 15:07:02 -05:00
# Asserts that all of the provided selectors are present on the given page
# or descendants of the current node. If options are provided, the assertion
# will check that each locator is present with those options as well (other than :wait).
#
# page.assert_all_of_selectors(:custom, 'Tom', 'Joe', visible: all)
# page.assert_all_of_selectors(:css, '#my_div', 'a.not_clicked')
#
# It accepts all options that {Capybara::Node::Finders#all} accepts,
# such as :text and :visible.
#
# The :wait option applies to all of the selectors as a group, so all of the locators must be present
# within :wait (Defaults to Capybara.default_max_wait_time) seconds.
#
2018-05-17 17:45:53 -04:00
# @overload assert_all_of_selectors([kind = Capybara.default_selector], *locators, **options)
2017-01-02 15:07:02 -05:00
#
2018-03-14 16:16:49 -04:00
def assert_all_of_selectors ( * args , wait : nil , ** options , & optional_filter_block )
wait = session_options . default_max_wait_time if wait . nil?
2018-05-16 15:47:08 -04:00
selector = extract_selector ( args )
2017-01-02 15:07:02 -05:00
synchronize ( wait ) do
args . each do | locator |
assert_selector ( selector , locator , options , & optional_filter_block )
end
end
end
# Asserts that none of the provided selectors are present on the given page
# or descendants of the current node. If options are provided, the assertion
# will check that each locator is present with those options as well (other than :wait).
#
# page.assert_none_of_selectors(:custom, 'Tom', 'Joe', visible: all)
# page.assert_none_of_selectors(:css, '#my_div', 'a.not_clicked')
#
# It accepts all options that {Capybara::Node::Finders#all} accepts,
# such as :text and :visible.
#
# The :wait option applies to all of the selectors as a group, so none of the locators must be present
# within :wait (Defaults to Capybara.default_max_wait_time) seconds.
#
2018-05-17 17:45:53 -04:00
# @overload assert_none_of_selectors([kind = Capybara.default_selector], *locators, **options)
2017-01-02 15:07:02 -05:00
#
2018-03-14 16:16:49 -04:00
def assert_none_of_selectors ( * args , wait : nil , ** options , & optional_filter_block )
wait = session_options . default_max_wait_time if wait . nil?
2018-05-16 15:47:08 -04:00
selector = extract_selector ( args )
2017-01-02 15:07:02 -05:00
synchronize ( wait ) do
args . each do | locator |
assert_no_selector ( selector , locator , options , & optional_filter_block )
end
end
end
2012-07-13 14:33:14 -04:00
##
#
2016-09-16 13:50:49 -04:00
# Asserts that a given selector is not on the page or a descendant of the current node.
2012-07-13 14:33:14 -04:00
# Usage is identical to Capybara::Node::Matchers#assert_selector
#
2014-01-17 14:00:45 -05:00
# 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:
#
2016-10-04 14:10:29 -04:00
# 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
2014-01-17 14:00:45 -05:00
#
2012-07-13 14:33:14 -04:00
# @param (see Capybara::Node::Finders#assert_selector)
# @raise [Capybara::ExpectationNotMet] If the selector exists
#
2016-09-23 18:03:36 -04:00
def assert_no_selector ( * args , & optional_filter_block )
2016-11-21 19:28:45 -05:00
_verify_selector_result ( args , optional_filter_block ) do | result , query |
2018-01-08 15:23:54 -05:00
if result . matches_count? && ( ! result . empty? || query . expects_none? )
2014-02-16 12:13:58 -05:00
raise Capybara :: ExpectationNotMet , result . negative_failure_message
2014-01-17 14:00:45 -05:00
end
2012-06-08 10:47:01 -04:00
end
end
2014-01-29 06:45:18 -05:00
2010-10-12 07:26:24 -04:00
##
#
2016-09-16 13:50:49 -04:00
# Checks if a given XPath expression is on the page or a descendant of the current node.
2010-10-12 07:26:24 -04:00
#
# page.has_xpath?('.//p[@id="foo"]')
#
# By default it will check if the expression occurs at least once,
# but a different number can be specified.
#
2016-10-04 14:10:29 -04:00
# page.has_xpath?('.//p[@id="foo"]', count: 4)
2010-10-12 07:26:24 -04:00
#
# This will check if the expression occurs exactly 4 times.
#
# It also accepts all options that {Capybara::Node::Finders#all} accepts,
# such as :text and :visible.
#
2016-10-04 14:10:29 -04:00
# page.has_xpath?('.//li', text: 'Horse', visible: true)
2010-10-12 07:26:24 -04:00
#
# has_xpath? can also accept XPath expressions generate by the
# XPath gem:
#
# xpath = XPath.generate { |x| x.descendant(:p) }
# page.has_xpath?(xpath)
#
# @param [String] path An XPath expression
# @param options (see Capybara::Node::Finders#all)
# @option options [Integer] :count (nil) Number of times the expression should occur
# @return [Boolean] If the expression exists
#
2016-08-17 19:14:39 -04:00
def has_xpath? ( path , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_selector? ( :xpath , path , options , & optional_filter_block )
2010-10-12 07:26:24 -04:00
end
##
#
2016-09-16 13:50:49 -04:00
# Checks if a given XPath expression is not on the page or a descendant of the current node.
2010-10-12 07:26:24 -04:00
# Usage is identical to Capybara::Node::Matchers#has_xpath?
#
# @param (see Capybara::Node::Finders#has_xpath?)
# @return [Boolean]
#
2016-08-17 19:14:39 -04:00
def has_no_xpath? ( path , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_no_selector? ( :xpath , path , options , & optional_filter_block )
2010-10-12 07:26:24 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
2016-09-16 13:50:49 -04:00
# Checks if a given CSS selector is on the page or a descendant of the current node.
2010-08-24 06:37:35 -04:00
#
# page.has_css?('p#foo')
#
# By default it will check if the selector occurs at least once,
# but a different number can be specified.
#
2016-10-04 14:10:29 -04:00
# page.has_css?('p#foo', count: 4)
2010-08-24 06:37:35 -04:00
#
# This will check if the selector occurs exactly 4 times.
#
# It also accepts all options that {Capybara::Node::Finders#all} accepts,
# such as :text and :visible.
#
2016-10-04 14:10:29 -04:00
# page.has_css?('li', text: 'Horse', visible: true)
2010-08-24 06:37:35 -04:00
#
# @param [String] path A CSS selector
# @param options (see Capybara::Node::Finders#all)
# @option options [Integer] :count (nil) Number of times the selector should occur
# @return [Boolean] If the selector exists
#
2016-08-17 19:14:39 -04:00
def has_css? ( path , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_selector? ( :css , path , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
2016-09-16 13:50:49 -04:00
# Checks if a given CSS selector is not on the page or a descendant of the current node.
2010-08-24 06:37:35 -04:00
# Usage is identical to Capybara::Node::Matchers#has_css?
#
# @param (see Capybara::Node::Finders#has_css?)
# @return [Boolean]
#
2016-08-17 19:14:39 -04:00
def has_no_css? ( path , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_no_selector? ( :css , path , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has a link with the given
# text or id.
#
2010-11-18 18:08:26 -05:00
# @param [String] locator The text or id of a link to check for
# @param options
2015-04-27 20:33:39 -04:00
# @option options [String, Regexp] :href The value the href attribute must be
2010-11-18 18:08:26 -05:00
# @return [Boolean] Whether it exists
2010-08-24 06:37:35 -04:00
#
2018-01-09 17:05:50 -05:00
def has_link? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_selector? ( :link , locator , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has no link with the given
# text or id.
#
2010-11-18 18:08:26 -05:00
# @param (see Capybara::Node::Finders#has_link?)
2010-08-24 06:37:35 -04:00
# @return [Boolean] Whether it doesn't exist
#
2018-01-09 17:05:50 -05:00
def has_no_link? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_no_selector? ( :link , locator , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has a button with the given
# text, value or id.
#
# @param [String] locator The text, value or id of a button to check for
# @return [Boolean] Whether it exists
#
2018-01-09 17:05:50 -05:00
def has_button? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_selector? ( :button , locator , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has no button with the given
# text, value or id.
#
# @param [String] locator The text, value or id of a button to check for
# @return [Boolean] Whether it doesn't exist
#
2018-01-09 17:05:50 -05:00
def has_no_button? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_no_selector? ( :button , locator , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has a form field with the given
# label, name or id.
#
# For text fields and other textual fields, such as textareas and
# HTML5 email/url/etc. fields, it's possible to specify a :with
# option to specify the text the field should contain:
#
2016-10-04 14:10:29 -04:00
# page.has_field?('Name', with: 'Jonas')
2010-08-24 06:37:35 -04:00
#
2012-02-29 21:57:05 -05:00
# It is also possible to filter by the field type attribute:
#
2016-10-04 14:10:29 -04:00
# page.has_field?('Email', type: 'email')
2012-02-29 21:57:05 -05:00
#
2013-03-07 12:59:16 -05:00
# Note: 'textarea' and 'select' are valid type values, matching the associated tag names.
#
2016-07-28 04:25:24 -04:00
# @param [String] locator The label, name or id of a field to check for
# @option options [String, Regexp] :with The text content of the field or a Regexp to match
# @option options [String] :type The type attribute of the field
# @return [Boolean] Whether it exists
2010-08-24 06:37:35 -04:00
#
2018-01-09 17:05:50 -05:00
def has_field? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_selector? ( :field , locator , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has no form field with the given
# label, name or id. See {Capybara::Node::Matchers#has_field?}.
#
2016-07-28 04:25:24 -04:00
# @param [String] locator The label, name or id of a field to check for
# @option options [String, Regexp] :with The text content of the field or a Regexp to match
# @option options [String] :type The type attribute of the field
# @return [Boolean] Whether it doesn't exist
2010-08-24 06:37:35 -04:00
#
2018-01-09 17:05:50 -05:00
def has_no_field? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_no_selector? ( :field , locator , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has a radio button or
2018-07-05 18:29:24 -04:00
# checkbox with the given label, value, id, or Capybara.test_id attribute that is currently
2010-08-24 06:37:35 -04:00
# checked.
#
# @param [String] locator The label, name or id of a checked field
# @return [Boolean] Whether it exists
#
2018-01-09 17:05:50 -05:00
def has_checked_field? ( locator = nil , ** options , & optional_filter_block )
2016-10-04 14:10:29 -04:00
has_selector? ( :field , locator , options . merge ( checked : true ) , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2011-03-25 06:35:59 -04:00
##
#
# Checks if the page or current node has no radio button or
2018-07-05 18:29:24 -04:00
# checkbox with the given label, value or id, or Capybara.test_id attribute that is currently
2011-03-25 06:35:59 -04:00
# checked.
#
# @param [String] locator The label, name or id of a checked field
2013-07-23 17:24:44 -04:00
# @return [Boolean] Whether it doesn't exist
2011-03-25 06:35:59 -04:00
#
2018-01-09 17:05:50 -05:00
def has_no_checked_field? ( locator = nil , ** options , & optional_filter_block )
2016-11-22 14:32:16 -05:00
has_no_selector? ( :field , locator , options . merge ( checked : true ) , & optional_filter_block )
2011-03-25 06:35:59 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has a radio button or
2018-07-05 18:29:24 -04:00
# checkbox with the given label, value or id, or Capybara.test_id attribute that is currently
2010-08-24 06:37:35 -04:00
# unchecked.
#
# @param [String] locator The label, name or id of an unchecked field
# @return [Boolean] Whether it exists
#
2018-01-09 17:05:50 -05:00
def has_unchecked_field? ( locator = nil , ** options , & optional_filter_block )
2016-10-04 14:10:29 -04:00
has_selector? ( :field , locator , options . merge ( unchecked : true ) , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2011-03-25 06:35:59 -04:00
##
#
# Checks if the page or current node has no radio button or
2018-07-05 18:29:24 -04:00
# checkbox with the given label, value or id, or Capybara.test_id attribute that is currently
2011-03-25 06:35:59 -04:00
# unchecked.
#
# @param [String] locator The label, name or id of an unchecked field
2013-07-23 17:24:44 -04:00
# @return [Boolean] Whether it doesn't exist
2011-03-25 06:35:59 -04:00
#
2018-01-09 17:05:50 -05:00
def has_no_unchecked_field? ( locator = nil , ** options , & optional_filter_block )
2016-10-04 14:10:29 -04:00
has_no_selector? ( :field , locator , options . merge ( unchecked : true ) , & optional_filter_block )
2011-03-25 06:35:59 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has a select field with the
# given label, name or id.
#
# It can be specified which option should currently be selected:
#
2016-10-04 14:10:29 -04:00
# page.has_select?('Language', selected: 'German')
2010-08-24 06:37:35 -04:00
#
# For multiple select boxes, several options may be specified:
#
2016-10-04 14:10:29 -04:00
# page.has_select?('Language', selected: ['English', 'German'])
2010-08-24 06:37:35 -04:00
#
2012-03-15 23:14:47 -04:00
# It's also possible to check if the exact set of options exists for
2010-08-24 06:37:35 -04:00
# this select box:
#
2016-10-04 14:10:29 -04:00
# page.has_select?('Language', options: ['English', 'German', 'Spanish'])
2012-03-22 21:24:49 -04:00
#
# You can also check for a partial set of options:
#
2016-10-04 14:10:29 -04:00
# page.has_select?('Language', with_options: ['English', 'German'])
2010-08-24 06:37:35 -04:00
#
2017-06-07 13:32:01 -04:00
# @param [String] locator The label, name or id of a select box
# @option options [Array] :options Options which should be contained in this select box
# @option options [Array] :with_options Partial set of options which should be contained in this select box
# @option options [String, Array] :selected Options which should be selected
# @option options [String, Array] :with_selected Partial set of options which should minimally be selected
# @return [Boolean] Whether it exists
2010-08-24 06:37:35 -04:00
#
2018-01-09 17:05:50 -05:00
def has_select? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_selector? ( :select , locator , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has no select field with the
# given label, name or id. See {Capybara::Node::Matchers#has_select?}.
#
# @param (see Capybara::Node::Matchers#has_select?)
# @return [Boolean] Whether it doesn't exist
#
2018-01-09 17:05:50 -05:00
def has_no_select? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_no_selector? ( :select , locator , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has a table with the given id
2012-12-23 10:11:33 -05:00
# or caption:
2010-08-24 06:37:35 -04:00
#
2012-12-23 10:11:33 -05:00
# page.has_table?('People')
2010-08-24 06:37:35 -04:00
#
# @param [String] locator The id or caption of a table
# @return [Boolean] Whether it exist
#
2018-01-09 17:05:50 -05:00
def has_table? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_selector? ( :table , locator , options , & optional_filter_block )
2010-07-09 20:20:32 -04:00
end
2010-08-24 06:37:35 -04:00
##
#
# Checks if the page or current node has no table with the given id
2010-08-27 14:52:06 -04:00
# or caption. See {Capybara::Node::Matchers#has_table?}.
2010-08-24 06:37:35 -04:00
#
# @param (see Capybara::Node::Matchers#has_table?)
# @return [Boolean] Whether it doesn't exist
#
2018-01-09 17:05:50 -05:00
def has_no_table? ( locator = nil , ** options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
has_no_selector? ( :table , locator , options , & optional_filter_block )
end
##
#
# Asserts that the current_node matches a given selector
#
# node.assert_matches_selector('p#foo')
# node.assert_matches_selector(:xpath, '//p[@id="foo"]')
# node.assert_matches_selector(:foo)
#
# It also accepts all options that {Capybara::Node::Finders#all} accepts,
# such as :text and :visible.
#
2016-10-04 14:10:29 -04:00
# node.assert_matches_selector('li', text: 'Horse', visible: true)
2016-09-23 18:03:36 -04:00
#
# @param (see Capybara::Node::Finders#all)
# @raise [Capybara::ExpectationNotMet] If the selector does not match
#
2016-10-02 18:01:34 -04:00
def assert_matches_selector ( * args , & optional_filter_block )
2016-11-21 19:28:45 -05:00
_verify_match_result ( args , optional_filter_block ) do | result |
2018-07-10 17:18:39 -04:00
raise Capybara :: ExpectationNotMet , 'Item does not match the provided selector' unless result . include? self
2016-09-23 18:03:36 -04:00
end
end
2016-10-02 18:01:34 -04:00
def assert_not_matches_selector ( * args , & optional_filter_block )
2016-11-21 19:28:45 -05:00
_verify_match_result ( args , optional_filter_block ) do | result |
2016-11-18 13:56:47 -05:00
raise Capybara :: ExpectationNotMet , 'Item matched the provided selector' if result . include? self
2016-09-23 18:03:36 -04:00
end
end
2018-07-23 14:17:07 -04:00
# Deprecated
# TODO: remove
def refute_selector ( * args , & optional_filter_block )
2018-07-24 16:27:43 -04:00
warn '`refute_selector` was never meant to be in this scope unless ' \
'using minitest. Either replace with `assert_no_selector` ' \
2018-07-23 14:17:07 -04:00
" or require 'capybara/minitest'. "
assert_no_selector ( * args , & optional_filter_block )
end
# Deprecated
# TODO: remove
2018-08-03 18:09:26 -04:00
def refute_matches_selector ( * args , & optional_filter_block )
2018-07-24 16:27:43 -04:00
warn '`refute_matches_selector` was never meant to be in this scope unless ' \
'using minitest. Either replace with `assert_not_matches_selector` ' \
2018-07-23 14:17:07 -04:00
" or require 'capybara/minitest'. "
assert_not_matches_selector ( * args , & optional_filter_block )
end
2016-09-23 18:03:36 -04:00
##
#
# Checks if the current node matches given selector
#
# @param (see Capybara::Node::Finders#has_selector?)
# @return [Boolean]
#
2018-07-23 17:57:22 -04:00
def matches_selector? ( * args , ** options , & optional_filter_block )
make_predicate ( options ) { assert_matches_selector ( * args , options , & optional_filter_block ) }
2010-12-23 13:38:44 -05:00
end
2011-10-16 19:46:19 -04:00
2016-09-23 18:03:36 -04:00
##
#
# Checks if the current node matches given XPath expression
#
# @param [String, XPath::Expression] xpath The XPath expression to match against the current code
# @return [Boolean]
#
2016-11-13 21:32:23 -05:00
def matches_xpath? ( xpath , ** options , & optional_filter_block )
2016-10-02 18:01:34 -04:00
matches_selector? ( :xpath , xpath , options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
end
##
#
# Checks if the current node matches given CSS selector
#
# @param [String] css The CSS selector to match against the current code
# @return [Boolean]
#
2016-11-13 21:32:23 -05:00
def matches_css? ( css , ** options , & optional_filter_block )
2016-10-03 20:07:06 -04:00
matches_selector? ( :css , css , options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
end
##
#
# Checks if the current node does not match given selector
# Usage is identical to Capybara::Node::Matchers#has_selector?
#
# @param (see Capybara::Node::Finders#has_selector?)
# @return [Boolean]
#
2018-07-23 17:57:22 -04:00
def not_matches_selector? ( * args , ** options , & optional_filter_block )
make_predicate ( options ) { assert_not_matches_selector ( * args , options , & optional_filter_block ) }
2016-09-23 18:03:36 -04:00
end
##
#
# Checks if the current node does not match given XPath expression
#
# @param [String, XPath::Expression] xpath The XPath expression to match against the current code
# @return [Boolean]
#
2016-11-13 21:32:23 -05:00
def not_matches_xpath? ( xpath , ** options , & optional_filter_block )
2016-10-02 18:01:34 -04:00
not_matches_selector? ( :xpath , xpath , options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
end
##
#
# Checks if the current node does not match given CSS selector
#
# @param [String] css The CSS selector to match against the current code
# @return [Boolean]
#
2016-11-13 21:32:23 -05:00
def not_matches_css? ( css , ** options , & optional_filter_block )
2016-10-02 18:01:34 -04:00
not_matches_selector? ( :css , css , options , & optional_filter_block )
2016-09-23 18:03:36 -04:00
end
2014-02-16 12:13:58 -05:00
##
# Asserts that the page or current node has the given text content,
# ignoring any HTML tags.
#
# @!macro text_query_params
2018-05-17 17:45:53 -04:00
# @overload $0(type, text, **options)
2015-11-02 11:04:20 -05:00
# @param [:all, :visible] type Whether to check for only visible or all text. If this parameter is missing or nil then we use the value of `Capybara.ignore_hidden_elements`, which defaults to `true`, corresponding to `:visible`.
2014-02-16 12:13:58 -05:00
# @param [String, Regexp] text The string/regexp to check for. If it's a string, text is expected to include it. If it's a regexp, text is expected to match it.
# @option options [Integer] :count (nil) Number of times the text is expected to occur
# @option options [Integer] :minimum (nil) Minimum number of times the text is expected to occur
# @option options [Integer] :maximum (nil) Maximum number of times the text is expected to occur
# @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
2015-04-14 16:56:30 -04:00
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
2016-12-23 15:17:45 -05:00
# @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
2018-08-01 18:53:06 -04:00
# @option options [Boolean] :normalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
2018-05-17 17:45:53 -04:00
# @overload $0(text, **options)
2014-02-16 12:13:58 -05:00
# @param [String, Regexp] text The string/regexp to check for. If it's a string, text is expected to include it. If it's a regexp, text is expected to match it.
# @option options [Integer] :count (nil) Number of times the text is expected to occur
# @option options [Integer] :minimum (nil) Minimum number of times the text is expected to occur
# @option options [Integer] :maximum (nil) Maximum number of times the text is expected to occur
# @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
2015-04-14 16:56:30 -04:00
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
2016-12-23 15:17:45 -05:00
# @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
2018-07-30 12:23:29 -04:00
# @option options [Boolean] :normalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
2014-02-16 12:13:58 -05:00
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
# @return [true]
#
def assert_text ( * args )
2016-11-21 19:28:45 -05:00
_verify_text ( args ) do | count , query |
2018-05-10 16:20:23 -04:00
unless query . matches_count? ( count ) && ( count . positive? || query . expects_none? )
2014-02-16 12:13:58 -05:00
raise Capybara :: ExpectationNotMet , query . failure_message
end
end
2012-07-12 11:12:24 -04:00
end
2014-02-16 12:13:58 -05:00
##
# Asserts that the page or current node doesn't have the given text content,
# ignoring any HTML tags.
#
# @macro text_query_params
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
# @return [true]
#
def assert_no_text ( * args )
2016-11-21 19:28:45 -05:00
_verify_text ( args ) do | count , query |
2018-05-10 16:20:23 -04:00
if query . matches_count? ( count ) && ( count . positive? || query . expects_none? )
2014-02-16 12:13:58 -05:00
raise Capybara :: ExpectationNotMet , query . negative_failure_message
end
end
end
2012-01-02 06:17:15 -05:00
2014-02-16 12:13:58 -05:00
##
# Checks if the page or current node has the given text content,
# ignoring any HTML 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)
#
# This will check if the text occurs from 2 to 4 times.
#
# @macro text_query_params
# @return [Boolean] Whether it exists
#
2018-07-23 17:57:22 -04:00
def has_text? ( * args , ** options )
make_predicate ( options ) { assert_text ( * args , options ) }
2014-02-16 12:13:58 -05:00
end
alias_method :has_content? , :has_text?
2013-03-17 10:48:04 -04:00
2014-02-16 12:13:58 -05:00
##
# Checks if the page or current node does not have the given text
# content, ignoring any HTML tags and normalizing whitespace.
#
# @macro text_query_params
# @return [Boolean] Whether it doesn't exist
#
2018-07-23 17:57:22 -04:00
def has_no_text? ( * args , ** options )
make_predicate ( options ) { assert_no_text ( * args , options ) }
2014-02-16 12:13:58 -05:00
end
alias_method :has_no_content? , :has_no_text?
def == ( other )
2018-01-09 17:05:50 -05:00
eql? ( other ) || ( other . respond_to? ( :base ) && base == other . base )
2013-03-03 18:04:23 -05:00
end
2016-09-23 18:03:36 -04:00
2016-11-18 13:56:47 -05:00
private
2018-05-16 15:47:08 -04:00
def extract_selector ( args )
args . first . is_a? ( Symbol ) ? args . shift : session_options . default_selector
end
2018-01-08 15:23:54 -05:00
def _verify_selector_result ( query_args , optional_filter_block )
2018-01-12 19:57:41 -05:00
query_args = _set_query_session_options ( * query_args )
2016-11-18 13:56:47 -05:00
query = Capybara :: Queries :: SelectorQuery . new ( * query_args , & optional_filter_block )
synchronize ( query . wait ) do
2018-05-16 15:47:08 -04:00
yield query . resolve_for ( self ) , query
2016-11-18 13:56:47 -05:00
end
2018-01-12 19:57:41 -05:00
true
2016-11-18 13:56:47 -05:00
end
2018-01-08 15:23:54 -05:00
def _verify_match_result ( query_args , optional_filter_block )
2018-01-12 19:57:41 -05:00
query_args = _set_query_session_options ( * query_args )
2016-11-18 13:56:47 -05:00
query = Capybara :: Queries :: MatchQuery . new ( * query_args , & optional_filter_block )
synchronize ( query . wait ) do
2018-07-24 16:27:43 -04:00
yield query . resolve_for ( first ( :xpath , './parent::*' , minimum : 0 ) || query_scope )
2016-11-18 13:56:47 -05:00
end
2018-01-12 19:57:41 -05:00
true
2016-11-18 13:56:47 -05:00
end
2016-11-21 19:28:45 -05:00
def _verify_text ( query_args )
2018-01-12 19:57:41 -05:00
query_args = _set_query_session_options ( * query_args )
2016-11-18 13:56:47 -05:00
query = Capybara :: Queries :: TextQuery . new ( * query_args )
synchronize ( query . wait ) do
2018-05-16 15:47:08 -04:00
yield query . resolve_for ( self ) , query
2016-11-18 13:56:47 -05:00
end
2018-01-12 19:57:41 -05:00
true
2016-11-18 13:56:47 -05:00
end
2018-01-12 19:57:41 -05:00
def _set_query_session_options ( * query_args , ** query_options )
query_options [ :session_options ] = session_options
query_args . push ( query_options )
2016-12-15 12:04:01 -05:00
end
2018-07-23 17:57:22 -04:00
def make_predicate ( options )
options [ :wait ] = 0 unless options . key? ( :wait ) || session_options . predicates_wait
yield
rescue Capybara :: ExpectationNotMet
false
end
2010-07-09 20:20:32 -04:00
end
end
end