Add the qualifier allow_blank to validate_length_of (#1318)

Co-authored-by: Elliot Winkler <elliot.winkler@gmail.com>
This commit is contained in:
Elliot Winkler 2020-07-11 11:33:54 -06:00 committed by GitHub
parent 421a49d0b6
commit a4289e9651
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 24 deletions

View File

@ -311,15 +311,6 @@ EOT
self
end
def allow_blank
@options[:allow_blank] = true
self
end
def expects_to_allow_blank?
@options[:allow_blank]
end
def allow_nil
@options[:allow_nil] = true
self
@ -423,14 +414,14 @@ EOT
allows_all_values_in_array? &&
disallows_all_values_outside_of_array? &&
allows_nil_value? &&
allows_blank_value?
allow_blank_matches?
end
def does_not_match_for_array?
disallows_any_values_in_array? ||
allows_any_value_outside_of_array? ||
disallows_nil_value? ||
disallows_blank_value?
allow_blank_does_not_match?
end
def allows_lower_value
@ -616,16 +607,6 @@ EOT
@options[:allow_nil] && disallows_value_of(nil)
end
def allows_blank_value?
@options[:allow_blank] != true ||
BLANK_VALUES.all? { |value| allows_value_of(value) }
end
def disallows_blank_value?
@options[:allow_blank] &&
BLANK_VALUES.any? { |value| disallows_value_of(value) }
end
def inspected_array
Shoulda::Matchers::Util.inspect_values(@array).to_sentence(
two_words_connector: " or ",

View File

@ -232,13 +232,34 @@ module Shoulda
# it { should validate_length_of(:bio).is_at_least(15).allow_nil }
# end
#
# # Test::Unit
# # Minitest (Shoulda)
# class UserTest < ActiveSupport::TestCase
# should validate_length_of(:bio).is_at_least(15).allow_nil
# end
#
# @return [ValidateLengthOfMatcher]
#
# # ##### allow_blank
#
# Use `allow_blank` to assert that the attribute allows blank.
#
# class User
# include ActiveModel::Model
# attr_accessor :bio
#
# validates_length_of :bio, minimum: 15, allow_blank: true
# end
#
# # RSpec
# describe User do
# it { should validate_length_of(:bio).is_at_least(15).allow_blank }
# end
#
# # Minitest (Shoulda)
# class UserTest < ActiveSupport::TestCase
# should validate_length_of(:bio).is_at_least(15).allow_blank
# end
#
def validate_length_of(attr)
ValidateLengthOfMatcher.new(attr)
end
@ -331,7 +352,8 @@ module Shoulda
lower_bound_matches? &&
upper_bound_matches? &&
allow_nil_matches?
allow_nil_matches? &&
allow_blank_matches?
end
def does_not_match?(subject)
@ -339,7 +361,8 @@ module Shoulda
lower_bound_does_not_match? ||
upper_bound_does_not_match? ||
allow_nil_does_not_match?
allow_nil_does_not_match? ||
allow_blank_does_not_match?
end
private
@ -376,6 +399,7 @@ module Shoulda
def disallows_lower_length?
!@options.key?(:minimum) ||
@options[:minimum] == 0 ||
(@options[:minimum] == 1 && expects_to_allow_blank?) ||
disallows_length_of?(
@options[:minimum] - 1,
translated_short_message

View File

@ -24,6 +24,11 @@ module Shoulda
self
end
def allow_blank
options[:allow_blank] = true
self
end
def strict
@expects_strict = true
self
@ -116,8 +121,20 @@ module Shoulda
)
end
def allow_blank_matches?
!expects_to_allow_blank? ||
blank_values.all? { |value| allows_value_of(value) }
end
def allow_blank_does_not_match?
expects_to_allow_blank? &&
blank_values.all? { |value| disallows_value_of(value) }
end
private
attr_reader :options
def overall_failure_message
Shoulda::Matchers.word_wrap(
"Expected #{model.name} to #{description}, but this could not be " +
@ -161,6 +178,14 @@ module Shoulda
@last_submatcher_run = matcher
matcher.matches?(subject)
end
def expects_to_allow_blank?
options[:allow_blank]
end
def blank_values
['', ' ', "\n", "\r", "\t", "\f"]
end
end
end
end

View File

@ -311,6 +311,62 @@ this could not be proved.
end
end
context 'qualified with allow_blank' do
context 'and validating with allow_blank' do
context 'with minimum' do
context 'and minimum is 1' do
it 'accepts' do
expect(validating_length(minimum: 1, allow_blank: true)).
to validate_length_of(:attr).is_at_least(1).allow_blank
end
end
context 'and minimum is greater than 1' do
it 'accepts' do
expect(validating_length(minimum: 2, allow_blank: true)).
to validate_length_of(:attr).is_at_least(2).allow_blank
end
end
end
context 'with maximum' do
context 'and maximum is 0' do
it 'accepts' do
expect(validating_length(maximum: 0, allow_blank: true)).
to validate_length_of(:attr).is_at_most(0).allow_blank
end
end
context 'and maximum is greater than 0' do
it 'accepts' do
expect(validating_length(maximum: 1, allow_blank: true)).
to validate_length_of(:attr).is_at_most(1).allow_blank
end
end
end
end
context 'and not validating with allow_blank' do
it 'rejects' do
assertion = lambda do
expect(validating_length(minimum: 1)).
to validate_length_of(:attr).is_at_least(1).allow_blank
end
message = <<-MESSAGE
Expected Example to validate that the length of :attr is at least 1, but
this could not be proved.
After setting :attr to "", 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 }