Use diffferent queries for searching
* Add assert_text, assert_no_text, assert_title, assert_no_title * Refactor query resolving * Improve failure messages for have_text, have_title RSpec matchers (they will be the same as for added assert_* methods) * Add Simple#inspect
This commit is contained in:
parent
d4dcd3b1d1
commit
06c4955e56
|
@ -323,13 +323,18 @@ module Capybara
|
|||
require 'capybara/window'
|
||||
require 'capybara/server'
|
||||
require 'capybara/selector'
|
||||
require 'capybara/query'
|
||||
require 'capybara/result'
|
||||
require 'capybara/version'
|
||||
|
||||
require 'capybara/queries/base_query'
|
||||
require 'capybara/query'
|
||||
require 'capybara/queries/text_query'
|
||||
require 'capybara/queries/title_query'
|
||||
|
||||
require 'capybara/node/finders'
|
||||
require 'capybara/node/matchers'
|
||||
require 'capybara/node/actions'
|
||||
require 'capybara/node/document_matchers'
|
||||
require 'capybara/node/simple'
|
||||
require 'capybara/node/base'
|
||||
require 'capybara/node/element'
|
||||
|
|
|
@ -97,6 +97,16 @@ module Capybara
|
|||
end
|
||||
end
|
||||
|
||||
# @api private
|
||||
def find_css(css)
|
||||
base.find_css(css)
|
||||
end
|
||||
|
||||
# @api private
|
||||
def find_xpath(xpath)
|
||||
base.find_xpath(xpath)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def catch_error?(error, errors = nil)
|
||||
|
|
|
@ -9,6 +9,8 @@ module Capybara
|
|||
# @see Capybara::Node
|
||||
#
|
||||
class Document < Base
|
||||
include Capybara::Node::DocumentMatchers
|
||||
|
||||
def inspect
|
||||
%(#<Capybara::Document>)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
module Capybara
|
||||
module Node
|
||||
module DocumentMatchers
|
||||
##
|
||||
# Asserts that the page has the given title.
|
||||
#
|
||||
# @!macro title_query_params
|
||||
# @overload $0(string, options = {})
|
||||
# @param string [String] The string that title should include
|
||||
# @overload $0(regexp, options = {})
|
||||
# @param regexp [Regexp] The regexp that title should match to
|
||||
# @option options [Numeric] :wait (Capybara.default_wait_time) Time that Capybara will wait for title to eq/match given string/regexp argument
|
||||
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
||||
# @return [true]
|
||||
#
|
||||
def assert_title(title, options = {})
|
||||
query = Capybara::Queries::TitleQuery.new(title, options)
|
||||
synchronize(query.wait) do
|
||||
unless query.resolves_for?(self)
|
||||
raise Capybara::ExpectationNotMet, query.failure_message
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
##
|
||||
# Asserts that the page doesn't have the given title.
|
||||
#
|
||||
# @macro title_query_params
|
||||
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
||||
# @return [true]
|
||||
#
|
||||
def assert_no_title(title, options = {})
|
||||
query = Capybara::Queries::TitleQuery.new(title, options)
|
||||
synchronize(query.wait) do
|
||||
if query.resolves_for?(self)
|
||||
raise Capybara::ExpectationNotMet, query.negative_failure_message
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
##
|
||||
# Checks if the page has the given title.
|
||||
#
|
||||
# @macro title_query_params
|
||||
# @return [Boolean]
|
||||
#
|
||||
def has_title?(title, options = {})
|
||||
assert_title(title, options)
|
||||
rescue Capybara::ExpectationNotMet
|
||||
return false
|
||||
end
|
||||
|
||||
##
|
||||
# Checks if the page doesn't have the given title.
|
||||
#
|
||||
# @macro title_query_params
|
||||
# @return [Boolean]
|
||||
#
|
||||
def has_no_title?(title, options = {})
|
||||
assert_no_title(title, options)
|
||||
rescue Capybara::ExpectationNotMet
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -29,10 +29,10 @@ module Capybara
|
|||
query = Capybara::Query.new(*args)
|
||||
synchronize(query.wait) do
|
||||
if query.match == :smart or query.match == :prefer_exact
|
||||
result = resolve_query(query, true)
|
||||
result = resolve_query(query, false) if result.size == 0 and not query.exact?
|
||||
result = query.resolve_for(self, true)
|
||||
result = query.resolve_for(self, false) if result.size == 0 && !query.exact?
|
||||
else
|
||||
result = resolve_query(query)
|
||||
result = query.resolve_for(self)
|
||||
end
|
||||
if query.match == :one or query.match == :smart and result.size > 1
|
||||
raise Capybara::Ambiguous.new("Ambiguous match, found #{result.size} elements matching #{query.description}")
|
||||
|
@ -144,8 +144,8 @@ module Capybara
|
|||
def all(*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 = query.resolve_for(self)
|
||||
raise Capybara::ExpectationNotMet, result.failure_message unless result.matches_count?
|
||||
result
|
||||
end
|
||||
end
|
||||
|
@ -164,21 +164,6 @@ module Capybara
|
|||
def first(*args)
|
||||
all(*args).first
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def resolve_query(query, exact=nil)
|
||||
synchronize do
|
||||
elements = if query.selector.format==:css
|
||||
base.find_css(query.css)
|
||||
else
|
||||
base.find_xpath(query.xpath(exact))
|
||||
end.map do |node|
|
||||
Capybara::Node::Element.new(session, node, self, query)
|
||||
end
|
||||
Capybara::Result.new(elements, query)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -91,8 +91,11 @@ module Capybara
|
|||
def assert_selector(*args)
|
||||
query = Capybara::Query.new(*args)
|
||||
synchronize(query.wait) do
|
||||
result = all(*args)
|
||||
raise Capybara::ExpectationNotMet, result.failure_message if result.size == 0 && !Capybara::Helpers.expects_none?(query.options)
|
||||
result = query.resolve_for(self)
|
||||
matches_count = Capybara::Helpers.matches_count?(result.size, query.options)
|
||||
unless matches_count && ((result.size > 0) || Capybara::Helpers.expects_none?(query.options))
|
||||
raise Capybara::ExpectationNotMet, result.failure_message
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
@ -116,19 +119,14 @@ module Capybara
|
|||
def assert_no_selector(*args)
|
||||
query = Capybara::Query.new(*args)
|
||||
synchronize(query.wait) do
|
||||
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
|
||||
result = query.resolve_for(self)
|
||||
matches_count = Capybara::Helpers.matches_count?(result.size, query.options)
|
||||
if matches_count && ((result.size > 0) || Capybara::Helpers.expects_none?(query.options))
|
||||
raise Capybara::ExpectationNotMet, result.negative_failure_message
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
alias_method :refute_selector, :assert_no_selector
|
||||
|
||||
##
|
||||
|
@ -215,58 +213,6 @@ module Capybara
|
|||
has_no_selector?(:css, path, options)
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Checks if the page or current node has the given text content,
|
||||
# ignoring any HTML tags and normalizing whitespace.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# @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)
|
||||
query = Capybara::Query.new(*args)
|
||||
synchronize(query.wait) do
|
||||
raise ExpectationNotMet unless text_found?(*args)
|
||||
end
|
||||
return true
|
||||
rescue Capybara::ExpectationNotMet
|
||||
return false
|
||||
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.
|
||||
#
|
||||
# @param (see #has_text?)
|
||||
# @return [Boolean] Whether it doesn't exist
|
||||
#
|
||||
def has_no_text?(*args)
|
||||
query = Capybara::Query.new(*args)
|
||||
synchronize(query.wait) do
|
||||
raise ExpectationNotMet if text_found?(*args)
|
||||
end
|
||||
return true
|
||||
rescue Capybara::ExpectationNotMet
|
||||
return false
|
||||
end
|
||||
alias_method :has_no_content?, :has_no_text?
|
||||
|
||||
##
|
||||
#
|
||||
# Checks if the page or current node has a link with the given
|
||||
|
@ -479,18 +425,102 @@ module Capybara
|
|||
has_no_selector?(:table, locator, options)
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
self.eql?(other) or (other.respond_to?(:base) and base == other.base)
|
||||
##
|
||||
# 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
|
||||
# @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_wait_time) Time that Capybara will wait for text to eq/match given string/regexp argument
|
||||
# @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_wait_time) Time that Capybara will wait for text to eq/match given string/regexp argument
|
||||
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
||||
# @return [true]
|
||||
#
|
||||
def assert_text(*args)
|
||||
query = Capybara::Queries::TextQuery.new(*args)
|
||||
synchronize(query.wait) do
|
||||
count = query.resolve_for(self)
|
||||
matches_count = Capybara::Helpers.matches_count?(count, query.options)
|
||||
unless matches_count && ((count > 0) || Capybara::Helpers.expects_none?(query.options))
|
||||
raise Capybara::ExpectationNotMet, query.failure_message
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
private
|
||||
##
|
||||
# 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)
|
||||
query = Capybara::Queries::TextQuery.new(*args)
|
||||
synchronize(query.wait) do
|
||||
count = query.resolve_for(self)
|
||||
matches_count = Capybara::Helpers.matches_count?(count, query.options)
|
||||
if matches_count && ((count > 0) || Capybara::Helpers.expects_none?(query.options))
|
||||
raise Capybara::ExpectationNotMet, query.negative_failure_message
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
def text_found?(*args)
|
||||
type = args.shift if args.first.is_a?(Symbol) or args.first.nil?
|
||||
content, options = args
|
||||
count = Capybara::Helpers.normalize_whitespace(text(type)).scan(Capybara::Helpers.to_regexp(content)).count
|
||||
##
|
||||
# Checks if the page or current node has the given text content,
|
||||
# ignoring any HTML tags.
|
||||
#
|
||||
# Whitespaces are normalized in both node's text and passed text parameter.
|
||||
# Note that whitespace isn't normalized in passed regexp as normalizing whitespace
|
||||
# in regexp isn't easy and doesn't seem to be worth it.
|
||||
#
|
||||
# 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)
|
||||
assert_text(*args)
|
||||
rescue Capybara::ExpectationNotMet
|
||||
return false
|
||||
end
|
||||
alias_method :has_content?, :has_text?
|
||||
|
||||
Capybara::Helpers.matches_count?(count, {:minimum=>1}.merge(options || {}))
|
||||
##
|
||||
# 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)
|
||||
assert_no_text(*args)
|
||||
rescue Capybara::ExpectationNotMet
|
||||
return false
|
||||
end
|
||||
alias_method :has_no_content?, :has_no_text?
|
||||
|
||||
def ==(other)
|
||||
self.eql?(other) || (other.respond_to?(:base) && base == other.base)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,6 +14,7 @@ module Capybara
|
|||
class Simple
|
||||
include Capybara::Node::Finders
|
||||
include Capybara::Node::Matchers
|
||||
include Capybara::Node::DocumentMatchers
|
||||
|
||||
attr_reader :native
|
||||
|
||||
|
@ -148,25 +149,18 @@ module Capybara
|
|||
native.xpath("//title").first.text
|
||||
end
|
||||
|
||||
def has_title?(content)
|
||||
title.match(Capybara::Helpers.to_regexp(content))
|
||||
def inspect
|
||||
%(#<Capybara::Node::Simple tag="#{tag_name}" path="#{path}">)
|
||||
end
|
||||
|
||||
def has_no_title?(content)
|
||||
not has_title?(content)
|
||||
# @api private
|
||||
def find_css(css)
|
||||
native.css(css)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def resolve_query(query, exact=nil)
|
||||
elements = if query.selector.format == :css
|
||||
native.css(query.css)
|
||||
else
|
||||
native.xpath(query.xpath(exact))
|
||||
end.map do |node|
|
||||
self.class.new(node)
|
||||
end
|
||||
Capybara::Result.new(elements, query)
|
||||
# @api private
|
||||
def find_xpath(xpath)
|
||||
native.xpath(xpath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
module Capybara
|
||||
# @api private
|
||||
module Queries
|
||||
class BaseQuery
|
||||
COUNT_KEYS = [:count, :minimum, :maximum, :between]
|
||||
|
||||
attr_reader :options
|
||||
|
||||
def wait
|
||||
if @options.has_key?(:wait)
|
||||
@options[:wait] || 0
|
||||
else
|
||||
Capybara.default_wait_time
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_valid_keys
|
||||
invalid_keys = @options.keys - valid_keys
|
||||
unless invalid_keys.empty?
|
||||
invalid_names = invalid_keys.map(&:inspect).join(", ")
|
||||
valid_names = valid_keys.map(&:inspect).join(", ")
|
||||
raise ArgumentError, "invalid keys #{invalid_names}, should be one of #{valid_names}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,56 @@
|
|||
module Capybara
|
||||
# @api private
|
||||
module Queries
|
||||
class TextQuery < BaseQuery
|
||||
def initialize(*args)
|
||||
@type = args.shift if args.first.is_a?(Symbol) || args.first.nil?
|
||||
@expected_text, @options = args
|
||||
unless @expected_text.is_a?(Regexp)
|
||||
@expected_text = Capybara::Helpers.normalize_whitespace(@expected_text)
|
||||
end
|
||||
@search_regexp = Capybara::Helpers.to_regexp(@expected_text)
|
||||
@options ||= {}
|
||||
assert_valid_keys
|
||||
|
||||
# this is needed to not break existing tests that may use keys supported by `Query` but not supported by `TextQuery`
|
||||
# can be removed in next minor version (> 2.4)
|
||||
invalid_keys = @options.keys - (COUNT_KEYS + [:wait])
|
||||
unless invalid_keys.empty?
|
||||
invalid_names = invalid_keys.map(&:inspect).join(", ")
|
||||
valid_names = valid_keys.map(&:inspect).join(", ")
|
||||
warn "invalid keys #{invalid_names}, should be one of #{valid_names}"
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_for(node)
|
||||
@actual_text = Capybara::Helpers.normalize_whitespace(node.text(@type))
|
||||
@count = @actual_text.scan(@search_regexp).size
|
||||
end
|
||||
|
||||
def failure_message
|
||||
description =
|
||||
if @expected_text.is_a?(Regexp)
|
||||
"text matching #{@expected_text.inspect}"
|
||||
else
|
||||
"text #{@expected_text.inspect}"
|
||||
end
|
||||
|
||||
message = Capybara::Helpers.failure_message(description, @options)
|
||||
unless (COUNT_KEYS & @options.keys).empty?
|
||||
message << " but found #{@count} #{Capybara::Helpers.declension('time', 'times', @count)}"
|
||||
end
|
||||
message << " in #{@actual_text.inspect}"
|
||||
end
|
||||
|
||||
def negative_failure_message
|
||||
failure_message.sub(/(to find)/, 'not \1')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def valid_keys
|
||||
Capybara::Query::VALID_KEYS # can be changed to COUNT_KEYS + [:wait] in next minor version (> 2.4)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
module Capybara
|
||||
# @api private
|
||||
module Queries
|
||||
class TitleQuery < BaseQuery
|
||||
def initialize(expected_title, options = {})
|
||||
@expected_title = expected_title
|
||||
@options = options
|
||||
unless @expected_title.is_a?(Regexp)
|
||||
@expected_title = Capybara::Helpers.normalize_whitespace(@expected_title)
|
||||
end
|
||||
@search_regexp = Capybara::Helpers.to_regexp(@expected_title)
|
||||
assert_valid_keys
|
||||
end
|
||||
|
||||
def resolves_for?(node)
|
||||
@actual_title = node.title
|
||||
@actual_title.match(@search_regexp)
|
||||
end
|
||||
|
||||
def failure_message
|
||||
failure_message_helper
|
||||
end
|
||||
|
||||
def negative_failure_message
|
||||
failure_message_helper(' not')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def failure_message_helper(negated = '')
|
||||
verb = (@expected_title.is_a?(Regexp))? 'match' : 'include'
|
||||
"expected #{@actual_title.inspect}#{negated} to #{verb} #{@expected_title.inspect}"
|
||||
end
|
||||
|
||||
def valid_keys
|
||||
[:wait]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,7 @@
|
|||
module Capybara
|
||||
class Query
|
||||
# @deprecated This class and its methods are not supposed to be used by users of Capybara's public API.
|
||||
# It may be removed in future versions of Capybara.
|
||||
class Query < Queries::BaseQuery
|
||||
attr_accessor :selector, :locator, :options, :expression, :find, :negative
|
||||
|
||||
VALID_KEYS = [:text, :visible, :between, :count, :maximum, :minimum, :exact, :match, :wait]
|
||||
|
@ -23,7 +25,7 @@ module Capybara
|
|||
end
|
||||
|
||||
@expression = @selector.call(@locator)
|
||||
assert_valid_keys!
|
||||
assert_valid_keys
|
||||
end
|
||||
|
||||
def name; selector.name; end
|
||||
|
@ -70,14 +72,6 @@ module Capybara
|
|||
end
|
||||
end
|
||||
|
||||
def wait
|
||||
if options.has_key?(:wait)
|
||||
@options[:wait] or 0
|
||||
else
|
||||
Capybara.default_wait_time
|
||||
end
|
||||
end
|
||||
|
||||
def exact?
|
||||
if options.has_key?(:exact)
|
||||
@options[:exact]
|
||||
|
@ -107,16 +101,32 @@ module Capybara
|
|||
@expression
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_valid_keys!
|
||||
valid_keys = VALID_KEYS + @selector.custom_filters.keys
|
||||
invalid_keys = @options.keys - valid_keys
|
||||
unless invalid_keys.empty?
|
||||
invalid_names = invalid_keys.map(&:inspect).join(", ")
|
||||
valid_names = valid_keys.map(&:inspect).join(", ")
|
||||
raise ArgumentError, "invalid keys #{invalid_names}, should be one of #{valid_names}"
|
||||
# @api private
|
||||
def resolve_for(node, exact = nil)
|
||||
node.synchronize do
|
||||
children = if selector.format == :css
|
||||
node.find_css(self.css)
|
||||
else
|
||||
node.find_xpath(self.xpath(exact))
|
||||
end.map do |child|
|
||||
if node.is_a?(Capybara::Node::Base)
|
||||
Capybara::Node::Element.new(node.session, child, node, self)
|
||||
else
|
||||
Capybara::Node::Simple.new(child)
|
||||
end
|
||||
end
|
||||
Capybara::Result.new(children, self)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def valid_keys
|
||||
COUNT_KEYS + [:text, :visible, :exact, :match, :wait] + @selector.custom_filters.keys
|
||||
end
|
||||
|
||||
def assert_valid_keys
|
||||
super
|
||||
unless VALID_MATCH.include?(match)
|
||||
raise ArgumentError, "invalid option #{match.inspect} for :match, should be one of #{VALID_MATCH.map(&:inspect).join(", ")}"
|
||||
end
|
||||
|
|
|
@ -51,7 +51,7 @@ module Capybara
|
|||
end
|
||||
|
||||
def negative_failure_message
|
||||
failure_message.sub(/(to be found|to find)/, 'not \1')
|
||||
failure_message.sub(/(to find)/, 'not \1')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@ module Capybara
|
|||
module RSpecMatchers
|
||||
class Matcher
|
||||
include ::RSpec::Matchers::Composable if defined?(::RSpec::Version) && ::RSpec::Version::STRING.to_f >= 3.0
|
||||
|
||||
|
||||
def wrap(actual)
|
||||
if actual.respond_to?("has_selector?")
|
||||
actual
|
||||
|
@ -14,7 +14,7 @@ module Capybara
|
|||
|
||||
class HaveSelector < Matcher
|
||||
attr_reader :failure_message, :failure_message_when_negated
|
||||
|
||||
|
||||
def initialize(*args)
|
||||
@args = args
|
||||
end
|
||||
|
@ -22,7 +22,7 @@ module Capybara
|
|||
def matches?(actual)
|
||||
wrap(actual).assert_selector(*@args)
|
||||
rescue Capybara::ExpectationNotMet => e
|
||||
@failure_message = e.message
|
||||
@failure_message = e.message
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -40,46 +40,40 @@ module Capybara
|
|||
def query
|
||||
@query ||= Capybara::Query.new(*@args)
|
||||
end
|
||||
|
||||
|
||||
# RSpec 2 compatibility:
|
||||
alias_method :failure_message_for_should, :failure_message
|
||||
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
||||
|
||||
end
|
||||
|
||||
class HaveText < Matcher
|
||||
attr_reader :type, :content, :options
|
||||
|
||||
attr_reader :failure_message, :failure_message_when_negated
|
||||
|
||||
def initialize(*args)
|
||||
@args = args.dup
|
||||
|
||||
# are set just for backwards compatability
|
||||
@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, content, options)
|
||||
wrap(actual).assert_text(*@args)
|
||||
rescue Capybara::ExpectationNotMet => e
|
||||
@failure_message = e.message
|
||||
return false
|
||||
end
|
||||
|
||||
def does_not_match?(actual)
|
||||
@actual = wrap(actual)
|
||||
@actual.has_no_text?(type, content, options)
|
||||
wrap(actual).assert_no_text(*@args)
|
||||
rescue Capybara::ExpectationNotMet => e
|
||||
@failure_message_when_negated = e.message
|
||||
return false
|
||||
end
|
||||
|
||||
def failure_message
|
||||
message = Capybara::Helpers.failure_message(description, options)
|
||||
message << " in #{format(@actual.text(type))}"
|
||||
message
|
||||
end
|
||||
|
||||
def failure_message_when_negated
|
||||
failure_message.sub(/(to find)/, 'not \1')
|
||||
end
|
||||
|
||||
# RSpec 2 compatibility:
|
||||
alias_method :failure_message_for_should, :failure_message
|
||||
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
||||
|
||||
def description
|
||||
"text #{format(content)}"
|
||||
end
|
||||
|
@ -88,40 +82,45 @@ module Capybara
|
|||
content = Capybara::Helpers.normalize_whitespace(content) unless content.is_a? Regexp
|
||||
content.inspect
|
||||
end
|
||||
|
||||
# RSpec 2 compatibility:
|
||||
alias_method :failure_message_for_should, :failure_message
|
||||
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
||||
end
|
||||
|
||||
class HaveTitle < Matcher
|
||||
attr_reader :title
|
||||
|
||||
def initialize(title)
|
||||
@title = title
|
||||
attr_reader :failure_message, :failure_message_when_negated
|
||||
|
||||
def initialize(*args)
|
||||
@args = args
|
||||
|
||||
# are set just for backwards compatability
|
||||
@title = args.first
|
||||
end
|
||||
|
||||
def matches?(actual)
|
||||
@actual = wrap(actual)
|
||||
@actual.has_title?(title)
|
||||
wrap(actual).assert_title(*@args)
|
||||
rescue Capybara::ExpectationNotMet => e
|
||||
@failure_message = e.message
|
||||
return false
|
||||
end
|
||||
|
||||
def does_not_match?(actual)
|
||||
@actual = wrap(actual)
|
||||
@actual.has_no_title?(title)
|
||||
wrap(actual).assert_no_title(*@args)
|
||||
rescue Capybara::ExpectationNotMet => e
|
||||
@failure_message_when_negated = e.message
|
||||
return false
|
||||
end
|
||||
|
||||
def failure_message
|
||||
"expected there to be title #{title.inspect} in #{@actual.title.inspect}"
|
||||
end
|
||||
|
||||
def failure_message_when_negated
|
||||
"expected there not to be title #{title.inspect} in #{@actual.title.inspect}"
|
||||
def description
|
||||
"have title #{title.inspect}"
|
||||
end
|
||||
|
||||
# RSpec 2 compatibility:
|
||||
alias_method :failure_message_for_should, :failure_message
|
||||
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
||||
|
||||
def description
|
||||
"have title #{title.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
class BecomeClosed
|
||||
|
@ -169,8 +168,8 @@ module Capybara
|
|||
end
|
||||
alias_method :have_content, :have_text
|
||||
|
||||
def have_title(title)
|
||||
HaveTitle.new(title)
|
||||
def have_title(title, options = {})
|
||||
HaveTitle.new(title, options)
|
||||
end
|
||||
|
||||
def have_link(locator, options={})
|
||||
|
|
|
@ -35,7 +35,11 @@ module Capybara
|
|||
:has_no_table?, :has_table?, :unselect, :has_select?, :has_no_select?,
|
||||
:has_selector?, :has_no_selector?, :click_on, :has_no_checked_field?,
|
||||
:has_no_unchecked_field?, :query, :assert_selector, :assert_no_selector,
|
||||
:refute_selector
|
||||
:refute_selector, :assert_text, :assert_no_text
|
||||
]
|
||||
# @api private
|
||||
DOCUMENT_METHODS = [
|
||||
:title, :assert_title, :assert_no_title, :has_title?, :has_no_title?
|
||||
]
|
||||
SESSION_METHODS = [
|
||||
:body, :html, :source, :current_url, :current_host, :current_path,
|
||||
|
@ -44,8 +48,8 @@ module Capybara
|
|||
:windows, :open_new_window, :switch_to_window, :within_window, :window_opened_by,
|
||||
:save_page, :save_and_open_page, :save_screenshot,
|
||||
:save_and_open_screenshot, :reset_session!, :response_headers,
|
||||
:status_code, :title, :has_title?, :has_no_title?, :current_scope
|
||||
]
|
||||
:status_code, :current_scope
|
||||
] + DOCUMENT_METHODS
|
||||
MODAL_METHODS = [
|
||||
:accept_alert, :accept_confirm, :dismiss_confirm, :accept_prompt,
|
||||
:dismiss_prompt
|
||||
|
@ -171,14 +175,6 @@ module Capybara
|
|||
driver.current_url
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# @return [String] Title of the current page
|
||||
#
|
||||
def title
|
||||
driver.title
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Navigate to the given URL. The URL can either be a relative URL or an absolute URL
|
||||
|
@ -699,32 +695,16 @@ module Capybara
|
|||
end
|
||||
end
|
||||
|
||||
DOCUMENT_METHODS.each do |method|
|
||||
define_method method do |*args, &block|
|
||||
document.send(method, *args, &block)
|
||||
end
|
||||
end
|
||||
|
||||
def inspect
|
||||
%(#<Capybara::Session>)
|
||||
end
|
||||
|
||||
def has_title?(content)
|
||||
document.synchronize do
|
||||
unless title.match(Capybara::Helpers.to_regexp(content))
|
||||
raise ExpectationNotMet
|
||||
end
|
||||
end
|
||||
return true
|
||||
rescue Capybara::ExpectationNotMet
|
||||
return false
|
||||
end
|
||||
|
||||
def has_no_title?(content)
|
||||
document.synchronize do
|
||||
if title.match(Capybara::Helpers.to_regexp(content))
|
||||
raise ExpectationNotMet
|
||||
end
|
||||
end
|
||||
return true
|
||||
rescue Capybara::ExpectationNotMet
|
||||
return false
|
||||
end
|
||||
|
||||
def current_scope
|
||||
scopes.last || document
|
||||
end
|
||||
|
|
|
@ -53,7 +53,7 @@ $(function() {
|
|||
$('#reload-list').click(function() {
|
||||
setTimeout(function() {
|
||||
$('#the-list').html('<li>Foo</li><li>Bar</li>');
|
||||
}, 250)
|
||||
}, 550)
|
||||
});
|
||||
$('#change-title').click(function() {
|
||||
setTimeout(function() {
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
Capybara::SpecHelper.spec '#assert_text' do
|
||||
it "should be true if the given text is on the page" do
|
||||
@session.visit('/with_html')
|
||||
expect(@session.assert_text('est')).to eq(true)
|
||||
expect(@session.assert_text('Lorem')).to eq(true)
|
||||
expect(@session.assert_text('Redirect')).to eq(true)
|
||||
expect(@session.assert_text(:'Redirect')).to eq(true)
|
||||
expect(@session.assert_text('text with whitespace')).to eq(true)
|
||||
expect(@session.assert_text("text with \n\n whitespace")).to eq(true)
|
||||
end
|
||||
|
||||
it "should take scopes into account" do
|
||||
@session.visit('/with_html')
|
||||
@session.within("//a[@title='awesome title']") do
|
||||
expect(@session.assert_text('labore')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
it "should raise if scoped to an element which does not have the text" do
|
||||
@session.visit('/with_html')
|
||||
@session.within("//a[@title='awesome title']") do
|
||||
expect do
|
||||
@session.assert_text('monkey')
|
||||
end.to raise_error(Capybara::ExpectationNotMet, 'expected to find text "monkey" in "labore"')
|
||||
end
|
||||
end
|
||||
|
||||
it "should be true if :all given and text is invisible." do
|
||||
@session.visit('/with_html')
|
||||
expect(@session.assert_text(:all, 'Some of this text is hidden!')).to eq(true)
|
||||
end
|
||||
|
||||
it "should be true if `Capybara.ignore_hidden_elements = true` and text is invisible." do
|
||||
Capybara.ignore_hidden_elements = false
|
||||
@session.visit('/with_html')
|
||||
expect(@session.assert_text('Some of this text is hidden!')).to eq(true)
|
||||
end
|
||||
|
||||
it "should be true if the text in the page matches given regexp" do
|
||||
@session.visit('/with_html')
|
||||
expect(@session.assert_text(/Lorem/)).to eq(true)
|
||||
end
|
||||
|
||||
it "should be raise error if the text in the page doesn't match given regexp" do
|
||||
@session.visit('/with_html')
|
||||
expect do
|
||||
@session.assert_text(/xxxxyzzz/)
|
||||
end.to raise_error(Capybara::ExpectationNotMet, /\Aexpected to find text matching \/xxxxyzzz\/ in "This is a test Header Class(.+)"\Z/)
|
||||
end
|
||||
|
||||
it "should escape any characters that would have special meaning in a regexp" do
|
||||
@session.visit('/with_html')
|
||||
expect do
|
||||
@session.assert_text('.orem')
|
||||
end.to raise_error(Capybara::ExpectationNotMet)
|
||||
end
|
||||
|
||||
it "should wait for text to appear", :requires => [:js] do
|
||||
@session.visit('/with_js')
|
||||
@session.click_link('Click me')
|
||||
expect(@session.assert_text('Has been clicked')).to eq(true)
|
||||
end
|
||||
|
||||
context "with between" do
|
||||
it "should be true if the text occurs within the range given" do
|
||||
@session.visit('/with_count')
|
||||
expect(@session.assert_text('count', between: 1..3)).to eq(true)
|
||||
end
|
||||
|
||||
it "should be false if the text occurs more or fewer times than range" do
|
||||
@session.visit('/with_html')
|
||||
expect do
|
||||
@session.find(:css, '.number').assert_text(/\d/, between: 0..1)
|
||||
end.to raise_error(Capybara::ExpectationNotMet, "expected to find text matching /\\d/ between 0 and 1 times but found 2 times in \"42\"")
|
||||
end
|
||||
end
|
||||
|
||||
context "with wait", :requires => [:js] do
|
||||
it "should find element if it appears before given wait duration" do
|
||||
Capybara.using_wait_time(0) do
|
||||
@session.visit('/with_js')
|
||||
@session.find(:css, '#reload-list').click
|
||||
@session.find(:css, '#the-list').assert_text('Foo Bar', wait: 0.9)
|
||||
end
|
||||
end
|
||||
|
||||
it "should raise error if it appears after given wait duration" do
|
||||
Capybara.using_wait_time(0) do
|
||||
@session.visit('/with_js')
|
||||
@session.find(:css, '#reload-list').click
|
||||
el = @session.find(:css, '#the-list', visible: false)
|
||||
expect do
|
||||
el.assert_text(:all, 'Foo Bar', wait: 0.3)
|
||||
end.to raise_error(Capybara::ExpectationNotMet)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with multiple count filters' do
|
||||
before(:each) do
|
||||
@session.visit('/with_html')
|
||||
end
|
||||
|
||||
it 'ignores other filters when :count is specified' do
|
||||
o = {:count => 5,
|
||||
:minimum => 6,
|
||||
:maximum => 0,
|
||||
:between => 0..4}
|
||||
expect { @session.assert_text('Header', o) }.not_to raise_error
|
||||
end
|
||||
context 'with no :count expectation' do
|
||||
it 'fails if :minimum is not met' do
|
||||
o = {:minimum => 6,
|
||||
:maximum => 5,
|
||||
:between => 2..7}
|
||||
expect { @session.assert_text('Header', 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.assert_text('Header', o) }.to raise_error(Capybara::ExpectationNotMet)
|
||||
end
|
||||
it 'fails if :between is not met' do
|
||||
o = {:minimum => 0,
|
||||
:maximum => 5,
|
||||
:between => 0..4}
|
||||
expect { @session.assert_text('Header', o) }.to raise_error(Capybara::ExpectationNotMet)
|
||||
end
|
||||
it 'succeeds if all combineable expectations are met' do
|
||||
o = {:minimum => 0,
|
||||
:maximum => 5,
|
||||
:between => 2..7}
|
||||
expect { @session.assert_text('Header', o) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Capybara::SpecHelper.spec '#assert_no_text' do
|
||||
it "should raise error if the given text is on the page at least once" do
|
||||
@session.visit('/with_html')
|
||||
expect do
|
||||
@session.assert_no_text('Lorem')
|
||||
end.to raise_error(Capybara::ExpectationNotMet, /\Aexpected not to find text "Lorem" in "This is a test Header Class.+"\Z/)
|
||||
end
|
||||
|
||||
it "should be true if scoped to an element which does not have the text" do
|
||||
@session.visit('/with_html')
|
||||
@session.within("//a[@title='awesome title']") do
|
||||
expect(@session.assert_no_text('monkey')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
it "should be true if the given text is on the page but not visible" do
|
||||
@session.visit('/with_html')
|
||||
expect(@session.assert_no_text('Inside element with hidden ancestor')).to eq(true)
|
||||
end
|
||||
|
||||
it "should raise error if :all given and text is invisible." do
|
||||
@session.visit('/with_html')
|
||||
el = @session.find(:css, '#hidden-text', visible: false)
|
||||
expect do
|
||||
el.assert_no_text(:all, 'Some of this text is hidden!')
|
||||
end.to raise_error(Capybara::ExpectationNotMet, 'expected not to find text "Some of this text is hidden!" in "Some of this text is hidden!"')
|
||||
end
|
||||
|
||||
it "should be true if the text in the page doesn't match given regexp" do
|
||||
@session.visit('/with_html')
|
||||
@session.assert_no_text(/xxxxyzzz/)
|
||||
end
|
||||
|
||||
context "with count" do
|
||||
it "should be true if the text occurs within the range given" do
|
||||
@session.visit('/with_count')
|
||||
expect(@session.assert_text('count', count: 2)).to eq(true)
|
||||
end
|
||||
|
||||
it "should be false if the text occurs more or fewer times than range" do
|
||||
@session.visit('/with_html')
|
||||
expect do
|
||||
@session.find(:css, '.number').assert_text(/\d/, count: 1)
|
||||
end.to raise_error(Capybara::ExpectationNotMet, "expected to find text matching /\\d/ 1 time but found 2 times in \"42\"")
|
||||
end
|
||||
end
|
||||
|
||||
context "with wait", :requires => [:js] do
|
||||
it "should not find element if it appears after given wait duration" do
|
||||
@session.visit('/with_js')
|
||||
@session.click_link('Click me')
|
||||
@session.find(:css, '#reload-list').click
|
||||
@session.find(:css, '#the-list').assert_no_text('Foo Bar', :wait => 0.4)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,70 @@
|
|||
Capybara::SpecHelper.spec '#assert_title' do
|
||||
before do
|
||||
@session.visit('/with_js')
|
||||
end
|
||||
|
||||
it "should be true if the page's title contains the given string" do
|
||||
expect(@session.assert_title('js')).to eq(true)
|
||||
end
|
||||
|
||||
it "should be true when given an empty string" do
|
||||
expect(@session.assert_title('')).to eq(true)
|
||||
end
|
||||
|
||||
it "should allow regexp matches" do
|
||||
@session.should have_title(/w[a-z]{3}_js/)
|
||||
expect(@session.assert_title(/w[a-z]{3}_js/)).to eq(true)
|
||||
expect do
|
||||
@session.assert_title(/w[a-z]{10}_js/)
|
||||
end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to match /w[a-z]{10}_js/')
|
||||
end
|
||||
|
||||
it "should wait for title", :requires => [:js] do
|
||||
@session.click_link("Change title")
|
||||
expect(@session.assert_title("changed title")).to eq(true)
|
||||
end
|
||||
|
||||
it "should raise error if the title doesn't contain the given string" do
|
||||
expect do
|
||||
@session.assert_title('monkey')
|
||||
end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to include "monkey"')
|
||||
end
|
||||
|
||||
it "should normalize given title" do
|
||||
@session.assert_title(' with_js ')
|
||||
end
|
||||
|
||||
it "should normalize given title in error message" do
|
||||
expect do
|
||||
@session.assert_title(2)
|
||||
end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to include "2"')
|
||||
end
|
||||
end
|
||||
|
||||
Capybara::SpecHelper.spec '#assert_no_title' do
|
||||
before do
|
||||
@session.visit('/with_js')
|
||||
end
|
||||
|
||||
it "should raise error if the title contains the given string" do
|
||||
expect do
|
||||
@session.assert_no_title('with_j')
|
||||
end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" not to include "with_j"')
|
||||
end
|
||||
|
||||
it "should allow regexp matches" do
|
||||
expect do
|
||||
@session.assert_no_title(/w[a-z]{3}_js/)
|
||||
end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" not to match /w[a-z]{3}_js/')
|
||||
@session.assert_no_title(/monkey/)
|
||||
end
|
||||
|
||||
it "should wait for title to disappear", :requires => [:js] do
|
||||
@session.click_link("Change title")
|
||||
expect(@session.assert_no_title('with_js')).to eq(true)
|
||||
end
|
||||
|
||||
it "should be true if the title doesn't contain the given string" do
|
||||
expect(@session.assert_no_title('monkey')).to eq(true)
|
||||
end
|
||||
end
|
|
@ -106,7 +106,7 @@ Capybara::SpecHelper.spec '#has_text?' do
|
|||
end
|
||||
|
||||
it "should be true when passed nil" do
|
||||
# Historical behavior; no particular reason other than compatibility.
|
||||
# nil is converted to '' when to_s is invoked
|
||||
@session.visit('/with_html')
|
||||
expect(@session).to have_text(nil)
|
||||
end
|
||||
|
|
|
@ -5,12 +5,12 @@ require 'capybara/rspec/matchers'
|
|||
RSpec.describe Capybara::RSpecMatchers do
|
||||
include Capybara::DSL
|
||||
include Capybara::RSpecMatchers
|
||||
|
||||
|
||||
describe "have_css matcher" do
|
||||
it "gives proper description" do
|
||||
expect(have_css('h1').description).to eq("have css \"h1\"")
|
||||
end
|
||||
|
||||
|
||||
context "on a string" do
|
||||
context "with should" do
|
||||
it "passes if has_css? returns true" do
|
||||
|
@ -350,20 +350,26 @@ RSpec.describe Capybara::RSpecMatchers do
|
|||
|
||||
context "on a string" do
|
||||
context "with should" do
|
||||
it "passes if has_text? returns true" do
|
||||
it "passes if text contains given string" do
|
||||
expect("<h1>Text</h1>").to have_text('Text')
|
||||
end
|
||||
|
||||
it "passes if has_text? returns true using regexp" do
|
||||
it "passes if text matches given regexp" do
|
||||
expect("<h1>Text</h1>").to have_text(/ext/)
|
||||
end
|
||||
|
||||
it "fails if has_text? returns false" do
|
||||
it "fails if text doesn't contain given string" do
|
||||
expect do
|
||||
expect("<h1>Text</h1>").to have_text('No such Text')
|
||||
end.to raise_error(/expected to find text "No such Text" in "Text"/)
|
||||
end
|
||||
|
||||
it "fails if text doesn't match given regexp" do
|
||||
expect do
|
||||
expect("<h1>Text</h1>").to have_text(/No such Text/)
|
||||
end.to raise_error('expected to find text matching /No such Text/ in "Text"')
|
||||
end
|
||||
|
||||
it "casts Fixnum to string" do
|
||||
expect do
|
||||
expect("<h1>Text</h1>").to have_text(3)
|
||||
|
@ -373,30 +379,30 @@ RSpec.describe Capybara::RSpecMatchers do
|
|||
it "fails if matched text count does not equal to expected count" do
|
||||
expect do
|
||||
expect("<h1>Text</h1>").to have_text('Text', count: 2)
|
||||
end.to raise_error(/expected to find text "Text" 2 times in "Text"/)
|
||||
end.to raise_error('expected to find text "Text" 2 times but found 1 time in "Text"')
|
||||
end
|
||||
|
||||
it "fails if matched text count is less than expected minimum count" do
|
||||
expect do
|
||||
expect("<h1>Text</h1>").to have_text('Lorem', minimum: 1)
|
||||
end.to raise_error(/expected to find text "Lorem" at least 1 time in "Text"/)
|
||||
end.to raise_error('expected to find text "Lorem" at least 1 time but found 0 times in "Text"')
|
||||
end
|
||||
|
||||
it "fails if matched text count is more than expected maximum count" do
|
||||
expect do
|
||||
expect("<h1>Text TextText</h1>").to have_text('Text', maximum: 2)
|
||||
end.to raise_error(/expected to find text "Text" at most 2 times in "Text TextText"/)
|
||||
end.to raise_error('expected to find text "Text" at most 2 times but found 3 times in "Text TextText"')
|
||||
end
|
||||
|
||||
it "fails if matched text count does not belong to expected range" do
|
||||
expect do
|
||||
expect("<h1>Text</h1>").to have_text('Text', between: 2..3)
|
||||
end.to raise_error(/expected to find text "Text" between 2 and 3 times in "Text"/)
|
||||
end.to raise_error('expected to find text "Text" between 2 and 3 times but found 1 time in "Text"')
|
||||
end
|
||||
end
|
||||
|
||||
context "with should_not" do
|
||||
it "passes if has_no_text? returns true" do
|
||||
it "passes if text doesn't contain a string" do
|
||||
expect("<h1>Text</h1>").not_to have_text('No such Text')
|
||||
end
|
||||
|
||||
|
@ -404,7 +410,7 @@ RSpec.describe Capybara::RSpecMatchers do
|
|||
expect("<h1>Text</h1>").not_to have_text('.')
|
||||
end
|
||||
|
||||
it "fails if has_no_text? returns false" do
|
||||
it "fails if text contains a string" do
|
||||
expect do
|
||||
expect("<h1>Text</h1>").not_to have_text('Text')
|
||||
end.to raise_error(/expected not to find text "Text" in "Text"/)
|
||||
|
@ -477,7 +483,7 @@ RSpec.describe Capybara::RSpecMatchers do
|
|||
it "gives proper description" do
|
||||
expect(have_link('Just a link').description).to eq("have link \"Just a link\"")
|
||||
end
|
||||
|
||||
|
||||
it "passes if there is such a button" do
|
||||
expect(html).to have_link('Just a link')
|
||||
end
|
||||
|
@ -509,23 +515,48 @@ RSpec.describe Capybara::RSpecMatchers do
|
|||
it "fails if there is no such title" do
|
||||
expect do
|
||||
expect(html).to have_title('No such title')
|
||||
end.to raise_error(/expected there to be title "No such title"/)
|
||||
end.to raise_error('expected "Just a title" to include "No such title"')
|
||||
end
|
||||
|
||||
it "fails if title doesn't match regexp" do
|
||||
expect do
|
||||
expect(html).to have_title(/[[:upper:]]+[[:lower:]]+l{2}o/)
|
||||
end.to raise_error('expected "Just a title" to match /[[:upper:]]+[[:lower:]]+l{2}o/')
|
||||
end
|
||||
end
|
||||
|
||||
context "on a page or node" do
|
||||
before do
|
||||
visit('/with_js')
|
||||
end
|
||||
|
||||
it "passes if there is such a title" do
|
||||
visit('/with_js')
|
||||
expect(page).to have_title('with_js')
|
||||
end
|
||||
|
||||
it "fails if there is no such title" do
|
||||
visit('/with_js')
|
||||
expect do
|
||||
expect(page).to have_title('No such title')
|
||||
end.to raise_error(/expected there to be title "No such title"/)
|
||||
end.to raise_error('expected "with_js" to include "No such title"')
|
||||
end
|
||||
|
||||
context 'with wait' do
|
||||
before(:each) do
|
||||
@session = TestSessions::Selenium
|
||||
@session.visit('/with_js')
|
||||
end
|
||||
|
||||
it 'waits if wait time is more than timeout' do
|
||||
@session.click_link("Change title")
|
||||
using_wait_time 0 do
|
||||
expect(@session).to have_title('changed title', wait: 0.5)
|
||||
end
|
||||
end
|
||||
|
||||
it "doesn't wait if wait time is less than timeout" do
|
||||
@session.click_link("Change title")
|
||||
using_wait_time 0 do
|
||||
expect(@session).not_to have_title('changed title')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -727,7 +758,7 @@ RSpec.describe Capybara::RSpecMatchers do
|
|||
it "gives proper description" do
|
||||
expect(have_table('Lovely table').description).to eq("have table \"Lovely table\"")
|
||||
end
|
||||
|
||||
|
||||
it "passes if there is such a select" do
|
||||
expect(html).to have_table('Lovely table')
|
||||
end
|
||||
|
@ -743,4 +774,3 @@ RSpec.describe Capybara::RSpecMatchers do
|
|||
end if RSpec::Version::STRING.to_f >= 3.0
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue