diff --git a/lib/rspec/core/memoized_helpers.rb b/lib/rspec/core/memoized_helpers.rb index 771c12d716..87ee8e9359 100644 --- a/lib/rspec/core/memoized_helpers.rb +++ b/lib/rspec/core/memoized_helpers.rb @@ -78,6 +78,7 @@ def subject # @note If you are using RSpec's newer expect-based syntax you may # want to use `is_expected.to` instead of `should`. def should(matcher=nil, message=nil) + enforce_value_expectation(matcher, 'should') RSpec::Expectations::PositiveExpectationHandler.handle_matcher(subject, matcher, message) end @@ -97,6 +98,7 @@ def should(matcher=nil, message=nil) # @note If you are using RSpec's newer expect-based syntax you may # want to use `is_expected.to_not` instead of `should_not`. def should_not(matcher=nil, message=nil) + enforce_value_expectation(matcher, 'should_not') RSpec::Expectations::NegativeExpectationHandler.handle_matcher(subject, matcher, message) end @@ -144,6 +146,26 @@ def __init_memoized end end + # @private + def enforce_value_expectation(matcher, method_name) + return if matcher_supports_value_expectations?(matcher) + + RSpec.deprecate( + "#{method_name} #{RSpec::Support::ObjectFormatter.format(matcher)}", + :message => + "The implicit block expectation syntax is deprecated, you should pass " \ + "a block to `expect` to use the provided block expectation matcher " \ + "(#{RSpec::Support::ObjectFormatter.format(matcher)}), " \ + "or the matcher must implement `supports_value_expectations?`." + ) + end + + def matcher_supports_value_expectations?(matcher) + matcher.supports_value_expectations? + rescue + true + end + # @private class ThreadsafeMemoized def initialize diff --git a/spec/rspec/core/memoized_helpers_spec.rb b/spec/rspec/core/memoized_helpers_spec.rb index dc2da63f82..4987549853 100644 --- a/spec/rspec/core/memoized_helpers_spec.rb +++ b/spec/rspec/core/memoized_helpers_spec.rb @@ -630,6 +630,28 @@ def hello_message; "Hello from module"; end end end + RSpec.describe 'implicit block expectation syntax' do + matcher :block_matcher do + match { |actual| true } + supports_block_expectations + def supports_value_expectations? + false + end + end + + subject { 'value or a Proc' } + + it '`should` prints a deprecation warning when given a value' do + expect_warn_deprecation(/The implicit block expectation syntax is deprecated, you should pass/) + expect { should block_matcher }.not_to raise_error + end + + it '`should_not` prints a deprecation warning when given a value' do + expect_warn_deprecation(/The implicit block expectation syntax is deprecated, you should pass/) + expect { should_not block_matcher }.to raise_error(Exception) + end + end + RSpec.describe 'Module#define_method' do it 'retains its normal private visibility on Ruby versions where it is normally private', :if => RUBY_VERSION < '2.5' do a_module = Module.new