Rewrite the tests for ComparisonMatcher

Why:

* The tests for ComparisonMatcher don't actually test
  ComparisonMatcher -- they test the comparison qualifiers for
  NumericalityMatcher. Not only is this misleading, but it also creates
  a problem as `validate_numericality_of` is no longer available in any
  example group, but only ones that have been specially tagged.

To satisfy the above:

* Ensure that the tests build an instance of ComparisonMatcher and test
  against that.
* Fix style issues with the tests.
* Additionally, add a #description method to ComparisonMatcher while
  we're at it.
This commit is contained in:
Elliot Winkler 2015-09-24 16:49:58 -06:00
parent 8cf449b4ca
commit ef80d2be42
2 changed files with 171 additions and 133 deletions

View File

@ -24,24 +24,31 @@ module Shoulda
@strict = false @strict = false
end end
def description
message = "validate that #{@attribute} is #{comparison_expectation} #{@value}"
if @strict
message << " strictly"
end
message
end
def for(attribute) def for(attribute)
@attribute = attribute @attribute = attribute
self self
end end
def with_message(message)
@message = message
self
end
def matches?(subject) def matches?(subject)
@subject = subject @subject = subject
all_bounds_correct? all_bounds_correct?
end end
def with_message(message)
@message = message
end
def comparison_description
"#{expectation} #{@value}"
end
def failure_message def failure_message
last_failing_submatcher.failure_message last_failing_submatcher.failure_message
end end
@ -50,6 +57,10 @@ module Shoulda
last_failing_submatcher.failure_message_when_negated last_failing_submatcher.failure_message_when_negated
end end
def comparison_description
"#{comparison_expectation} #{@value}"
end
private private
def all_bounds_correct? def all_bounds_correct?
@ -116,7 +127,7 @@ module Shoulda
[-diff, 0, diff] [-diff, 0, diff]
end end
def expectation def comparison_expectation
case @operator case @operator
when :> then "greater than" when :> then "greater than"
when :>= then "greater than or equal to" when :>= then "greater than or equal to"

View File

