Hi Nick, I came up with a hacky solution that might do the trick for your use case.
``` module MyMatchers class Pass include RSpec::Matchers::Composable def initialize(expected_return_value) @expected_return_value = expected_return_value end def description "pass with #{@expected_return_value} return value" end def matches?(block) if block.source_location.first.end_with?('compound.rb') fail "You should use this matcher at the top of the chain, immediately following the `expect { ... }`" end @actual_return_value = block.call values_match?(@expected_return_value, @actual_return_value) end def failure_message(*args) "Expected: #{@expected_return_value}, got: #{@actual_return_value}" end def supports_block_expectations? true end end def pass(expected_return_value) Pass.new(expected_return_value) end end RSpec.configure do |config| config.include MyMatchers end $foo = 0 ``` Now, when you run: ``` RSpec.describe "a custom block matcher" do specify do expect { $foo = 2 } .to pass(2) .and change { $foo }.by(2) end end ``` it will be green. However, if `pass` is not the first matcher, it will blow up: ``` RSpec.describe "a custom block matcher" do specify do expect { $foo = 2 } .to change { $foo }.by(2) .and pass(2) end end ``` with: ``` a custom block matcher is expected to change `$foo` by 2 and pass with 2 return value (FAILED - 1) Failures: 1) a custom block matcher is expected to change `$foo` by 2 and pass with 2 return value Failure/Error: fail "You should use this matcher at the top of the chain, immediately following the `expect { ... }`" RuntimeError: You should use this matcher at the top of the chain, immediately following the `expect { ... }` ``` I hope that works. There's room to make this generic by: - wrapping the initial expect block into a proc that would save the return value of a wrapped initial block into a variable - pass the return value to other matchers along with the block around in NestedEvaluator if matcher's `matches?` accepts two arguments This would allow for using `pass` in any position in the chain. I'm still not entirely convinced it will be widely used, since the `expect { expect(action!).to eq(return_value) }.to check_side_effect }` trick works quite fine for non-DSL cases. - Phil -- You received this message because you are subscribed to the Google Groups "rspec" group. To unsubscribe from this group and stop receiving emails from it, send an email to rspec+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/CAAk5Ok9HOT%3Dp3MNtSV5nmhTsQnLpw7hHq%2Bbu2JEi84rwsF7Fsw%40mail.gmail.com.