mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
743 lines
30 KiB
Ruby
743 lines
30 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Capybara
|
|
module Node
|
|
module Matchers
|
|
##
|
|
#
|
|
# Checks if a given selector is on the page or a descendant of the current node.
|
|
#
|
|
# page.has_selector?('p#foo')
|
|
# page.has_selector?(:xpath, './/p[@id="foo"]')
|
|
# page.has_selector?(:foo)
|
|
#
|
|
# By default it will check if the expression occurs at least once,
|
|
# but a different number can be specified.
|
|
#
|
|
# page.has_selector?('p.foo', count: 4)
|
|
#
|
|
# 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.
|
|
#
|
|
# page.has_selector?('li', text: 'Horse', visible: true)
|
|
#
|
|
# has_selector? can also accept XPath expressions generated by the
|
|
# XPath gem:
|
|
#
|
|
# page.has_selector?(:xpath, XPath.descendant(:p))
|
|
#
|
|
# @param (see Capybara::Node::Finders#all)
|
|
# @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
|
|
#
|
|
def has_selector?(*args, **options, &optional_filter_block)
|
|
make_predicate(options) { assert_selector(*args, options, &optional_filter_block) }
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if a given selector is not on the page or a descendant of the current node.
|
|
# Usage is identical to Capybara::Node::Matchers#has_selector?
|
|
#
|
|
# @param (see Capybara::Node::Finders#has_selector?)
|
|
# @return [Boolean]
|
|
#
|
|
def has_no_selector?(*args, **options, &optional_filter_block)
|
|
make_predicate(options) { assert_no_selector(*args, options, &optional_filter_block) }
|
|
end
|
|
|
|
##
|
|
#
|
|
# 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)
|
|
make_predicate(options) { assert_style(styles, options) }
|
|
end
|
|
|
|
##
|
|
#
|
|
# Asserts that a given selector is on the page or a descendant of the current node.
|
|
#
|
|
# 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.
|
|
#
|
|
# page.assert_selector('p#foo', count: 4)
|
|
#
|
|
# 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.
|
|
#
|
|
# page.assert_selector('li', text: 'Horse', visible: true)
|
|
#
|
|
# `assert_selector` can also accept XPath expressions generated by the
|
|
# 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
|
|
#
|
|
def assert_selector(*args, &optional_filter_block)
|
|
_verify_selector_result(args, optional_filter_block) do |result, query|
|
|
unless result.matches_count? && (result.any? || query.expects_none?)
|
|
raise Capybara::ExpectationNotMet, result.failure_message
|
|
end
|
|
end
|
|
end
|
|
|
|
##
|
|
#
|
|
# 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
|
|
|
|
# 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.
|
|
#
|
|
# @overload assert_all_of_selectors([kind = Capybara.default_selector], *locators, **options)
|
|
#
|
|
def assert_all_of_selectors(*args, wait: nil, **options, &optional_filter_block)
|
|
wait = session_options.default_max_wait_time if wait.nil?
|
|
selector = extract_selector(args)
|
|
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.
|
|
#
|
|
# @overload assert_none_of_selectors([kind = Capybara.default_selector], *locators, **options)
|
|
#
|
|
def assert_none_of_selectors(*args, wait: nil, **options, &optional_filter_block)
|
|
wait = session_options.default_max_wait_time if wait.nil?
|
|
selector = extract_selector(args)
|
|
synchronize(wait) do
|
|
args.each do |locator|
|
|
assert_no_selector(selector, locator, options, &optional_filter_block)
|
|
end
|
|
end
|
|
end
|
|
|
|
##
|
|
#
|
|
# Asserts that a given selector is not on the page or a descendant of the 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, &optional_filter_block)
|
|
_verify_selector_result(args, optional_filter_block) do |result, query|
|
|
if result.matches_count? && (!result.empty? || query.expects_none?)
|
|
raise Capybara::ExpectationNotMet, result.negative_failure_message
|
|
end
|
|
end
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if a given XPath expression is on the page or a descendant of the current node.
|
|
#
|
|
# 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.
|
|
#
|
|
# page.has_xpath?('.//p[@id="foo"]', count: 4)
|
|
#
|
|
# 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.
|
|
#
|
|
# page.has_xpath?('.//li', text: 'Horse', visible: true)
|
|
#
|
|
# 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
|
|
#
|
|
def has_xpath?(path, **options, &optional_filter_block)
|
|
has_selector?(:xpath, path, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if a given XPath expression is not on the page or a descendant of the current node.
|
|
# Usage is identical to Capybara::Node::Matchers#has_xpath?
|
|
#
|
|
# @param (see Capybara::Node::Finders#has_xpath?)
|
|
# @return [Boolean]
|
|
#
|
|
def has_no_xpath?(path, **options, &optional_filter_block)
|
|
has_no_selector?(:xpath, path, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if a given CSS selector is on the page or a descendant of the current node.
|
|
#
|
|
# page.has_css?('p#foo')
|
|
#
|
|
# By default it will check if the selector occurs at least once,
|
|
# but a different number can be specified.
|
|
#
|
|
# page.has_css?('p#foo', count: 4)
|
|
#
|
|
# 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.
|
|
#
|
|
# page.has_css?('li', text: 'Horse', visible: true)
|
|
#
|
|
# @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
|
|
#
|
|
def has_css?(path, **options, &optional_filter_block)
|
|
has_selector?(:css, path, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if a given CSS selector is not on the page or a descendant of the current node.
|
|
# Usage is identical to Capybara::Node::Matchers#has_css?
|
|
#
|
|
# @param (see Capybara::Node::Finders#has_css?)
|
|
# @return [Boolean]
|
|
#
|
|
def has_no_css?(path, **options, &optional_filter_block)
|
|
has_no_selector?(:css, path, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the page or current node has a link with the given
|
|
# text or id.
|
|
#
|
|
# @param [String] locator The text or id of a link to check for
|
|
# @param options
|
|
# @option options [String, Regexp] :href The value the href attribute must be
|
|
# @return [Boolean] Whether it exists
|
|
#
|
|
def has_link?(locator = nil, **options, &optional_filter_block)
|
|
has_selector?(:link, locator, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the page or current node has no link with the given
|
|
# text or id.
|
|
#
|
|
# @param (see Capybara::Node::Finders#has_link?)
|
|
# @return [Boolean] Whether it doesn't exist
|
|
#
|
|
def has_no_link?(locator = nil, **options, &optional_filter_block)
|
|
has_no_selector?(:link, locator, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# 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
|
|
#
|
|
def has_button?(locator = nil, **options, &optional_filter_block)
|
|
has_selector?(:button, locator, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# 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
|
|
#
|
|
def has_no_button?(locator = nil, **options, &optional_filter_block)
|
|
has_no_selector?(:button, locator, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# 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:
|
|
#
|
|
# page.has_field?('Name', with: 'Jonas')
|
|
#
|
|
# It is also possible to filter by the field type attribute:
|
|
#
|
|
# page.has_field?('Email', type: 'email')
|
|
#
|
|
# Note: 'textarea' and 'select' are valid type values, matching the associated tag names.
|
|
#
|
|
# @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
|
|
#
|
|
def has_field?(locator = nil, **options, &optional_filter_block)
|
|
has_selector?(:field, locator, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the page or current node has no form field with the given
|
|
# label, name or id. See {Capybara::Node::Matchers#has_field?}.
|
|
#
|
|
# @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
|
|
#
|
|
def has_no_field?(locator = nil, **options, &optional_filter_block)
|
|
has_no_selector?(:field, locator, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the page or current node has a radio button or
|
|
# checkbox with the given label, value, id, or Capybara.test_id attribute that is currently
|
|
# checked.
|
|
#
|
|
# @param [String] locator The label, name or id of a checked field
|
|
# @return [Boolean] Whether it exists
|
|
#
|
|
def has_checked_field?(locator = nil, **options, &optional_filter_block)
|
|
has_selector?(:field, locator, options.merge(checked: true), &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the page or current node has no radio button or
|
|
# checkbox with the given label, value or id, or Capybara.test_id attribute that is currently
|
|
# checked.
|
|
#
|
|
# @param [String] locator The label, name or id of a checked field
|
|
# @return [Boolean] Whether it doesn't exist
|
|
#
|
|
def has_no_checked_field?(locator = nil, **options, &optional_filter_block)
|
|
has_no_selector?(:field, locator, options.merge(checked: true), &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the page or current node has a radio button or
|
|
# checkbox with the given label, value or id, or Capybara.test_id attribute that is currently
|
|
# unchecked.
|
|
#
|
|
# @param [String] locator The label, name or id of an unchecked field
|
|
# @return [Boolean] Whether it exists
|
|
#
|
|
def has_unchecked_field?(locator = nil, **options, &optional_filter_block)
|
|
has_selector?(:field, locator, options.merge(unchecked: true), &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the page or current node has no radio button or
|
|
# checkbox with the given label, value or id, or Capybara.test_id attribute that is currently
|
|
# unchecked.
|
|
#
|
|
# @param [String] locator The label, name or id of an unchecked field
|
|
# @return [Boolean] Whether it doesn't exist
|
|
#
|
|
def has_no_unchecked_field?(locator = nil, **options, &optional_filter_block)
|
|
has_no_selector?(:field, locator, options.merge(unchecked: true), &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# 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:
|
|
#
|
|
# page.has_select?('Language', selected: 'German')
|
|
#
|
|
# For multiple select boxes, several options may be specified:
|
|
#
|
|
# page.has_select?('Language', selected: ['English', 'German'])
|
|
#
|
|
# It's also possible to check if the exact set of options exists for
|
|
# this select box:
|
|
#
|
|
# page.has_select?('Language', options: ['English', 'German', 'Spanish'])
|
|
#
|
|
# You can also check for a partial set of options:
|
|
#
|
|
# page.has_select?('Language', with_options: ['English', 'German'])
|
|
#
|
|
# @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
|
|
#
|
|
def has_select?(locator = nil, **options, &optional_filter_block)
|
|
has_selector?(:select, locator, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# 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
|
|
#
|
|
def has_no_select?(locator = nil, **options, &optional_filter_block)
|
|
has_no_selector?(:select, locator, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the page or current node has a table with the given id
|
|
# or caption:
|
|
#
|
|
# page.has_table?('People')
|
|
#
|
|
# @param [String] locator The id or caption of a table
|
|
# @return [Boolean] Whether it exist
|
|
#
|
|
def has_table?(locator = nil, **options, &optional_filter_block)
|
|
has_selector?(:table, locator, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the page or current node has no table with the given id
|
|
# or caption. See {Capybara::Node::Matchers#has_table?}.
|
|
#
|
|
# @param (see Capybara::Node::Matchers#has_table?)
|
|
# @return [Boolean] Whether it doesn't exist
|
|
#
|
|
def has_no_table?(locator = nil, **options, &optional_filter_block)
|
|
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.
|
|
#
|
|
# node.assert_matches_selector('li', text: 'Horse', visible: true)
|
|
#
|
|
# @param (see Capybara::Node::Finders#all)
|
|
# @raise [Capybara::ExpectationNotMet] If the selector does not match
|
|
#
|
|
def assert_matches_selector(*args, &optional_filter_block)
|
|
_verify_match_result(args, optional_filter_block) do |result|
|
|
raise Capybara::ExpectationNotMet, 'Item does not match the provided selector' unless result.include? self
|
|
end
|
|
end
|
|
|
|
def assert_not_matches_selector(*args, &optional_filter_block)
|
|
_verify_match_result(args, optional_filter_block) do |result|
|
|
raise Capybara::ExpectationNotMet, 'Item matched the provided selector' if result.include? self
|
|
end
|
|
end
|
|
|
|
# Deprecated
|
|
# TODO: remove
|
|
def refute_selector(*args, &optional_filter_block)
|
|
warn '`refute_selector` was never meant to be in this scope unless ' \
|
|
'using minitest. Either replace with `assert_no_selector` ' \
|
|
"or require 'capybara/minitest'."
|
|
assert_no_selector(*args, &optional_filter_block)
|
|
end
|
|
|
|
# Deprecated
|
|
# TODO: remove
|
|
def refute_matches_selector(*args, &optional_filter_block)
|
|
warn '`refute_matches_selector` was never meant to be in this scope unless ' \
|
|
'using minitest. Either replace with `assert_not_matches_selector` ' \
|
|
"or require 'capybara/minitest'."
|
|
assert_not_matches_selector(*args, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the current node matches given selector
|
|
#
|
|
# @param (see Capybara::Node::Finders#has_selector?)
|
|
# @return [Boolean]
|
|
#
|
|
def matches_selector?(*args, **options, &optional_filter_block)
|
|
make_predicate(options) { assert_matches_selector(*args, options, &optional_filter_block) }
|
|
end
|
|
|
|
##
|
|
#
|
|
# 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]
|
|
#
|
|
def matches_xpath?(xpath, **options, &optional_filter_block)
|
|
matches_selector?(:xpath, xpath, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
#
|
|
# Checks if the current node matches given CSS selector
|
|
#
|
|
# @param [String] css The CSS selector to match against the current code
|
|
# @return [Boolean]
|
|
#
|
|
def matches_css?(css, **options, &optional_filter_block)
|
|
matches_selector?(:css, css, options, &optional_filter_block)
|
|
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]
|
|
#
|
|
def not_matches_selector?(*args, **options, &optional_filter_block)
|
|
make_predicate(options) { assert_not_matches_selector(*args, options, &optional_filter_block) }
|
|
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]
|
|
#
|
|
def not_matches_xpath?(xpath, **options, &optional_filter_block)
|
|
not_matches_selector?(:xpath, xpath, options, &optional_filter_block)
|
|
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]
|
|
#
|
|
def not_matches_css?(css, **options, &optional_filter_block)
|
|
not_matches_selector?(:css, css, options, &optional_filter_block)
|
|
end
|
|
|
|
##
|
|
# Asserts that the page or current node has the given text content,
|
|
# ignoring any HTML tags.
|
|
#
|
|
# @!macro text_query_params
|
|
# @overload $0(type, text, **options)
|
|
# @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`.
|
|
# @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
|
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
|
|
# @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
|
|
# @option options [Boolean] :normalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
|
|
# @overload $0(text, **options)
|
|
# @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
|
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
|
|
# @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
|
|
# @option options [Boolean] :normalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
|
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
|
# @return [true]
|
|
#
|
|
def assert_text(*args)
|
|
_verify_text(args) do |count, query|
|
|
unless query.matches_count?(count) && (count.positive? || query.expects_none?)
|
|
raise Capybara::ExpectationNotMet, query.failure_message
|
|
end
|
|
end
|
|
end
|
|
|
|
##
|
|
# 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)
|
|
_verify_text(args) do |count, query|
|
|
if query.matches_count?(count) && (count.positive? || query.expects_none?)
|
|
raise Capybara::ExpectationNotMet, query.negative_failure_message
|
|
end
|
|
end
|
|
end
|
|
|
|
##
|
|
# 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
|
|
#
|
|
def has_text?(*args, **options)
|
|
make_predicate(options) { assert_text(*args, options) }
|
|
end
|
|
alias_method :has_content?, :has_text?
|
|
|
|
##
|
|
# 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
|
|
#
|
|
def has_no_text?(*args, **options)
|
|
make_predicate(options) { assert_no_text(*args, options) }
|
|
end
|
|
alias_method :has_no_content?, :has_no_text?
|
|
|
|
def ==(other)
|
|
eql?(other) || (other.respond_to?(:base) && base == other.base)
|
|
end
|
|
|
|
private
|
|
|
|
def extract_selector(args)
|
|
args.first.is_a?(Symbol) ? args.shift : session_options.default_selector
|
|
end
|
|
|
|
def _verify_selector_result(query_args, optional_filter_block)
|
|
query_args = _set_query_session_options(*query_args)
|
|
query = Capybara::Queries::SelectorQuery.new(*query_args, &optional_filter_block)
|
|
synchronize(query.wait) do
|
|
yield query.resolve_for(self), query
|
|
end
|
|
true
|
|
end
|
|
|
|
def _verify_match_result(query_args, optional_filter_block)
|
|
query_args = _set_query_session_options(*query_args)
|
|
query = Capybara::Queries::MatchQuery.new(*query_args, &optional_filter_block)
|
|
synchronize(query.wait) do
|
|
yield query.resolve_for(first(:xpath, './parent::*', minimum: 0) || session&.document || query_scope)
|
|
end
|
|
true
|
|
end
|
|
|
|
def _verify_text(query_args)
|
|
query_args = _set_query_session_options(*query_args)
|
|
query = Capybara::Queries::TextQuery.new(*query_args)
|
|
synchronize(query.wait) do
|
|
yield query.resolve_for(self), query
|
|
end
|
|
true
|
|
end
|
|
|
|
def _set_query_session_options(*query_args, **query_options)
|
|
query_options[:session_options] = session_options
|
|
query_args.push(query_options)
|
|
end
|
|
|
|
def make_predicate(options)
|
|
options[:wait] = 0 unless options.key?(:wait) || session_options.predicates_wait
|
|
yield
|
|
rescue Capybara::ExpectationNotMet
|
|
false
|
|
end
|
|
end
|
|
end
|
|
end
|