@ -1,22 +1,19 @@
require 'unit_spec_helper' require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher do describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher do
subject { described_class.new(matcher, 0, :>) } it_behaves_like 'a numerical submatcher' do
subject { build_matcher }
it_behaves_like 'a numerical submatcher' end
shared_examples_for 'strict qualifier' do shared_examples_for 'strict qualifier' do
def validation_qualifier
matcher_qualifier.to_s.gsub(/^is_/, '').to_sym
end
context 'asserting strict validation when validating strictly' do context 'asserting strict validation when validating strictly' do
it 'accepts' do it 'accepts' do
record = instance_with_validations( record = instance_with_validations(
validation_qualifier => 1, validation_qualifier => 1,
strict: true strict: true
) )
expect(record).to matcher.__send__(matcher_qualifier, 1).strict matcher = build_matcher(operator: operator, value: 1).strict
expect(record).to matcher
end end
end end
@ -27,209 +24,231 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
validation_qualifier => 1, validation_qualifier => 1,
strict: true strict: true
) )
expect(record).not_to matcher.__send__(matcher_qualifier, 1) matcher = build_matcher(operator: operator, value: 1)
expect(record).not_to matcher
end end
end end
context 'asserting strict validation when not validating strictly' do context 'asserting strict validation when not validating strictly' do
it 'rejects' do it 'rejects' do
record = instance_with_validations(validation_qualifier => 1) record = instance_with_validations(validation_qualifier => 1)
expect(record).not_to matcher.__send__(matcher_qualifier, 1).strict matcher = build_matcher(operator: operator, value: 1).strict
expect(record).not_to matcher
end end
end end
end end
context 'when initialized without correct numerical matcher' do context 'when initialized without correct numerical matcher' do
it 'raises an argument error' do it 'raises an ArgumentError' do
fake_matcher = matcher numericality_matcher = double
class << fake_matcher expect { described_class.new(numericality_matcher, 0, :>) }.
undef_method :diff_to_compare to raise_error(ArgumentError)
end
expect do
described_class.new(fake_matcher, 0, :>)
end.to raise_error ArgumentError
end end
end end
context 'is_greater_than' do describe 'is_greater_than' do
include_examples 'strict qualifier' do include_examples 'strict qualifier'
def matcher_qualifier
:is_greater_than it do
end record = instance_with_validations(greater_than: 1.5)
matcher = build_matcher(operator: :>, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(greater_than: 2)) record = instance_with_validations(greater_than: 2)
.to matcher.is_greater_than(2) matcher = build_matcher(operator: :>, value: 2)
expect(record).to matcher
end end
it do it do
expect(instance_with_validations(greater_than: 1.5)) record = instance_with_validations(greater_than: 2.5)
.not_to matcher.is_greater_than(2) matcher = build_matcher(operator: :>, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(greater_than: 2.5)) record = instance_without_validations
.not_to matcher.is_greater_than(2) matcher = build_matcher(operator: :>, value: 2)
expect(record).not_to matcher
end end
it do def operator
expect(instance_without_validations).not_to matcher.is_greater_than(2) :>
end
def validation_qualifier
:greater_than
end end
end end
context 'is_greater_than_or_equal_to' do describe 'is_greater_than_or_equal_to' do
include_examples 'strict qualifier' do include_examples 'strict qualifier'
def matcher_qualifier
:is_greater_than_or_equal_to it do
end record = instance_with_validations(greater_than_or_equal_to: 1.5)
matcher = build_matcher(operator: :>=, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(greater_than_or_equal_to: 2)) record = instance_with_validations(greater_than_or_equal_to: 2)
.to matcher.is_greater_than_or_equal_to(2) matcher = build_matcher(operator: :>=, value: 2)
expect(record).to matcher
end end
it do it do
expect(instance_with_validations(greater_than_or_equal_to: 1.5)) record = instance_with_validations(greater_than_or_equal_to: 2.5)
.not_to matcher.is_greater_than_or_equal_to(2) matcher = build_matcher(operator: :>=, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(greater_than_or_equal_to: 2.5)) record = instance_without_validations
.not_to matcher.is_greater_than_or_equal_to(2) matcher = build_matcher(operator: :>=, value: 2)
expect(record).not_to matcher
end end
it do def operator
expect(instance_without_validations) :>=
.not_to matcher.is_greater_than_or_equal_to(2) end
def validation_qualifier
:greater_than_or_equal_to
end end
end end
context 'is_less_than' do describe 'is_less_than' do
include_examples 'strict qualifier' do include_examples 'strict qualifier'
def matcher_qualifier
:is_less_than it do
end record = instance_with_validations(less_than: 1.5)
matcher = build_matcher(operator: :<, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(less_than: 2)) record = instance_with_validations(less_than: 2)
.to matcher.is_less_than(2) matcher = build_matcher(operator: :<, value: 2)
expect(record).to matcher
end end
it do it do
expect(instance_with_validations(less_than: 1.5)) record = instance_with_validations(less_than: 2.5)
.not_to matcher.is_less_than(2) matcher = build_matcher(operator: :<, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(less_than: 2.5)) record = instance_without_validations
.not_to matcher.is_less_than(2) matcher = build_matcher(operator: :<, value: 2)
expect(record).not_to matcher
end end
it do def operator
expect(instance_without_validations) :<
.not_to matcher.is_less_than(2) end
def validation_qualifier
:less_than
end end
end end
context 'is_less_than_or_equal_to' do describe 'is_less_than_or_equal_to' do
include_examples 'strict qualifier' do include_examples 'strict qualifier'
def matcher_qualifier
:is_less_than_or_equal_to it do
end record = instance_with_validations(less_than_or_equal_to: 1.5)
matcher = build_matcher(operator: :<=, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(less_than_or_equal_to: 2)) record = instance_with_validations(less_than_or_equal_to: 2)
.to matcher.is_less_than_or_equal_to(2) matcher = build_matcher(operator: :<=, value: 2)
expect(record).to matcher
end end
it do it do
expect(instance_with_validations(less_than_or_equal_to: 1.5)) record = instance_with_validations(less_than_or_equal_to: 2.5)
.not_to matcher.is_less_than_or_equal_to(2) matcher = build_matcher(operator: :<=, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(less_than_or_equal_to: 2.5)) record = instance_without_validations
.not_to matcher.is_less_than_or_equal_to(2) matcher = build_matcher(operator: :<=, value: 2)
expect(record).not_to matcher
end end
it do def operator
expect(instance_without_validations) :<=
.not_to matcher.is_less_than_or_equal_to(2) end
def validation_qualifier
:less_than_or_equal_to
end end
end end
context 'is_equal_to' do describe 'is_equal_to' do
include_examples 'strict qualifier' do include_examples 'strict qualifier'
def matcher_qualifier
:is_equal_to it do
end record = instance_with_validations(equal_to: 1.5)
matcher = build_matcher(operator: :==, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(equal_to: 0)) record = instance_with_validations(equal_to: 2)
.to matcher.is_equal_to(0) matcher = build_matcher(operator: :==, value: 2)
expect(record).to matcher
end end
it do it do
expect(instance_with_validations(equal_to: -0.5)) record = instance_with_validations(equal_to: 2.5)
.not_to matcher.is_equal_to(0) matcher = build_matcher(operator: :==, value: 2)
expect(record).not_to matcher
end end
it do it do
expect(instance_with_validations(equal_to: 0.5)) record = instance_without_validations
.not_to matcher.is_equal_to(0) matcher = build_matcher(operator: :==, value: 2)
expect(record).not_to matcher
end end
it do def operator
expect(instance_without_validations) :==
.not_to matcher.is_equal_to(0) end
def validation_qualifier
:equal_to
end end
end end
context 'with_message' do describe 'with_message' do
it 'verifies the message for the validation' do it 'verifies the message for the validation' do
instance = instance_with_validations(equal_to: 0, message: 'Must be zero') instance = instance_with_validations(equal_to: 0, message: 'Must be zero')
expect(instance).to matcher.is_equal_to(0).with_message('Must be zero') matcher = build_matcher.with_message('Must be zero')
end expect(instance).to matcher
end
context 'qualified with on and validating with on' do
it 'accepts' do
expect(instance_with_validations(on: :customizable)).
to matcher.on(:customizable)
end
end
context 'qualified with on but not validating with on' do
it 'accepts since the validation never considers a context' do
expect(instance_with_validations).to matcher.on(:customizable)
end
end
context 'not qualified with on but validating with on' do
it 'rejects since the validation never runs' do
expect(instance_with_validations(on: :customizable)).
not_to matcher
end end
end end
describe '#comparison_description' do describe '#comparison_description' do
[{ operator: :>, value: 0, expectation: 'greater than 0' }, tests = [
{ operator: :>=, value: -1.0, expectation: 'greater than or equal to -1.0' }, { operator: :>, value: 0, expectation: 'greater than 0' },
{ operator: :==, value: 2.2, expectation: 'equal to 2.2' }, { operator: :>=, value: -1.0, expectation: 'greater than or equal to -1.0' },
{ operator: :<, value: -3, expectation: 'less than -3' }, { operator: :==, value: 2.2, expectation: 'equal to 2.2' },
{ operator: :<=, value: 4, expectation: 'less than or equal to 4' }, { operator: :<, value: -3, expectation: 'less than -3' },
].each do |h| { operator: :<=, value: 4, expectation: 'less than or equal to 4' },
context "with :#{h[:operator]} as operator and #{h[:value]} as value" do ]
subject do
described_class.new(matcher, h[:value], h[:operator]) tests.each do |test|
.comparison_description context "with :#{test[:operator]} as operator and #{test[:value]} as value" do
it do
matcher = build_matcher(operator: test[:operator], value: test[:value])
expect(matcher.comparison_description).to eq test[:expectation]
end end
it { should eq h[:expectation] }
end end
end end
end end
@ -245,17 +264,25 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
model_with_validations(options).new(attribute_name => '1') model_with_validations(options).new(attribute_name => '1')
end end
def instance_without_validations def model_without_validations
define_model :example, attribute_name => :string do |model| define_model :example, attribute_name => :string do |model|
model.attr_accessible(attribute_name) model.attr_accessible(attribute_name)
end.new end
end
def instance_without_validations
model_without_validations.new
end end
def attribute_name def attribute_name
:attr :attr
end end
def matcher def build_matcher(operator: :==, value: 0)
validate_numericality_of(:attr) described_class.new(numericality_matcher, value, operator).for(attribute_name)
end
def numericality_matcher
double(diff_to_compare: 1)
end end
end end