thoughtbot--shoulda-matchers/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_...

318 lines
11 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateLengthOfMatcher, type: :model do
context 'an attribute with a non-zero minimum length validation' do
it 'accepts ensuring the correct minimum length' do
expect(validating_length(minimum: 4)).
to validate_length_of(:attr).is_at_least(4)
end
it 'rejects ensuring a lower minimum length with any message' do
expect(validating_length(minimum: 4)).
not_to validate_length_of(:attr).is_at_least(3).with_short_message(/.*/)
end
it 'rejects ensuring a higher minimum length with any message' do
expect(validating_length(minimum: 4)).
not_to validate_length_of(:attr).is_at_least(5).with_short_message(/.*/)
end
it 'does not override the default message with a blank' do
expect(validating_length(minimum: 4)).
to validate_length_of(:attr).is_at_least(4).with_short_message(nil)
end
it_supports(
'ignoring_interference_by_writer',
tests: {
accept_if_qualified_but_changing_value_does_not_interfere: {
changing_values_with: :upcase,
},
reject_if_qualified_but_changing_value_interferes: {
model_name: 'Example',
attribute_name: :attr,
changing_values_with: :add_character,
expected_message: <<-MESSAGE.strip
Example did not properly validate that the length of :attr is at least
4.
After setting :attr to "xxx" -- which was read back as "xxxa" --
the matcher expected the Example to be invalid, but it was valid
instead.
As indicated in the message above, :attr seems to be changing certain
values as they are set, and this could have something to do with why
this test is failing. If you've overridden the writer method for this
attribute, then you may need to change it to make this test pass, or
do something else entirely.
MESSAGE
}
}
) do
def validation_matcher_scenario_args
super.deep_merge(validation_options: { minimum: 4 })
end
def configure_validation_matcher(matcher)
matcher.is_at_least(4)
end
end
end
context 'an attribute with a minimum length validation of 0' do
it 'accepts ensuring the correct minimum length' do
expect(validating_length(minimum: 0)).
to validate_length_of(:attr).is_at_least(0)
end
end
context 'an attribute with a maximum length' do
it 'accepts ensuring the correct maximum length' do
expect(validating_length(maximum: 4)).
to validate_length_of(:attr).is_at_most(4)
end
it 'rejects ensuring a lower maximum length with any message' do
expect(validating_length(maximum: 4)).
not_to validate_length_of(:attr).is_at_most(3).with_long_message(/.*/)
end
it 'rejects ensuring a higher maximum length with any message' do
expect(validating_length(maximum: 4)).
not_to validate_length_of(:attr).is_at_most(5).with_long_message(/.*/)
end
it 'does not override the default message with a blank' do
expect(validating_length(maximum: 4)).
to validate_length_of(:attr).is_at_most(4).with_long_message(nil)
end
it_supports(
'ignoring_interference_by_writer',
tests: {
accept_if_qualified_but_changing_value_does_not_interfere: {
changing_values_with: :upcase,
},
reject_if_qualified_but_changing_value_interferes: {
model_name: 'Example',
attribute_name: :attr,
changing_values_with: :remove_character,
expected_message: <<-MESSAGE.strip
Example did not properly validate that the length of :attr is at most 4.
After setting :attr to "xxxxx" -- which was read back as "xxxx" --
the matcher expected the Example to be invalid, but it was valid
instead.
As indicated in the message above, :attr seems to be changing certain
values as they are set, and this could have something to do with why
this test is failing. If you've overridden the writer method for this
attribute, then you may need to change it to make this test pass, or
do something else entirely.
MESSAGE
}
}
) do
def validation_matcher_scenario_args
super.deep_merge(validation_options: { maximum: 4 })
end
def configure_validation_matcher(matcher)
matcher.is_at_most(4)
end
end
end
context 'an attribute with a required exact length' do
it 'accepts ensuring the correct length' do
expect(validating_length(is: 4)).
to validate_length_of(:attr).is_equal_to(4)
end
it 'rejects ensuring a lower maximum length with any message' do
expect(validating_length(is: 4)).
not_to validate_length_of(:attr).is_equal_to(3).with_message(/.*/)
end
it 'rejects ensuring a higher maximum length with any message' do
expect(validating_length(is: 4)).
not_to validate_length_of(:attr).is_equal_to(5).with_message(/.*/)
end
it 'does not override the default message with a blank' do
expect(validating_length(is: 4)).
to validate_length_of(:attr).is_equal_to(4).with_message(nil)
end
it_supports(
'ignoring_interference_by_writer',
tests: {
accept_if_qualified_but_changing_value_does_not_interfere: {
changing_values_with: :upcase,
},
reject_if_qualified_but_changing_value_interferes: {
model_name: 'Example',
attribute_name: :attr,
changing_values_with: :add_character,
expected_message: <<-MESSAGE.strip
Example did not properly validate that the length of :attr is 4.
After setting :attr to "xxx" -- which was read back as "xxxa" --
the matcher expected the Example to be invalid, but it was valid
instead.
As indicated in the message above, :attr seems to be changing certain
values as they are set, and this could have something to do with why
this test is failing. If you've overridden the writer method for this
attribute, then you may need to change it to make this test pass, or
do something else entirely.
MESSAGE
}
}
) do
def validation_matcher_scenario_args
super.deep_merge(validation_options: { is: 4 })
end
def configure_validation_matcher(matcher)
matcher.is_equal_to(4)
end
end
end
context 'an attribute with a required exact length and another validation' do
it 'accepts ensuring the correct length' do
model = define_model(:example, attr: :string) do
validates_length_of :attr, is: 4
validates_numericality_of :attr
end.new
expect(model).to validate_length_of(:attr).is_equal_to(4)
end
end
context 'an attribute with a custom minimum length validation' do
it 'accepts ensuring the correct minimum length' do
expect(validating_length(minimum: 4, too_short: 'foobar')).
to validate_length_of(:attr).is_at_least(4).with_short_message(/foo/)
end
end
context 'an attribute with a custom maximum length validation' do
it 'accepts ensuring the correct minimum length' do
expect(validating_length(maximum: 4, too_long: 'foobar')).
to validate_length_of(:attr).is_at_most(4).with_long_message(/foo/)
end
end
context 'an attribute with a custom equal validation' do
it 'accepts ensuring the correct exact length' do
expect(validating_length(is: 4, message: 'foobar')).
to validate_length_of(:attr).is_equal_to(4).with_message(/foo/)
end
end
context 'an attribute without a length validation' do
it 'rejects ensuring a minimum length' do
expect(define_model(:example, attr: :string).new).
not_to validate_length_of(:attr).is_at_least(1)
end
end
context 'using translations' do
after { I18n.backend.reload! }
context "a too_long translation containing %{attribute}, %{model}" do
before do
stub_translation(
"activerecord.errors.messages.too_long",
"The %{attribute} of your %{model} is too long (maximum is %{count} characters)")
end
it "does not raise an exception" do
expect {
expect(validating_length(maximum: 4)).
to validate_length_of(:attr).is_at_most(4)
}.to_not raise_exception
end
end
context "a too_short translation containing %{attribute}, %{model}" do
before do
stub_translation(
"activerecord.errors.messages.too_short",
"The %{attribute} of your %{model} is too short (minimum is %{count} characters)")
end
it "does not raise an exception" do
expect {
expect(validating_length(minimum: 4)).to validate_length_of(:attr).is_at_least(4)
}.to_not raise_exception
end
end
context "a wrong_length translation containing %{attribute}, %{model}" do
before do
stub_translation(
"activerecord.errors.messages.wrong_length",
"The %{attribute} of your %{model} is the wrong length (should be %{count} characters)")
end
it "does not raise an exception" do
expect {
expect(validating_length(is: 4)).
to validate_length_of(:attr).is_equal_to(4)
}.to_not raise_exception
end
end
end
context 'qualified with allow_nil' do
context 'and validating with allow_nil' do
it 'accepts' do
expect(validating_length(minimum: 1, allow_nil: true)).
to validate_length_of(:attr).is_at_least(1).allow_nil
end
end
context 'and not validating with allow_nil' do
it 'rejects' do
assertion = lambda do
expect(validating_length(minimum: 1)).
to validate_length_of(:attr).is_at_least(1).allow_nil
end
message = <<-MESSAGE
Example did not properly validate that the length of :attr is at least
1.
After setting :attr to nil, the matcher expected the Example to be
valid, but it was invalid instead, producing these validation errors:
* attr: ["is too short (minimum is 1 character)"]
MESSAGE
expect(&assertion).to fail_with_message(message)
end
end
end
def define_model_validating_length(options = {})
options = options.dup
attribute_name = options.delete(:attribute_name) { :attr }
define_model(:example, attribute_name => :string) do |model|
model.validates_length_of(attribute_name, options)
end
end
def validating_length(options = {})
define_model_validating_length(options).new
end
alias_method :build_record_validating_length, :validating_length
def validation_matcher_scenario_args
super.deep_merge(
matcher_name: :validate_length_of,
model_creator: :active_model
)
end
end