1
0
Fork 0
mirror of https://github.com/thoughtbot/shoulda-matchers.git synced 2022-11-09 12:01:38 -05:00

Rewrite tests for ensure_inclusion_of

ensure_inclusion_of is pretty complex. Not only does it support two ways
of specifying valid values (in_array, in_range), but it also supports
multiple column types (string, integer, float, decimal, boolean).

When it comes to handling numbers and strings, ensure_inclusion_of has
very similar logic, and we can test these cases similarly.

We also do not have tests for handling regular Ruby attributes as
opposed to database columns (validates_inclusion_of works with both).
Those tests will be added in a future commit, this commit lays the
groundwork for that.
This commit is contained in:
Elliot Winkler 2014-04-17 19:40:39 -06:00
parent 8f933f8064
commit c7b1505990

View file

@ -1,320 +1,609 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::EnsureInclusionOfMatcher do
context 'with no validations' do
it 'rejects an array which does not have a validator defined' do
expect(define_model(:example, attr: :string).new).
not_to ensure_inclusion_of(:attr).in_array(%w(Yes No))
end
end
shared_context 'for a generic attribute' do
def self.testing_values_of_option(option_name, &block)
[nil, true, false].each do |option_value|
context_name = "+ #{option_name}"
option_args = []
matches_or_not = ['matches', 'does not match']
to_or_not_to = [:to, :not_to]
context 'with an integer column' do
it 'can verify a zero in the array' do
model = define_model(:example, attr: :integer) do
validates_inclusion_of :attr, in: [0, 1, 2]
end.new
unless option_value == nil
context_name << "(#{option_value})"
option_args = [option_value]
end
expect(model).to ensure_inclusion_of(:attr).in_array([0,1,2])
end
end
if option_value == false
matches_or_not.reverse!
to_or_not_to.reverse!
end
context 'with an decimal column' do
it 'can verify decimal values' do
model = define_model(:example, attr: :decimal) do
validates_inclusion_of :attr, in: [0.0, 0.1]
end.new
expect(model).to ensure_inclusion_of(:attr).in_array([0.0, 0.1])
end
end
context 'with true/false values' do
it 'can verify outside values to ensure the negative case' do
expect(define_model(:example, attr: :string).new).
not_to ensure_inclusion_of(:attr).in_array([true, false])
end
end
context 'where we cannot determine a value outside the array' do
it 'raises a custom exception' do
model = define_model(:example, attr: :string).new
arbitrary_string = described_class::ARBITRARY_OUTSIDE_STRING
expect { expect(model).to ensure_inclusion_of(:attr).in_array([arbitrary_string]) }.to raise_error Shoulda::Matchers::ActiveModel::CouldNotDetermineValueOutsideOfArray
end
end
context 'an attribute which must be included in a range' do
it 'accepts ensuring the correct range' do
expect(validating_inclusion(in: 2..5)).
to ensure_inclusion_of(:attr).in_range(2..5)
end
end
it 'rejects ensuring a lower minimum value' do
expect(validating_inclusion(in: 2..5)).
not_to ensure_inclusion_of(:attr).in_range(1..5)
end
context 'against an integer attribute' do
it_behaves_like 'it supports in_array',
possible_values: (1..5).to_a,
zero: 0,
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_FIXNUM
it 'rejects ensuring a higher minimum value' do
expect(validating_inclusion(in: 2..5)).
not_to ensure_inclusion_of(:attr).in_range(3..5)
end
it_behaves_like 'it supports in_range',
possible_values: 1..5,
zero: 0
it 'rejects ensuring a lower maximum value' do
expect(validating_inclusion(in: 2..5)).
not_to ensure_inclusion_of(:attr).in_range(2..4)
end
it 'rejects ensuring a higher maximum value' do
expect(validating_inclusion(in: 2..5)).
not_to ensure_inclusion_of(:attr).in_range(2..6)
end
it 'does not override the default message with a blank' do
expect(validating_inclusion(in: 2..5)).
to ensure_inclusion_of(:attr).in_range(2..5).with_message(nil)
end
end
context 'an attribute which must be included in a range with excluded end' do
it 'accepts ensuring the correct range' do
expect(validating_inclusion(in: 2...5)).
to ensure_inclusion_of(:attr).in_range(2...5)
end
it 'rejects ensuring a lower maximum value' do
expect(validating_inclusion(in: 2...5)).
not_to ensure_inclusion_of(:attr).in_range(2...4)
end
end
context 'an attribute with a custom ranged value validation' do
it 'accepts ensuring the correct range' do
expect(validating_inclusion(in: 2..4, message: 'not good')).
to ensure_inclusion_of(:attr).in_range(2..4).with_message(/not good/)
end
end
context 'an attribute with custom range validations' do
it 'accepts ensuring the correct range and messages' do
model = custom_validation do
if attr < 2
errors.add(:attr, 'too low')
elsif attr > 5
errors.add(:attr, 'too high')
context 'when attribute validates a range of values via custom validation' do
it 'matches ensuring the correct range and messages' do
expect_to_match_ensuring_range_and_messages(2..5, 2, 5)
expect_to_match_ensuring_range_and_messages(2...5, 2, 4)
end
end
expect(model).to ensure_inclusion_of(:attr).in_range(2..5).
with_low_message(/low/).with_high_message(/high/)
model = custom_validation do
if attr < 2
errors.add(:attr, 'too low')
elsif attr > 4
errors.add(:attr, 'too high')
end
def build_object(options = {}, &block)
build_object_with_generic_attribute(
options.merge(column_type: :integer),
&block
)
end
expect(model).to ensure_inclusion_of(:attr).in_range(2...5).
with_low_message(/low/).with_high_message(/high/)
end
end
context 'an attribute which must be included in an array' do
it 'accepts with correct array' do
expect(validating_inclusion(in: %w(one two))).
to ensure_inclusion_of(:attr).in_array(%w(one two))
end
it 'rejects when only part of array matches' do
expect(validating_inclusion(in: %w(one two))).
not_to ensure_inclusion_of(:attr).in_array(%w(one wrong_value))
end
it 'rejects when array does not match at all' do
expect(validating_inclusion(in: %w(one two))).
not_to ensure_inclusion_of(:attr).in_array(%w(cat dog))
end
it 'has correct description' do
expect(ensure_inclusion_of(:attr).in_array([true, "dog"]).description).
to eq 'ensure inclusion of attr in [true, "dog"]'
end
it 'rejects allow_blank' do
expect(validating_inclusion(in: %w(one two))).
not_to ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank(true)
end
it 'accepts allow_blank(false)' do
expect(validating_inclusion(in: %w(one two))).
to ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank(false)
end
it 'rejects allow_nil' do
expect(validating_inclusion(in: %w(one two))).
not_to ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil(true)
end
it 'accepts allow_nil(false)' do
expect(validating_inclusion(in: %w(one two))).
to ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil(false)
end
end
context 'with allowed blank and allowed nil' do
it 'accepts allow_blank' do
expect(validating_inclusion(in: %w(one two), allow_blank: true)).
to ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank
end
it 'rejects allow_blank(false)' do
expect(validating_inclusion(in: %w(one two), allow_blank: true)).
not_to ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank(false)
end
it 'accepts allow_nil' do
expect(validating_inclusion(in: %w(one two), allow_nil: true)).
to ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil
end
it 'rejects allow_nil' do
expect(validating_inclusion(in: %w(one two), allow_nil: true)).
not_to ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil(false)
end
end
context 'an attribute allowing some blank values but not others' do
it 'rejects allow_blank' do
expect(validating_inclusion(in: ['one', 'two', ''])).
not_to ensure_inclusion_of(:attr).in_array(['one', 'two', '']).allow_blank(true)
end
end
if active_model_3_2?
context 'a strict attribute which must be included in a range' do
it 'accepts ensuring the correct range' do
expect(validating_inclusion(in: 2..5, strict: true)).
to ensure_inclusion_of(:attr).in_range(2..5).strict
end
it 'rejects ensuring another range' do
expect(validating_inclusion(in: 2..5, strict: true)).
not_to ensure_inclusion_of(:attr).in_range(2..6).strict
def add_outside_value_to(values)
values + [values.last + 1]
end
end
end
context 'against a boolean attribute' do
context 'which is nullable' do
context 'when ensuring inclusion of true' do
it "doesn't raise an error" do
record = validating_inclusion_of_boolean_in(:attr, [true], null: true)
expect(record).to ensure_inclusion_of(:attr).in_array([true])
end
context "against a float attribute" do
it_behaves_like 'it supports in_array',
possible_values: [1.0, 2.0, 3.0, 4.0, 5.0],
zero: 0.0,
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_FIXNUM
it_behaves_like 'it supports in_range',
possible_values: 1.0..5.0,
zero: 0.0
def build_object(options = {}, &block)
build_object_with_generic_attribute(
options.merge(column_type: :float),
&block
)
end
context 'when ensuring inclusion of false' do
it "doesn't raise an error" do
record = validating_inclusion_of_boolean_in(:attr, [false], null: true)
expect(record).to ensure_inclusion_of(:attr).in_array([false])
end
def add_outside_value_to(values)
values + [values.last + 1]
end
end
context "against a decimal attribute" do
it_behaves_like 'it supports in_array',
possible_values: [1.0, 2.0, 3.0, 4.0, 5.0],
zero: 0.0,
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_DECIMAL
it_behaves_like 'it supports in_range',
possible_values: 1.0..5.0,
zero: 0.0
def build_object(options = {}, &block)
build_object_with_generic_attribute(
options.merge(column_type: :decimal),
&block
)
end
context 'when ensuring inclusion of true and false' do
it "doesn't raise an error" do
record = validating_inclusion_of_boolean_in(:attr, [true, false], null: true)
capture(:stderr) do
expect(record).to ensure_inclusion_of(:attr).in_array([true, false])
def add_outside_value_to(values)
values + [values.last + 1]
end
end
context 'against a boolean attribute' do
context 'which is nullable' do
include_context 'against a boolean attribute for true and false'
context 'when ensuring inclusion of nil' do
it 'matches' do
valid_values = [nil]
builder = build_object_allowing(valid_values)
capture(:stderr) do
expect_to_match_in_array(builder, valid_values)
end
end
it 'prints a warning' do
valid_values = [nil]
builder = build_object_allowing(valid_values)
message = 'You are using `ensure_inclusion_of` to assert that a boolean column allows nil'
stderr = capture(:stderr) do
expect_to_match_in_array(builder, valid_values)
end
expect(stderr.gsub(/\n+/, ' ')).to include(message)
end
end
it 'prints a warning' do
record = validating_inclusion_of_boolean_in(:attr, [true, false], null: true)
stderr = capture(:stderr) do
expect(record).to ensure_inclusion_of(:attr).in_array([true, false])
end
expect(stderr.gsub(/\n+/, ' ')).
to include('You are using `ensure_inclusion_of` to assert that a boolean column allows boolean values and disallows non-boolean ones')
def build_object(options = {}, &block)
super(options.merge(column_options: { null: true }))
end
end
context 'when ensuring inclusion of nil' do
it "doesn't raise an error" do
record = validating_inclusion_of_boolean_in(:attr, [nil], null: true)
capture(:stderr) do
expect(record).to ensure_inclusion_of(:attr).in_array([nil])
context 'which is non-nullable' do
include_context 'against a boolean attribute for true and false'
context 'when ensuring inclusion of nil' do
it 'raises a specific error' do
valid_values = [nil]
builder = build_object_allowing(valid_values)
error_class = Shoulda::Matchers::ActiveModel::NonNullableBooleanError
expect {
expect_to_match_in_array(builder, valid_values)
}.to raise_error(error_class)
end
end
it 'prints a warning' do
record = validating_inclusion_of_boolean_in(:attr, [nil], null: true)
stderr = capture(:stderr) do
expect(record).to ensure_inclusion_of(:attr).in_array([nil])
end
expect(stderr.gsub(/\n+/, ' ')).
to include('You are using `ensure_inclusion_of` to assert that a boolean column allows nil')
def build_object(options = {}, &block)
super(options.merge(column_options: { null: false }))
end
end
def build_object(options = {}, &block)
build_object_with_generic_attribute(
options.merge(column_type: :boolean),
&block
)
end
end
context 'which is non-nullable' do
context 'when ensuring inclusion of true' do
it "doesn't raise an error" do
record = validating_inclusion_of_boolean_in(:attr, [true], null: false)
expect(record).to ensure_inclusion_of(:attr).in_array([true])
context 'against a string attribute' do
it_behaves_like 'it supports in_array',
possible_values: %w(foo bar baz),
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_STRING
def build_object(options = {}, &block)
build_object_with_generic_attribute(
options.merge(column_type: :string),
&block
)
end
def add_outside_value_to(values)
values + %w(qux)
end
end
end
shared_examples_for 'it supports allow_nil' do |args|
valid_values = args.fetch(:valid_values)
testing_values_of_option 'allow_nil' do |option_args, matches_or_not, to_or_not_to|
it "#{matches_or_not[0]} when the validation specifies allow_nil" do
builder = build_object_allowing(valid_values, allow_nil: true)
__send__("expect_#{to_or_not_to[0]}_match_on_values", builder, valid_values) do |matcher|
matcher.allow_nil(*option_args)
end
end
context 'when ensuring inclusion of false' do
it "doesn't raise an error" do
record = validating_inclusion_of_boolean_in(:attr, [false], null: false)
expect(record).to ensure_inclusion_of(:attr).in_array([false])
end
end
it "#{matches_or_not[1]} when the validation does not specify allow_nil" do
builder = build_object_allowing(valid_values)
context 'when ensuring inclusion of true and false' do
it "doesn't raise an error" do
record = validating_inclusion_of_boolean_in(:attr, [true, false], null: false)
capture(:stderr) do
expect(record).to ensure_inclusion_of(:attr).in_array([true, false])
end
end
it 'prints a warning' do
record = validating_inclusion_of_boolean_in(:attr, [true, false], null: false)
stderr = capture(:stderr) do
expect(record).to ensure_inclusion_of(:attr).in_array([true, false])
end
expect(stderr.gsub(/\n+/, ' ')).
to include('You are using `ensure_inclusion_of` to assert that a boolean column allows boolean values and disallows non-boolean ones')
end
end
context 'when ensuring inclusion of nil' do
it 'raises a specific error' do
record = validating_inclusion_of_boolean_in(:attr, [nil], null: false)
error_class = Shoulda::Matchers::ActiveModel::NonNullableBooleanError
expect {
expect(record).to ensure_inclusion_of(:attr).in_array([nil])
}.to raise_error(error_class)
__send__("expect_#{to_or_not_to[1]}_match_on_values", builder, valid_values) do |matcher|
matcher.allow_nil(*option_args)
end
end
end
end
def validating_inclusion(options)
define_model(:example, attr: :string) do
validates_inclusion_of :attr, options
end.new
shared_examples_for 'it supports allow_blank' do |args|
valid_values = args.fetch(:valid_values)
testing_values_of_option 'allow_blank' do |option_args, matches_or_not, to_or_not_to|
it "#{matches_or_not[0]} when the validation specifies allow_blank" do
builder = build_object_allowing(valid_values, allow_blank: true)
__send__("expect_#{to_or_not_to[0]}_match_on_values", builder, valid_values) do |matcher|
matcher.allow_blank(*option_args)
end
end
it "#{matches_or_not[1]} when the validation does not specify allow_blank" do
builder = build_object_allowing(valid_values)
__send__("expect_#{to_or_not_to[1]}_match_on_values", builder, valid_values) do |matcher|
matcher.allow_blank(*option_args)
end
end
end
end
def validating_inclusion_of_boolean_in(attribute, values, options = {})
null = options.fetch(:null, true)
column_options = { type: :boolean, options: { null: null } }
define_model(:example, attribute => column_options) do
validates_inclusion_of attribute, in: values
end.new
shared_examples_for 'it supports with_message' do |args|
valid_values = args.fetch(:valid_values)
context 'given a string' do
it 'matches when validation uses given message' do
builder = build_object_allowing(valid_values, message: 'a message')
expect_to_match_on_values(builder, valid_values) do |matcher|
matcher.with_message('a message')
end
end
it 'does not match when validation uses the default message instead of given message' do
pending 'does not work'
builder = build_object_allowing(valid_values)
expect_not_to_match_on_values(builder, valid_values) do |matcher|
matcher.with_message('a message')
end
end
it 'does not match when validation uses a message but it is not same as given' do
pending 'does not work'
builder = build_object_allowing(valid_values, message: 'a different message')
expect_not_to_match_on_values(builder, valid_values) do |matcher|
matcher.with_message('a message')
end
end
end
context 'given a regex' do
it 'matches when validation uses a message that matches the regex' do
builder = build_object_allowing(valid_values, message: 'this is a message')
expect_to_match_on_values(builder, valid_values) do |matcher|
matcher.with_message(/a message/)
end
end
it 'does not match when validation uses the default message instead of given message' do
pending 'does not work'
builder = build_object_allowing(valid_values)
expect_not_to_match_on_values(builder, valid_values) do |matcher|
matcher.with_message(/a message/)
end
end
it 'does not match when validation uses a message but it does not match regex' do
pending 'does not work'
builder = build_object_allowing(valid_values, message: 'a different message')
expect_not_to_match_on_values(builder, valid_values) do |matcher|
matcher.with_message(/a message/)
end
end
end
context 'given nil' do
it 'is as if with_message had never been called' do
builder = build_object_allowing(valid_values)
expect_to_match_on_values(builder, valid_values) do |matcher|
matcher.with_message(nil)
end
end
end
end
shared_examples_for 'it supports in_array' do |args|
possible_values = args.fetch(:possible_values)
zero = args[:zero]
reserved_outside_value = args.fetch(:reserved_outside_value)
it 'does not match a record with no validations' do
builder = build_object
expect_not_to_match_on_values(builder, possible_values)
end
it 'matches given the same array of valid values' do
builder = build_object_allowing(possible_values)
expect_to_match_on_values(builder, possible_values)
end
it 'matches given a subset of the valid values' do
builder = build_object_allowing(possible_values)
expect_to_match_on_values(builder, possible_values[1..-1])
end
if zero
it 'matches when one of the given values is a 0' do
valid_values = possible_values + [zero]
builder = build_object_allowing(valid_values)
expect_to_match_on_values(builder, valid_values)
end
end
it 'does not match when one of the given values is invalid' do
builder = build_object_allowing(possible_values)
expect_not_to_match_on_values(builder, add_outside_value_to(possible_values))
end
it 'raises an error when valid and given value is our test outside value' do
error_class = Shoulda::Matchers::ActiveModel::CouldNotDetermineValueOutsideOfArray
builder = build_object_allowing([reserved_outside_value])
expect { expect_to_match_on_values(builder, [reserved_outside_value]) }.
to raise_error(error_class)
end
it_behaves_like 'it supports allow_nil', valid_values: possible_values
it_behaves_like 'it supports allow_blank', valid_values: possible_values
it_behaves_like 'it supports with_message', valid_values: possible_values
if active_model_3_2?
context '+ strict' do
context 'when the validation specifies strict' do
it 'matches when the given values match the valid values' do
builder = build_object_allowing(possible_values, strict: true)
expect_to_match_on_values(builder, possible_values) do |matcher|
matcher.strict
end
end
it 'does not match when the given values do not match the valid values' do
builder = build_object_allowing(possible_values, strict: true)
values = add_outside_value_to(possible_values)
expect_not_to_match_on_values(builder, values) do |matcher|
matcher.strict
end
end
end
context 'when the validation does not specify strict' do
it 'does not match' do
builder = build_object_allowing(possible_values)
expect_not_to_match_on_values(builder, possible_values) do |matcher|
matcher.strict
end
end
end
end
end
def expect_to_match_on_values(builder, values, &block)
expect_to_match_in_array(builder, values, &block)
end
def expect_not_to_match_on_values(builder, values, &block)
expect_not_to_match_in_array(builder, values, &block)
end
end
shared_examples_for 'it supports in_range' do |args|
possible_values = args[:possible_values]
it 'does not match a record with no validations' do
builder = build_object
expect_not_to_match_on_values(builder, possible_values)
end
it 'matches given a range that exactly matches the valid range' do
builder = build_object_allowing(possible_values)
expect_to_match_on_values(builder, possible_values)
end
it 'does not match given a range whose start value falls outside valid range' do
builder = build_object_allowing(possible_values)
expect_not_to_match_on_values(builder,
Range.new(possible_values.first - 1, possible_values.last)
)
end
it 'does not match given a range whose start value falls inside valid range' do
builder = build_object_allowing(possible_values)
expect_not_to_match_on_values(builder,
Range.new(possible_values.first + 1, possible_values.last)
)
end
it 'does not match given a range whose end value falls inside valid range' do
builder = build_object_allowing(possible_values)
expect_not_to_match_on_values(builder,
Range.new(possible_values.first, possible_values.last - 1)
)
end
it 'does not match given a range whose end value falls outside valid range' do
builder = build_object_allowing(possible_values)
expect_not_to_match_on_values(builder,
Range.new(possible_values.first, possible_values.last + 1)
)
end
it_behaves_like 'it supports allow_nil', valid_values: possible_values
it_behaves_like 'it supports allow_blank', valid_values: possible_values
it_behaves_like 'it supports with_message', valid_values: possible_values
if active_model_3_2?
context '+ strict' do
context 'when the validation specifies strict' do
it 'matches when the given range matches the range in the validation' do
builder = build_object_allowing(possible_values, strict: true)
expect_to_match_on_values(builder, possible_values) do |matcher|
matcher.strict
end
end
it 'matches when the given range does not match the range in the validation' do
builder = build_object_allowing(possible_values, strict: true)
range = Range.new(possible_values.first, possible_values.last + 1)
expect_not_to_match_on_values(builder, range) do |matcher|
matcher.strict
end
end
end
context 'when the validation does not specify strict' do
it 'does not match' do
builder = build_object_allowing(possible_values)
expect_not_to_match_on_values(builder, possible_values) do |matcher|
matcher.strict
end
end
end
end
end
def expect_to_match_on_values(builder, range, &block)
expect_to_match_in_range(builder, range, &block)
end
def expect_not_to_match_on_values(builder, range, &block)
expect_not_to_match_in_range(builder, range, &block)
end
end
shared_context 'against a boolean attribute for true and false' do
context 'when ensuring inclusion of true' do
it 'matches' do
valid_values = [true]
builder = build_object_allowing(valid_values)
expect_to_match_in_array(builder, valid_values)
end
end
context 'when ensuring inclusion of false' do
it 'matches' do
valid_values = [false]
builder = build_object_allowing(valid_values)
expect_to_match_in_array(builder, valid_values)
end
end
context 'when ensuring inclusion of true and false' do
it 'matches' do
valid_values = [true, false]
builder = build_object_allowing(valid_values)
capture(:stderr) do
expect_to_match_in_array(builder, valid_values)
end
end
it 'prints a warning' do
valid_values = [true, false]
builder = build_object_allowing(valid_values)
message = 'You are using `ensure_inclusion_of` to assert that a boolean column allows boolean values and disallows non-boolean ones'
stderr = capture(:stderr) do
expect_to_match_in_array(builder, valid_values)
end
expect(stderr.gsub(/\n+/, ' ')).to include(message)
end
end
end
context 'for a database column' do
include_context 'for a generic attribute'
def build_object_with_generic_attribute(options = {}, &block)
attribute_name = :attr
column_type = options.fetch(:column_type)
column_options = {
type: column_type,
options: options.fetch(:column_options, {})
}
validation_options = options[:validation_options]
custom_validation = options[:custom_validation]
model = define_model :example, attribute_name => column_options do
if validation_options
validates_inclusion_of attribute_name, validation_options
end
if custom_validation
define_method :custom_validation do
instance_exec(attribute_name, &custom_validation)
end
validate :custom_validation
end
end
object = model.new
object_builder_class.new(attribute_name, object, validation_options)
end
end
def object_builder_class
@_object_builder_class ||= Struct.new(:attribute, :object, :validation_options)
end
def build_object_allowing(values, options = {})
build_object(validation_options: options.merge(in: values))
end
def expect_to_match(builder)
matcher = ensure_inclusion_of(builder.attribute)
yield matcher if block_given?
expect(builder.object).to(matcher)
end
def expect_not_to_match(builder)
matcher = ensure_inclusion_of(builder.attribute)
yield matcher if block_given?
expect(builder.object).not_to(matcher)
end
def expect_to_match_in_array(builder, array)
expect_to_match(builder) do |matcher|
matcher.in_array(array)
yield matcher if block_given?
end
end
def expect_not_to_match_in_array(builder, array)
expect_not_to_match(builder) do |matcher|
matcher.in_array(array)
yield matcher if block_given?
end
end
def expect_to_match_in_range(builder, range)
expect_to_match(builder) do |matcher|
matcher.in_range(range)
yield matcher if block_given?
end
end
def expect_not_to_match_in_range(builder, range)
expect_not_to_match(builder) do |matcher|
matcher.in_range(range)
yield matcher if block_given?
end
end
def expect_to_match_ensuring_range_and_messages(range, low_value, high_value)
low_message = 'too low'
high_message = 'too high'
builder = build_object custom_validation: ->(attribute) {
value = __send__(attribute)
if value < low_value
errors.add(attribute, low_message)
elsif value > high_value
errors.add(attribute, high_message)
end
}
expect_to_match(builder) do |matcher|
matcher.
in_range(range).
with_low_message(low_message).
with_high_message(high_message)
end
end
end