Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Prevent should from circumventing target check #2800

Merged
merged 1 commit into from
Jan 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions lib/rspec/core/memoized_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions spec/rspec/core/memoized_helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down