You can use RSpec::Matchers.define_negated_matcher
to define a negated version of an existing matcher. This is particularly useful in composed matcher expressions or to create more expressive and meaningful matchers.
You should only negate "atomic" matchers with an unambiguous inversion. For example, have_radio_button(label)
can be negated, whereas have_active_radio_button(label)
should not be. Its inversion could either mean "there is a radio button with that label, but it is not active", or "there is no radio button with that label at all". Prefer using attributes in this case: have_radio_button(label, active: true)
.
Examples
RSpec::Matchers.define_negated_matcher :not_change, :change
describe 'A negated matcher' do
it 'can be used to chain negated changes' do
expect { subject.maybe_change(object) }
.to not_change(object, :attr_1)
.and not_change(contract, :attr_2)
end
end
RSpec::Matchers.define_negated_matcher :an_array_excluding, :include
describe 'A negated matcher' do
it 'can be used in a composed matcher expression' do
expect { list.delete(5) }.to change { list }.to(an_array_excluding(5))
end
end
RSpec::Matchers.define_negated_matcher :exclude, :include
describe 'A negated matcher' do
it 'can be used for creating more expressive and meaningful matchers' do
expect(list.difference([5])).to exclude(5)
end
end
Posted by Julian to makandra dev (2021-12-15 14:16)