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

Commit ff04d47

Browse files
authored
Merge pull request #1476 from rspec/error-on-improperly-composing-matchers
Prevent mismatched composed use of value and block matchers
2 parents 2b7b4fd + 7f9bfa4 commit ff04d47

File tree

3 files changed

+16
-5
lines changed

3 files changed

+16
-5
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Bug Fixes:
66
* When using null object doubles, prevent typos triggering dynamic matchers.
77
(Eric Mueller, #1455)
88
* Use `RSpec.warning` for an expectation warning rather than `Kernel.warn`. (Jon Rowe, #1472)
9+
* Prevent mismatched use of block and value matchers in compound expectations. (Phil Pirozhkov, #1476)
910

1011
Enhancements:
1112

lib/rspec/matchers/built_in/compound.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,11 @@ def initialize_copy(other)
7777
def match(_expected, actual)
7878
evaluator_klass = if supports_block_expectations? && Proc === actual
7979
NestedEvaluator
80-
else
80+
elsif supports_value_expectations?
8181
SequentialEvaluator
82+
else
83+
# Can't raise an ArgumentError in this context, as it's rescued
84+
raise "Block and value matchers can't be combined in a compound expectation (#{matcher_1.description}, #{matcher_2.description})"
8285
end
8386

8487
@evaluator = evaluator_klass.new(actual, matcher_1, matcher_2)

spec/rspec/matchers/built_in/compound_spec.rb

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,17 @@ def expect_block
261261
end
262262

263263
describe "expect(...).to custom_matcher.and(other_matcher)" do
264-
it "treats a matcher that doesn't support value expectations correctly" do
265-
expect {
266-
expect([1, 2]).to include(1).and raise_error(/test/)
267-
}.to fail_with(/but was not given a block/)
264+
if RUBY_VERSION.to_f > 1.8 # The example can be adjusted to be compatible with Ruby 1.8, but it is then not indicative of the problem
265+
binding.eval(<<-CODE, __FILE__, __LINE__)
266+
it "does not allow composing incompatible matchers" do
267+
arr = []
268+
expect {
269+
expect { arr << :foo }
270+
.to change { arr }.to be_one
271+
.and change { arr }.to include(:foo) # There is a barely noticeable difference: the `.and` runs on the wrong matcher, `be_one` instead of `change`
272+
}.to raise_error("Block and value matchers can't be combined in a compound expectation (be one, change result to include :foo)")
273+
end
274+
CODE
268275
end
269276

270277
it "treats a matcher that does support value expectations correctly" do

0 commit comments

Comments
 (0)