RSpec matchers filter block

This commit is contained in:
Thomas Walpole 2016-11-18 15:22:04 -08:00
parent de24df6f28
commit 3948f93346
5 changed files with 60 additions and 44 deletions

View File

@ -12,14 +12,16 @@ module Capybara
end
end
def matches?(actual)
private
def wrap_matches?(actual)
yield(wrap(actual))
rescue Capybara::ExpectationNotMet => e
@failure_message = e.message
return false
end
def does_not_match?(actual)
def wrap_does_not_match?(actual)
yield(wrap(actual))
rescue Capybara::ExpectationNotMet => e
@failure_message_when_negated = e.message
@ -36,11 +38,11 @@ module Capybara
end
def matches?(actual)
super(actual){ |el| el.assert_selector(*@args) }
wrap_matches?(actual){ |el| el.assert_selector(*@args, &@filter_block) }
end
def does_not_match?(actual)
super(actual){ |el| el.assert_no_selector(*@args) }
wrap_does_not_match?(actual){ |el| el.assert_no_selector(*@args, &@filter_block) }
end
def description
@ -56,6 +58,24 @@ module Capybara
alias_method :failure_message_for_should_not, :failure_message_when_negated
end
class MatchSelector < HaveSelector
def matches?(actual)
wrap_matches?(actual) { |el| el.assert_matches_selector(*@args, &@filter_block) }
end
def does_not_match?(actual)
wrap_does_not_match?(actual) { |el| el.assert_not_matches_selector(*@args, &@filter_block) }
end
def description
"match #{query.description}"
end
def query
@query ||= Capybara::Queries::MatchQuery.new(*@args)
end
end
class HaveText < Matcher
attr_reader :type, :content, :options
@ -71,11 +91,11 @@ module Capybara
end
def matches?(actual)
super(actual) { |el| el.assert_text(*@args) }
wrap_matches?(actual) { |el| el.assert_text(*@args) }
end
def does_not_match?(actual)
super(actual) { |el| el.assert_no_text(*@args) }
wrap_does_not_match?(actual) { |el| el.assert_no_text(*@args) }
end
def description
@ -105,11 +125,11 @@ module Capybara
end
def matches?(actual)
super(actual) { |el| el.assert_title(*@args) }
wrap_matches?(actual) { |el| el.assert_title(*@args) }
end
def does_not_match?(actual)
super(actual) { |el| el.assert_no_title(*@args) }
wrap_does_not_match?(actual) { |el| el.assert_no_title(*@args) }
end
def description
@ -134,11 +154,11 @@ module Capybara
end
def matches?(actual)
super(actual) { |el| el.assert_current_path(*@args) }
wrap_matches?(actual) { |el| el.assert_current_path(*@args) }
end
def does_not_match?(actual)
super(actual) { |el| el.assert_no_current_path(*@args) }
wrap_does_not_match?(actual) { |el| el.assert_no_current_path(*@args) }
end
def description
@ -178,40 +198,12 @@ module Capybara
alias_method :failure_message_for_should_not, :failure_message_when_negated
end
class MatchSelector < Matcher
attr_reader :failure_message, :failure_message_when_negated
def initialize(*args)
@args = args
end
def matches?(actual)
super(actual) { |el| el.assert_matches_selector(*@args) }
end
def does_not_match?(actual)
super(actual) { |el| el.assert_not_matches_selector(*@args) }
end
def description
"match #{query.description}"
end
def query
@query ||= Capybara::Queries::MatchQuery.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
def have_selector(*args, &optional_filter_block)
HaveSelector.new(*args, &optional_filter_block)
end
def match_selector(*args)
MatchSelector.new(*args)
def match_selector(*args, &optional_filter_block)
MatchSelector.new(*args, &optional_filter_block)
end
# defined_negated_matcher was added in RSpec 3.1 - it's syntactic sugar only since a user can do
# expect(page).not_to match_selector, so not sure we really need to support not_match_selector for prior to RSpec 3.1
@ -222,16 +214,16 @@ module Capybara
HaveSelector.new(:xpath, xpath, options, &optional_filter_block)
end
def match_xpath(xpath, options={})
MatchSelector.new(:xpath, xpath, options)
def match_xpath(xpath, options={}, &optional_filter_block)
MatchSelector.new(:xpath, xpath, options, &optional_filter_block)
end
def have_css(css, options={}, &optional_filter_block)
HaveSelector.new(:css, css, options, &optional_filter_block)
end
def match_css(css, options={})
MatchSelector.new(:css, css, options)
def match_css(css, options={}, &optional_filter_block)
MatchSelector.new(:css, css, options, &optional_filter_block)
end
def have_text(*args)

View File

@ -28,4 +28,9 @@ Capybara::SpecHelper.spec '#assert_matches_selector' do
it "should not accept count options" do
expect { @element.assert_matches_selector(:css, '.number', count: 1) }.to raise_error(ArgumentError)
end
it "should accept a filter block" do
@element.assert_matches_selector(:css, 'span') { |el| el[:class] == "number" }
@element.assert_not_matches_selector(:css,'span') { |el| el[:class] == "not_number" }
end
end

View File

@ -14,4 +14,10 @@ Capybara::SpecHelper.spec '#match_css?' do
expect(@element).not_to match_css("p a#doesnotexist")
expect(@element).not_to match_css("p.nosuchclass")
end
it "should accept an optional filter block" do
# This would be better done with
expect(@element).to match_css('span') { |el| el[:class] == "number" }
expect(@element).not_to match_css('span') { |el| el[:class] == "not_number" }
end
end

View File

@ -52,6 +52,8 @@ Capybara::SpecHelper.spec '#match_selector?' do
it 'should accept a custom filter block' do
@session.visit('/form')
cbox = @session.find(:css, '#form_pets_dog')
expect(cbox).to match_selector(:checkbox){ |node| node[:id] == "form_pets_dog"}
expect(cbox).not_to match_selector(:checkbox){ |node| node[:id] != "form_pets_dog"}
expect(cbox.matches_selector?(:checkbox){ |node| node[:id] == "form_pets_dog"}).to be true
expect(cbox.matches_selector?(:checkbox){ |node| node[:id] != "form_pets_dog"}).to be false
end

View File

@ -29,6 +29,10 @@ Capybara::SpecHelper.spec '#has_selector?' do
end
end
it "should accept a filter block" do
expect(@session).to have_selector(:css, "a", count: 1) { |el| el[:id] == "foo" }
end
context "with count" do
it "should be true if the content is on the page the given number of times" do
expect(@session).to have_selector("//p", count: 3)
@ -105,6 +109,13 @@ Capybara::SpecHelper.spec '#has_no_selector?' do
end
end
it "should accept a filter block" do
if !defined?(::RSpec::Expectations::Version) || (Gem::Version.new(RSpec::Expectations::Version::STRING) < Gem::Version.new('3.0'))
skip "RSpec < 3 doesn't pass the block along to the matcher for the Builtin::Has matcher"
end
expect(@session).to have_no_selector(:css, "a#foo") { |el| el[:id] != "foo" }
end
context "with count" do
it "should be false if the content is on the page the given number of times" do
expect(@session).not_to have_no_selector("//p", count: 3)