diff --git a/features/step_definitions/capybara_steps.rb b/features/step_definitions/capybara_steps.rb index 994dd7cbe..76ab1ed6e 100644 --- a/features/step_definitions/capybara_steps.rb +++ b/features/step_definitions/capybara_steps.rb @@ -13,7 +13,7 @@ When /^I use a matcher that fails$/ do begin expect(page).to have_css('h1#doesnotexist') - rescue StandardError => e + rescue StandardError, RSpec::Expectations::ExpectationNotMetError => e @error_message = e.message end end diff --git a/lib/capybara/rspec/matchers.rb b/lib/capybara/rspec/matchers.rb index 7412678de..98a05db67 100644 --- a/lib/capybara/rspec/matchers.rb +++ b/lib/capybara/rspec/matchers.rb @@ -1,6 +1,8 @@ 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 @@ -11,16 +13,24 @@ def wrap(actual) end class HaveSelector < Matcher + attr_accessor :failure_message, :failure_message_when_negated + def initialize(*args) @args = args end def matches?(actual) wrap(actual).assert_selector(*@args) + rescue Capybara::ExpectationNotMet => e + @failure_message = e.message + return false end def does_not_match?(actual) wrap(actual).assert_no_selector(*@args) + rescue Capybara::ExpectationNotMet => e + @failure_message_when_negated = e.message + return false end def description @@ -30,6 +40,11 @@ def description 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 diff --git a/spec/rspec/matchers_spec.rb b/spec/rspec/matchers_spec.rb index 451ba3ccc..2b3755506 100644 --- a/spec/rspec/matchers_spec.rb +++ b/spec/rspec/matchers_spec.rb @@ -5,12 +5,12 @@ 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 @@ -74,6 +74,11 @@ end.to raise_error(/expected not to find css "h1"/) end end + + it "supports compounding" do + expect("

Text

Text

").to have_css('h1').and have_css('h2') + expect("

Text

Text

").to have_css('h3').or have_css('h1') + end if RSpec::Version::STRING.to_f >= 3.0 end context "on a page or node" do @@ -136,6 +141,11 @@ end.to raise_error(%r(expected not to find xpath "//h1")) end end + + it "supports compounding" do + expect("

Text

Text

").to have_xpath('//h1').and have_xpath('//h2') + expect("

Text

Text

").to have_xpath('//h3').or have_xpath('//h1') + end if RSpec::Version::STRING.to_f >= 3.0 end context "on a page or node" do @@ -237,6 +247,11 @@ end end end + + it "supports compounding" do + expect("

Text

Text

").to have_selector('//h1').and have_selector('//h2') + expect("

Text

Text

").to have_selector('//h3').or have_selector('//h1') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_content matcher" do @@ -321,6 +336,11 @@ end end end + + it "supports compounding" do + expect("

Text

And

").to have_content('Text').and have_content('And') + expect("

Text

Or

").to have_content('XYZ').or have_content('Or') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_text matcher" do @@ -444,15 +464,20 @@ end end end + + it "supports compounding" do + expect("

Text

And

").to have_text('Text').and have_text('And') + expect("

Text

Or

").to have_text('Not here').or have_text('Or') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_link matcher" do - let(:html) { 'Just a link' } + let(:html) { 'Just a linkAnother link' } 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 @@ -462,6 +487,11 @@ expect(html).to have_link('No such Link') end.to raise_error(/expected to find link "No such Link"/) end + + it "supports compounding" do + expect(html).to have_link('Just a link').and have_link('Another link') + expect(html).to have_link('Not a link').or have_link('Another link') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_title matcher" do @@ -498,6 +528,10 @@ end.to raise_error(/expected there to be title "No such title"/) end end + + it "supports compounding" do + expect("I compound").to have_title('I dont compound').or have_title('I compound') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_button matcher" do @@ -516,6 +550,10 @@ expect(html).to have_button('No such Button') end.to raise_error(/expected to find button "No such Button"/) end + + it "supports compounding" do + expect(html).to have_button('Not this button').or have_button('A button') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_field matcher" do @@ -557,6 +595,10 @@ def to_s end expect(html).to have_field('Text field', with: Foo.new) end + + it "supports compounding" do + expect(html).to have_field('Not this one').or have_field('Text field') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_checked_field matcher" do @@ -602,6 +644,10 @@ def to_s expect(html).not_to have_checked_field('no such field') end end + + it "supports compounding" do + expect(html).to have_checked_field('not this one').or have_checked_field('it is checked') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_unchecked_field matcher" do @@ -647,6 +693,10 @@ def to_s expect(html).not_to have_unchecked_field('no such field') end end + + it "supports compounding" do + expect(html).to have_unchecked_field('it is checked').or have_unchecked_field('unchecked field') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_select matcher" do @@ -665,6 +715,10 @@ def to_s expect(html).to have_select('No such Select box') end.to raise_error(/expected to find select box "No such Select box"/) end + + it "supports compounding" do + expect(html).to have_select('Not this one').or have_select('Select Box') + end if RSpec::Version::STRING.to_f >= 3.0 end describe "have_table matcher" do @@ -673,7 +727,7 @@ def to_s 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 @@ -683,5 +737,10 @@ def to_s expect(html).to have_table('No such Table') end.to raise_error(/expected to find table "No such Table"/) end + + it "supports compounding" do + expect(html).to have_table('nope').or have_table('Lovely table') + end if RSpec::Version::STRING.to_f >= 3.0 end end +