Refactor absence matcher

This is part of a collection of commits that aim to improve failure
messages across the board, in order to make matchers easier to debug
when something goes wrong.

* Make the description of the matcher more readable.
* Fix or fill in tests involving failure messages and descriptions to
  match recent changes to ValidationMatcher.
This commit is contained in:
Elliot Winkler 2015-12-13 16:47:25 -07:00
parent bffc9c9b73
commit bf5030d34d
2 changed files with 43 additions and 19 deletions

View File

@ -78,20 +78,18 @@ module Shoulda
# @private
class ValidateAbsenceOfMatcher < ValidationMatcher
def with_message(message)
@expected_message = message
self
def initialize(attribute)
super
@expected_message = :present
end
def matches?(subject)
super(subject)
@expected_message ||= :present
disallows_value_of(value, @expected_message)
end
def description
"require #{@attribute} to not be set"
def simple_description
"validate that :#{@attribute} is empty/falsy"
end
private
@ -110,7 +108,7 @@ module Shoulda
when :decimal then BigDecimal.new(1, 0)
when :datetime, :time, :timestamp then Time.now
when :date then Date.new
when :binary then "0"
when :binary then '0'
else 'an arbitrary value'
end
end

View File

@ -37,9 +37,20 @@ describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher, type: :model
end
context 'a model without an absence validation' do
it 'rejects' do
model = define_model(:example, attr: :string).new
expect(model).not_to validate_absence_of(:attr)
it 'rejects with the correct failure message' do
record = define_model(:example, attr: :string).new
message = <<-MESSAGE
Example did not properly validate that :attr is empty/falsy.
After setting :attr to "an arbitrary value", the matcher expected the
Example to be invalid, but it was valid instead.
MESSAGE
assertion = lambda do
expect(record).to validate_absence_of(:attr)
end
expect(&assertion).to fail_with_message(message)
end
end
@ -54,14 +65,18 @@ describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher, type: :model
end
context 'an ActiveModel class without an absence validation' do
it 'rejects' do
expect(active_model_with(:attr)).not_to validate_absence_of(:attr)
end
it 'rejects with the correct failure message' do
message = <<-MESSAGE
Example did not properly validate that :attr is empty/falsy.
After setting :attr to "an arbitrary value", the matcher expected the
Example to be invalid, but it was valid instead.
MESSAGE
it 'provides the correct failure message' do
message = %{Expected errors to include "must be blank" when attr is set to "an arbitrary value",\ngot no errors}
assertion = lambda do
expect(active_model_with(:attr)).to validate_absence_of(:attr)
end
expect { expect(active_model_with(:attr)).to validate_absence_of(:attr) }.to fail_with_message(message)
expect(&assertion).to fail_with_message(message)
end
end
@ -86,9 +101,20 @@ describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher, type: :model
end
context 'a non-absent has_and_belongs_to_many association' do
it 'rejects' do
it 'rejects with the correct failure message' do
model = having_and_belonging_to_many(:children, absence: false)
expect(model).not_to validate_absence_of(:children)
message = <<-MESSAGE
Parent did not properly validate that :children is empty/falsy.
After setting :children to [#<Child id: nil>], the matcher expected
the Parent to be invalid, but it was valid instead.
MESSAGE
assertion = lambda do
expect(model).to validate_absence_of(:children)
end
expect(&assertion).to fail_with_message(message)
end
end