diff --git a/Changelog.md b/Changelog.md index 2ffb30677..46945989c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Breaking Changes: * Ruby < 2.3 is no longer supported. (Phil Pirozhkov, #1231) * Extract `should*` (both monkey-patching and non-monkey-patching). (Phil Pirozhkov, #1245) * Remove deprecated `LegacyMacherAdapter`. (Phil Pirozhkov, #????) +* Remove support for legacy RSpec 1&2 matchers. (Phil Pirozhkov, #????) Enhancements: diff --git a/lib/rspec/expectations/handler.rb b/lib/rspec/expectations/handler.rb index e8b46b7dd..5e2c4643e 100644 --- a/lib/rspec/expectations/handler.rb +++ b/lib/rspec/expectations/handler.rb @@ -12,18 +12,8 @@ def self.check_message(msg) end end - # Returns an RSpec-3+ compatible matcher, wrapping a legacy one - # in an adapter if necessary. - # - # @private - def self.modern_matcher_from(matcher) - LegacyMatcherAdapter::RSpec2.wrap(matcher) || - LegacyMatcherAdapter::RSpec1.wrap(matcher) || matcher - end - def self.with_matcher(handler, matcher, message) check_message(message) - matcher = modern_matcher_from(matcher) yield matcher ensure ::RSpec::Matchers.last_expectation_handler = handler @@ -101,72 +91,5 @@ def self.opposite_should_method :should end end - - # Wraps a matcher written against one of the legacy protocols in - # order to present the current protocol. - # - # @private - class LegacyMatcherAdapter < Matchers::MatcherDelegator - def initialize(matcher) - super - ::RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''), :type => "legacy_matcher") - |#{matcher.class.name || matcher.inspect} implements a legacy RSpec matcher - |protocol. For the current protocol you should expose the failure messages - |via the `failure_message` and `failure_message_when_negated` methods. - |(Used from #{CallerFilter.first_non_rspec_line}) - EOS - end - - def self.wrap(matcher) - new(matcher) if interface_matches?(matcher) - end - - # Starting in RSpec 1.2 (and continuing through all 2.x releases), - # the failure message protocol was: - # * `failure_message_for_should` - # * `failure_message_for_should_not` - # @private - class RSpec2 < self - def failure_message - base_matcher.failure_message_for_should - end - - def failure_message_when_negated - base_matcher.failure_message_for_should_not - end - - def self.interface_matches?(matcher) - ( - !matcher.respond_to?(:failure_message) && - matcher.respond_to?(:failure_message_for_should) - ) || ( - !matcher.respond_to?(:failure_message_when_negated) && - matcher.respond_to?(:failure_message_for_should_not) - ) - end - end - - # Before RSpec 1.2, the failure message protocol was: - # * `failure_message` - # * `negative_failure_message` - # @private - class RSpec1 < self - def failure_message - base_matcher.failure_message - end - - def failure_message_when_negated - base_matcher.negative_failure_message - end - - # Note: `failure_message` is part of the RSpec 3 protocol - # (paired with `failure_message_when_negated`), so we don't check - # for `failure_message` here. - def self.interface_matches?(matcher) - !matcher.respond_to?(:failure_message_when_negated) && - matcher.respond_to?(:negative_failure_message) - end - end - end end end diff --git a/lib/rspec/matchers.rb b/lib/rspec/matchers.rb index 444c83f11..114c176ee 100644 --- a/lib/rspec/matchers.rb +++ b/lib/rspec/matchers.rb @@ -981,8 +981,7 @@ def self.is_a_matcher?(obj) end return false unless obj.respond_to?(:matches?) - obj.respond_to?(:failure_message) || - obj.respond_to?(:failure_message_for_should) # support legacy matchers + obj.respond_to?(:failure_message) end ::RSpec::Support.register_matcher_definition do |obj| diff --git a/lib/rspec/matchers/dsl.rb b/lib/rspec/matchers/dsl.rb index c6119ac1b..390537e2d 100644 --- a/lib/rspec/matchers/dsl.rb +++ b/lib/rspec/matchers/dsl.rb @@ -335,34 +335,6 @@ def define_user_override(method_name, user_def, &our_def) our_def ||= lambda { super(*actual_arg_for(user_def)) } define_method(method_name, &our_def) end - - # Defines deprecated macro methods from RSpec 2 for backwards compatibility. - # @deprecated Use the methods from {Macros} instead. - module Deprecated - # @deprecated Use {Macros#match} instead. - def match_for_should(&definition) - RSpec.deprecate("`match_for_should`", :replacement => "`match`") - match(&definition) - end - - # @deprecated Use {Macros#match_when_negated} instead. - def match_for_should_not(&definition) - RSpec.deprecate("`match_for_should_not`", :replacement => "`match_when_negated`") - match_when_negated(&definition) - end - - # @deprecated Use {Macros#failure_message} instead. - def failure_message_for_should(&definition) - RSpec.deprecate("`failure_message_for_should`", :replacement => "`failure_message`") - failure_message(&definition) - end - - # @deprecated Use {Macros#failure_message_when_negated} instead. - def failure_message_for_should_not(&definition) - RSpec.deprecate("`failure_message_for_should_not`", :replacement => "`failure_message_when_negated`") - failure_message_when_negated(&definition) - end - end end # Defines default implementations of the matcher @@ -425,7 +397,6 @@ class Matcher # Makes the macro methods available to an `RSpec::Matchers.define` block. extend Macros - extend Macros::Deprecated # Exposes the value being matched against -- generally the object # object wrapped by `expect`. diff --git a/spec/rspec/matchers/dsl_spec.rb b/spec/rspec/matchers/dsl_spec.rb index 46b085e34..e999658cd 100644 --- a/spec/rspec/matchers/dsl_spec.rb +++ b/spec/rspec/matchers/dsl_spec.rb @@ -199,90 +199,6 @@ def new_matcher(name, *expected, &block) expect(m2.matches?(2)).to be_truthy end - context 'using deprecated APIs' do - before { allow_deprecation } - - describe "failure_message_for_should" do - let(:matcher) do - new_matcher(:foo) do - match { false } - failure_message_for_should { "failed" } - end - end - line = __LINE__ - 3 - - it 'defines the failure message for a positive expectation' do - expect { - expect(nil).to matcher - }.to fail_with("failed") - end - - it 'prints a deprecation warning' do - expect_deprecation_with_call_site(__FILE__, line, /failure_message_for_should/) - matcher - end - end - - describe "failure_message_for_should_not" do - let(:matcher) do - new_matcher(:foo) do - match { true } - failure_message_for_should_not { "failed" } - end - end - line = __LINE__ - 3 - - it 'defines the failure message for a negative expectation' do - expect { - expect(nil).not_to matcher - }.to fail_with("failed") - end - - it 'prints a deprecation warning' do - expect_deprecation_with_call_site(__FILE__, line, /failure_message_for_should_not/) - matcher - end - end - - describe "match_for_should" do - let(:matcher) do - new_matcher(:foo) do - match_for_should { |arg| arg } - end - end - line = __LINE__ - 3 - - it 'defines the positive expectation match logic' do - expect(true).to matcher - expect { expect(false).to matcher }.to fail_with(/foo/) - end - - it 'prints a deprecation warning' do - expect_deprecation_with_call_site(__FILE__, line, /match_for_should/) - matcher - end - end - - describe "match_for_should_not" do - let(:matcher) do - new_matcher(:foo) do - match_for_should_not { |arg| !arg } - end - end - line = __LINE__ - 3 - - it 'defines the positive expectation match logic' do - expect(false).not_to matcher - expect { expect(true).not_to matcher }.to fail_with(/foo/) - end - - it 'prints a deprecation warning' do - expect_deprecation_with_call_site(__FILE__, line, /match_for_should_not/) - matcher - end - end - end - context "with an included module" do let(:matcher) do new_matcher(:be_a_greeting) do diff --git a/spec/rspec/matchers/legacy_spec.rb b/spec/rspec/matchers/legacy_spec.rb deleted file mode 100644 index 6283a58ee..000000000 --- a/spec/rspec/matchers/legacy_spec.rb +++ /dev/null @@ -1,98 +0,0 @@ -module RSpec - module Matchers - RSpec.describe "Legacy matchers" do - shared_examples "a matcher written against a legacy protocol" do |matcher_class| - matcher = matcher_class.new - before { allow_deprecation } - - backwards_compat_matcher = Class.new(matcher_class) do - def failure_message; "failure when positive"; end - def failure_message_when_negated; "failure when negative"; end - end.new - - it 'is still considered to be a matcher' do - expect(Matchers.is_a_matcher?(matcher)).to be true - end - - context 'when matched positively' do - it 'returns the positive expectation failure message' do - expect { - expect(false).to matcher - }.to fail_with("failure when positive") - end - - it 'warns about the deprecated protocol' do - expect_warn_deprecation(/legacy\s+RSpec\s+matcher.+#{__FILE__}:#{__LINE__ + 1}/m) - expect(true).to matcher - end - - it 'does not warn when it also defines the current methods (i.e. to be compatible on multiple RSpec versions)' do - expect_no_deprecations - - expect { - expect(false).to backwards_compat_matcher - }.to fail_with("failure when positive") - end - end - - context 'when matched negatively' do - it 'returns the negative expectation failure message' do - expect { - expect(true).not_to matcher - }.to fail_with("failure when negative") - end - - it 'warns about the deprecated protocol' do - expect_warn_deprecation(/legacy\s+RSpec\s+matcher.+#{__FILE__}:#{__LINE__ + 1}/m) - expect(false).not_to matcher - end - - it 'does not warn when it also defines the current methods (i.e. to be compatible on multiple RSpec versions)' do - expect_no_deprecations - - expect { - expect(true).not_to backwards_compat_matcher - }.to fail_with("failure when negative") - end - - def pending_on_rbx - return unless defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' - pending "intermittently fails on RBX due to https://github.com/rubinius/rubinius/issues/2845" - end - - it 'calls `does_not_match?` if it is defined on the matcher' do - pending_on_rbx - - called = false - with_does_not_match = Class.new(matcher_class) do - define_method(:does_not_match?) { |actual| called = true; !actual } - end.new - - expect(false).not_to with_does_not_match - expect(called).to be true - end - end - end - - context "written using the RSpec 2.x `failure_message_for_should` and `failure_message_for_should_not` protocol" do - matcher_class = Class.new do - def matches?(actual); actual; end - def failure_message_for_should; "failure when positive"; end - def failure_message_for_should_not; "failure when negative"; end - end - - it_behaves_like "a matcher written against a legacy protocol", matcher_class - end - - context "written using the older `failure_message` and `negative_failure_message` protocol" do - matcher_class = Class.new do - def matches?(actual); actual; end - def failure_message; "failure when positive"; end - def negative_failure_message; "failure when negative"; end - end - - it_behaves_like "a matcher written against a legacy protocol", matcher_class - end - end - end -end