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:
parent
8cf449b4ca
commit
ef80d2be42
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue