Created
December 2, 2024 14:08
-
-
Save jaydorsey/6d139ee4dd531b8ec1ae93ad32ec1765 to your computer and use it in GitHub Desktop.
RSpec change record matcher
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# This custom matcher is designed to make record changes easy | |
# | |
# Without this matcher you'd typically do one of: | |
# | |
# # I believe these won't always work, depends on object reloading, what is changed, how it's changed, | |
# # the order things got loaded, etc. | |
# expect { update }.to change(foo, :method)... | |
# expect { update }.to change { foo.method }... | |
# expect { update }.to change(foo.reload, :method)... | |
# | |
# This will always work | |
# expect { update }.to change { foo.reload, :method}... | |
# | |
# With this matcher it will automatically reload for you and you can use just it (and chain w/ from/to) | |
# | |
# expect { update }.to change_record(foo, :method) | |
# expect { update }.to change_record(foo, :method).from(nil) | |
# expect { update }.to change_record(foo, :method).from(nil).to(:bar) | |
RSpec::Matchers.define :change_record do |record, attribute| | |
supports_block_expectations | |
match do |block| | |
@before = record.reload.send(attribute) | |
block.call | |
@after = record.reload.send(attribute) | |
@before != @after && (@from.nil? || @before == @from) && (@to.nil? || @after == @to) | |
end | |
chain :from do |value| | |
@from = value | |
end | |
chain :to do |value| | |
@to = value | |
end | |
failure_message do | |
message = "expected #{record.class}##{attribute} to change" | |
message += " from #{@from}" if @from | |
message += " to #{@to}" if @to | |
message += ", but it did not" | |
message | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment