shoulda-matchers 2.8.0 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound_config/ruby.yml +7 -0
- data/.travis.yml +11 -54
- data/Appraisals +45 -100
- data/CONTRIBUTING.md +51 -7
- data/Gemfile +7 -19
- data/Gemfile.lock +60 -134
- data/Guardfile +5 -0
- data/NEWS.md +203 -0
- data/README.md +95 -50
- data/Rakefile +1 -0
- data/doc_config/yard/templates/default/layout/html/setup.rb +1 -1
- data/gemfiles/4.0.0.gemfile +10 -7
- data/gemfiles/4.0.0.gemfile.lock +103 -79
- data/gemfiles/4.0.1.gemfile +10 -7
- data/gemfiles/4.0.1.gemfile.lock +109 -83
- data/gemfiles/4.1.gemfile +10 -7
- data/gemfiles/4.1.gemfile.lock +109 -85
- data/gemfiles/4.2.gemfile +10 -9
- data/gemfiles/4.2.gemfile.lock +86 -78
- data/lib/shoulda/matchers.rb +13 -18
- data/lib/shoulda/matchers/action_controller.rb +4 -1
- data/lib/shoulda/matchers/action_controller/flash_store.rb +95 -0
- data/lib/shoulda/matchers/action_controller/{strong_parameters_matcher.rb → permit_matcher.rb} +147 -30
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +1 -1
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +1 -1
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +1 -1
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -1
- data/lib/shoulda/matchers/action_controller/route_params.rb +15 -6
- data/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
- data/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +30 -136
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +28 -109
- data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +103 -0
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +1 -12
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +79 -10
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +10 -0
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +21 -0
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +24 -0
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +22 -5
- data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +29 -10
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +27 -10
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +27 -12
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +56 -20
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +3 -11
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +65 -0
- data/lib/shoulda/matchers/active_record/association_matcher.rb +40 -6
- data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +21 -7
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +11 -40
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +1 -1
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +2 -6
- data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +137 -22
- data/lib/shoulda/matchers/configuration.rb +20 -0
- data/lib/shoulda/matchers/doublespeak.rb +11 -1
- data/lib/shoulda/matchers/doublespeak/double.rb +29 -11
- data/lib/shoulda/matchers/doublespeak/double_collection.rb +4 -3
- data/lib/shoulda/matchers/doublespeak/method_call.rb +35 -0
- data/lib/shoulda/matchers/doublespeak/object_double.rb +7 -2
- data/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +4 -3
- data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +3 -3
- data/lib/shoulda/matchers/doublespeak/world.rb +21 -1
- data/lib/shoulda/matchers/integrations.rb +43 -0
- data/lib/shoulda/matchers/integrations/configuration.rb +68 -0
- data/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
- data/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
- data/lib/shoulda/matchers/integrations/libraries.rb +15 -0
- data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +31 -0
- data/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
- data/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
- data/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
- data/lib/shoulda/matchers/integrations/libraries/rails.rb +30 -0
- data/lib/shoulda/matchers/integrations/rails.rb +12 -0
- data/lib/shoulda/matchers/integrations/registry.rb +28 -0
- data/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
- data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
- data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
- data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
- data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
- data/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
- data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
- data/lib/shoulda/matchers/rails_shim.rb +0 -40
- data/lib/shoulda/matchers/version.rb +1 -1
- data/script/SUPPORTED_VERSIONS +1 -1
- data/script/update_gems_in_all_appraisals +14 -0
- data/shoulda-matchers.gemspec +2 -2
- data/spec/acceptance/active_model_integration_spec.rb +4 -1
- data/spec/acceptance/independent_matchers_spec.rb +6 -6
- data/spec/acceptance/multiple_libraries_integration_spec.rb +52 -0
- data/spec/acceptance/rails_integration_spec.rb +15 -5
- data/spec/acceptance_spec_helper.rb +8 -0
- data/spec/doublespeak_spec_helper.rb +14 -0
- data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +110 -0
- data/spec/support/acceptance/helpers.rb +2 -0
- data/spec/support/acceptance/helpers/base_helpers.rb +6 -1
- data/spec/support/acceptance/helpers/command_helpers.rb +6 -2
- data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -8
- data/spec/support/acceptance/helpers/n_unit_helpers.rb +25 -0
- data/spec/support/acceptance/helpers/rspec_helpers.rb +2 -0
- data/spec/support/acceptance/helpers/step_helpers.rb +13 -19
- data/spec/support/acceptance/matchers/have_output.rb +1 -1
- data/spec/support/tests/bundle.rb +1 -1
- data/spec/support/tests/command_runner.rb +25 -13
- data/spec/support/tests/current_bundle.rb +47 -0
- data/spec/support/tests/database.rb +28 -0
- data/spec/support/tests/database_adapters/postgresql.rb +25 -0
- data/spec/support/tests/database_adapters/sqlite3.rb +26 -0
- data/spec/support/tests/database_configuration.rb +33 -0
- data/spec/support/tests/database_configuration_registry.rb +28 -0
- data/spec/support/tests/filesystem.rb +25 -2
- data/spec/support/unit/helpers/active_record_versions.rb +12 -0
- data/spec/support/unit/helpers/class_builder.rb +6 -2
- data/spec/support/unit/helpers/column_type_helpers.rb +26 -0
- data/spec/support/unit/helpers/controller_builder.rb +0 -28
- data/spec/support/unit/helpers/database_helpers.rb +18 -0
- data/spec/support/unit/helpers/model_builder.rb +38 -6
- data/spec/support/unit/helpers/rails_versions.rb +2 -2
- data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +9 -8
- data/spec/support/unit/matchers/fail_with_message_matcher.rb +1 -1
- data/spec/support/unit/rails_application.rb +29 -13
- data/spec/support/unit/record_validating_confirmation_builder.rb +1 -2
- data/spec/support/unit/shared_examples/set_session_or_flash.rb +355 -0
- data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +433 -0
- data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +1 -5
- data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +37 -0
- data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +23 -147
- data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +8 -285
- data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +562 -0
- data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +81 -14
- data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +16 -8
- data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +101 -9
- data/spec/unit/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +39 -1
- data/spec/unit/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +39 -1
- data/spec/unit/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +39 -0
- data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -17
- data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -17
- data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -17
- data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +838 -271
- data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -19
- data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +93 -0
- data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +3 -3
- data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +25 -0
- data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +905 -0
- data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +17 -11
- data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +1 -1
- data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +144 -43
- data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +1 -1
- data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +36 -11
- data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +29 -16
- data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +8 -5
- data/spec/unit/shoulda/matchers/doublespeak_spec.rb +1 -1
- data/spec/unit_spec_helper.rb +15 -14
- data/spec/warnings_spy.rb +1 -1
- metadata +68 -29
- data/docs.watchr +0 -5
- data/gemfiles/3.0.gemfile +0 -26
- data/gemfiles/3.0.gemfile.lock +0 -173
- data/gemfiles/3.1.gemfile +0 -32
- data/gemfiles/3.1.gemfile.lock +0 -212
- data/gemfiles/3.1_1.9.2.gemfile +0 -32
- data/gemfiles/3.1_1.9.2.gemfile.lock +0 -212
- data/gemfiles/3.2.gemfile +0 -33
- data/gemfiles/3.2.gemfile.lock +0 -212
- data/gemfiles/3.2_1.9.2.gemfile +0 -31
- data/gemfiles/3.2_1.9.2.gemfile.lock +0 -207
- data/lib/shoulda/matchers/assertion_error.rb +0 -27
- data/lib/shoulda/matchers/doublespeak/structs.rb +0 -10
- data/lib/shoulda/matchers/integrations/nunit_test_case_detection.rb +0 -39
- data/lib/shoulda/matchers/integrations/rspec.rb +0 -19
- data/lib/shoulda/matchers/integrations/test_unit.rb +0 -34
- data/spec/unit/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +0 -331
- data/spec/unit/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +0 -564
data/spec/unit/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb
CHANGED
@@ -45,6 +45,44 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::OddNumberMatcher
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
context 'asserting strict validation when validating strictly' do
|
49
|
+
it 'accepts' do
|
50
|
+
expect(validating_odd_number(strict: true)).to subject.strict
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'asserting non-strict validation when validating strictly' do
|
55
|
+
it 'rejects' do
|
56
|
+
pending 'This needs to be fixed'
|
57
|
+
expect(validating_odd_number(strict: true)).not_to subject
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'asserting strict validation when not validating strictly' do
|
62
|
+
it 'rejects' do
|
63
|
+
expect(validating_odd_number).not_to subject.strict
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'qualified with on and validating with on' do
|
68
|
+
it 'accepts' do
|
69
|
+
expect(validating_odd_number(on: :customizable)).
|
70
|
+
to subject.on(:customizable)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'qualified with on but not validating with on' do
|
75
|
+
it 'accepts since the validation never considers a context' do
|
76
|
+
expect(validating_odd_number).to subject.on(:customizable)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'not qualified with on but validating with on' do
|
81
|
+
it 'rejects since the validation never runs' do
|
82
|
+
expect(validating_odd_number(on: :customizable)).
|
83
|
+
not_to subject
|
84
|
+
end
|
85
|
+
end
|
48
86
|
|
49
87
|
def validating_odd_number(options = {})
|
50
88
|
define_model :example, attr: :string do
|
@@ -56,4 +94,4 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::OddNumberMatcher
|
|
56
94
|
define_model(:example, attr: :string).new
|
57
95
|
end
|
58
96
|
|
59
|
-
end
|
97
|
+
end
|
data/spec/unit/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb
CHANGED
@@ -45,6 +45,45 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::OnlyIntegerMatche
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
context 'asserting strict validation when validating strictly' do
|
49
|
+
it 'accepts' do
|
50
|
+
expect(validating_only_integer(strict: true)).to subject.strict
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'asserting non-strict validation when validating strictly' do
|
55
|
+
it 'rejects' do
|
56
|
+
pending 'This needs to be fixed'
|
57
|
+
expect(validating_only_integer(strict: true)).not_to subject
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'asserting strict validation when not validating strictly' do
|
62
|
+
it 'rejects' do
|
63
|
+
expect(validating_only_integer).not_to subject.strict
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'qualified with on and validating with on' do
|
68
|
+
it 'accepts' do
|
69
|
+
expect(validating_only_integer(on: :customizable)).
|
70
|
+
to subject.on(:customizable)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'qualified with on but not validating with on' do
|
75
|
+
it 'accepts since the validation never considers a context' do
|
76
|
+
expect(validating_only_integer).to subject.on(:customizable)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'not qualified with on but validating with on' do
|
81
|
+
it 'rejects since the validation never runs' do
|
82
|
+
expect(validating_only_integer(on: :customizable)).
|
83
|
+
not_to subject
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
48
87
|
def validating_only_integer(options = {})
|
49
88
|
define_model :example, attr: :string do
|
50
89
|
validates_numericality_of :attr, { only_integer: true }.merge(options)
|
@@ -1,22 +1,5 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
|
-
describe Shoulda::Matchers::ActiveModel, type: :model do
|
4
|
-
describe '#ensure_exclusion_of' do
|
5
|
-
it 'is aliased to #validate_exclusion_of' do
|
6
|
-
allow(matchers).to receive(:validate_exclusion_of)
|
7
|
-
|
8
|
-
silence_warnings do
|
9
|
-
matchers.ensure_exclusion_of(:attr)
|
10
|
-
expect(matchers).to have_received(:validate_exclusion_of).with(:attr)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def matchers
|
16
|
-
@_matchers ||= Object.new.extend(described_class)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
3
|
describe Shoulda::Matchers::ActiveModel::ValidateExclusionOfMatcher, type: :model do
|
21
4
|
context 'an attribute which must be excluded from a range' do
|
22
5
|
it 'accepts ensuring the correct range' do
|
@@ -1,22 +1,5 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
|
-
describe Shoulda::Matchers::ActiveModel, type: :model do
|
4
|
-
describe '#ensure_inclusion_of' do
|
5
|
-
it 'is aliased to #validate_inclusion_of' do
|
6
|
-
allow(matchers).to receive(:validate_inclusion_of)
|
7
|
-
|
8
|
-
silence_warnings do
|
9
|
-
matchers.ensure_inclusion_of(:attr)
|
10
|
-
expect(matchers).to have_received(:validate_inclusion_of)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def matchers
|
16
|
-
@_matchers ||= Object.new.extend(described_class)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
3
|
describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :model do
|
21
4
|
shared_context 'for a generic attribute' do
|
22
5
|
def self.testing_values_of_option(option_name, &block)
|
@@ -1,22 +1,5 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
|
-
describe Shoulda::Matchers::ActiveModel, type: :model do
|
4
|
-
describe '#ensure_length_of' do
|
5
|
-
it 'is aliased to #validate_length_of' do
|
6
|
-
allow(matchers).to receive(:validate_length_of)
|
7
|
-
|
8
|
-
silence_warnings do
|
9
|
-
matchers.ensure_length_of(:attr)
|
10
|
-
expect(matchers).to have_received(:validate_length_of).with(:attr)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def matchers
|
16
|
-
@_matchers ||= Object.new.extend(described_class)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
3
|
describe Shoulda::Matchers::ActiveModel::ValidateLengthOfMatcher, type: :model do
|
21
4
|
context 'an attribute with a non-zero minimum length validation' do
|
22
5
|
it 'accepts ensuring the correct minimum length' do
|
@@ -1,425 +1,992 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
3
|
describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher, type: :model do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
class << self
|
5
|
+
def all_qualifiers
|
6
|
+
[
|
7
|
+
{
|
8
|
+
category: :comparison,
|
9
|
+
name: :is_greater_than,
|
10
|
+
argument: 1,
|
11
|
+
validation_name: :greater_than,
|
12
|
+
validation_value: 1,
|
13
|
+
},
|
14
|
+
{
|
15
|
+
category: :comparison,
|
16
|
+
name: :is_greater_than_or_equal_to,
|
17
|
+
argument: 1,
|
18
|
+
validation_name: :greater_than_or_equal_to,
|
19
|
+
validation_value: 1,
|
20
|
+
},
|
21
|
+
{
|
22
|
+
category: :comparison,
|
23
|
+
name: :is_less_than,
|
24
|
+
argument: 1,
|
25
|
+
validation_name: :less_than,
|
26
|
+
validation_value: 1,
|
27
|
+
},
|
28
|
+
{
|
29
|
+
category: :comparison,
|
30
|
+
name: :is_less_than_or_equal_to,
|
31
|
+
argument: 1,
|
32
|
+
validation_name: :less_than_or_equal_to,
|
33
|
+
validation_value: 1,
|
34
|
+
},
|
35
|
+
{
|
36
|
+
category: :comparison,
|
37
|
+
name: :is_equal_to,
|
38
|
+
argument: 1,
|
39
|
+
validation_name: :equal_to,
|
40
|
+
validation_value: 1,
|
41
|
+
},
|
42
|
+
{
|
43
|
+
category: :cardinality,
|
44
|
+
name: :odd,
|
45
|
+
validation_name: :odd,
|
46
|
+
validation_value: true,
|
47
|
+
},
|
48
|
+
{
|
49
|
+
category: :cardinality,
|
50
|
+
name: :even,
|
51
|
+
validation_name: :even,
|
52
|
+
validation_value: true,
|
53
|
+
},
|
54
|
+
{
|
55
|
+
name: :only_integer,
|
56
|
+
validation_name: :only_integer,
|
57
|
+
validation_value: true,
|
58
|
+
},
|
59
|
+
{
|
60
|
+
name: :on,
|
61
|
+
argument: :customizable,
|
62
|
+
validation_name: :on,
|
63
|
+
validation_value: :customizable
|
64
|
+
}
|
65
|
+
]
|
66
|
+
end
|
67
|
+
|
68
|
+
def qualifiers_under(category)
|
69
|
+
all_qualifiers.select do |qualifier|
|
70
|
+
qualifier[:category] == category
|
71
|
+
end
|
7
72
|
end
|
8
73
|
|
9
|
-
|
10
|
-
|
74
|
+
def mutually_exclusive_qualifiers
|
75
|
+
qualifiers_under(:cardinality) + qualifiers_under(:comparison)
|
11
76
|
end
|
12
|
-
end
|
13
77
|
|
14
|
-
|
15
|
-
|
16
|
-
expect(not_validating_numericality).not_to matcher
|
78
|
+
def non_mutually_exclusive_qualifiers
|
79
|
+
all_qualifiers - mutually_exclusive_qualifiers
|
17
80
|
end
|
18
81
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end.to fail_with_message_including(
|
24
|
-
'Expected errors to include "is not a number"'
|
25
|
-
)
|
82
|
+
def validations_by_qualifier
|
83
|
+
all_qualifiers.each_with_object({}) do |qualifier, hash|
|
84
|
+
hash[qualifier[:name]] = qualifier[:validation_name]
|
85
|
+
end
|
26
86
|
end
|
27
87
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
88
|
+
def all_qualifier_combinations
|
89
|
+
combinations = []
|
90
|
+
|
91
|
+
([nil] + mutually_exclusive_qualifiers).each do |mutually_exclusive_qualifier|
|
92
|
+
(0..non_mutually_exclusive_qualifiers.length).each do |n|
|
93
|
+
non_mutually_exclusive_qualifiers.combination(n) do |combination|
|
94
|
+
super_combination = (
|
95
|
+
[mutually_exclusive_qualifier] +
|
96
|
+
combination
|
97
|
+
)
|
98
|
+
super_combination.select!(&:present?)
|
99
|
+
|
100
|
+
if super_combination.any?
|
101
|
+
combinations << super_combination
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
combinations
|
35
108
|
end
|
36
109
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end.to fail_with_message_including(
|
42
|
-
'Expected errors to include "must be odd"'
|
43
|
-
)
|
110
|
+
def default_qualifier_arguments
|
111
|
+
all_qualifiers.each_with_object({}) do |qualifier, hash|
|
112
|
+
hash[qualifier[:name]] = qualifier[:argument]
|
113
|
+
end
|
44
114
|
end
|
45
115
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end.to fail_with_message_including(
|
51
|
-
'Expected errors to include "must be even"'
|
52
|
-
)
|
116
|
+
def default_validation_values
|
117
|
+
all_qualifiers.each_with_object({}) do |qualifier, hash|
|
118
|
+
hash[qualifier[:validation_name]] = qualifier[:validation_value]
|
119
|
+
end
|
53
120
|
end
|
54
121
|
end
|
55
122
|
|
56
|
-
context 'with
|
57
|
-
|
58
|
-
|
123
|
+
context 'qualified with nothing' do
|
124
|
+
context 'and validating numericality' do
|
125
|
+
it 'accepts' do
|
126
|
+
record = build_record_validating_numericality
|
127
|
+
expect(record).to validate_numericality
|
128
|
+
end
|
59
129
|
end
|
60
130
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
expect(
|
65
|
-
|
131
|
+
context 'and not validating anything' do
|
132
|
+
it 'rejects since it does not disallow non-numbers' do
|
133
|
+
record = build_record_validating_nothing
|
134
|
+
assertion = -> { expect(record).to validate_numericality }
|
135
|
+
expect(&assertion).to fail_with_message_including(
|
136
|
+
'Expected errors to include "is not a number"'
|
137
|
+
)
|
138
|
+
end
|
66
139
|
end
|
67
140
|
end
|
68
141
|
|
69
|
-
context 'with
|
70
|
-
|
71
|
-
|
142
|
+
context 'qualified with allow_nil' do
|
143
|
+
context 'and validating with allow_nil' do
|
144
|
+
it 'accepts' do
|
145
|
+
record = build_record_validating_numericality(allow_nil: true)
|
146
|
+
expect(record).to validate_numericality.allow_nil
|
147
|
+
end
|
72
148
|
end
|
73
149
|
|
74
|
-
|
75
|
-
|
150
|
+
context 'and not validating with allow_nil' do
|
151
|
+
it 'rejects since it tries to treat nil as a number' do
|
152
|
+
record = build_record_validating_numericality
|
153
|
+
assertion = lambda do
|
154
|
+
expect(record).to validate_numericality.allow_nil
|
155
|
+
end
|
156
|
+
expect(&assertion).to fail_with_message_including(
|
157
|
+
%[Did not expect errors to include "is not a number" when #{attribute_name} is set to nil]
|
158
|
+
)
|
159
|
+
end
|
76
160
|
end
|
161
|
+
end
|
77
162
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
)
|
163
|
+
context 'qualified with only_integer' do
|
164
|
+
context 'and validating with only_integer' do
|
165
|
+
it 'accepts' do
|
166
|
+
record = build_record_validating_numericality(only_integer: true)
|
167
|
+
expect(record).to validate_numericality.only_integer
|
168
|
+
end
|
85
169
|
end
|
86
|
-
end
|
87
170
|
|
88
|
-
|
89
|
-
|
90
|
-
|
171
|
+
context 'and not validating with only_integer' do
|
172
|
+
it 'rejects since it does not disallow non-integers' do
|
173
|
+
record = build_record_validating_numericality
|
174
|
+
assertion = lambda do
|
175
|
+
expect(record).to validate_numericality.only_integer
|
176
|
+
end
|
177
|
+
expect(&assertion).to fail_with_message_including(
|
178
|
+
'Expected errors to include "must be an integer"'
|
179
|
+
)
|
180
|
+
end
|
91
181
|
end
|
182
|
+
end
|
92
183
|
|
93
|
-
|
94
|
-
|
184
|
+
context 'qualified with odd' do
|
185
|
+
context 'and validating with odd' do
|
186
|
+
it 'accepts' do
|
187
|
+
record = build_record_validating_numericality(odd: true)
|
188
|
+
expect(record).to validate_numericality.odd
|
189
|
+
end
|
95
190
|
end
|
96
191
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
192
|
+
context 'and not validating with odd' do
|
193
|
+
it 'rejects since it does not disallow even numbers' do
|
194
|
+
record = build_record_validating_numericality
|
195
|
+
assertion = lambda do
|
196
|
+
expect(record).to validate_numericality.odd
|
197
|
+
end
|
198
|
+
expect(&assertion).to fail_with_message_including(
|
199
|
+
'Expected errors to include "must be odd"'
|
200
|
+
)
|
201
|
+
end
|
104
202
|
end
|
105
203
|
end
|
106
204
|
|
107
|
-
context 'with
|
108
|
-
|
109
|
-
|
205
|
+
context 'qualified with even' do
|
206
|
+
context 'and validating with even' do
|
207
|
+
it 'allows even number values for that attribute' do
|
208
|
+
record = build_record_validating_numericality(even: true)
|
209
|
+
expect(record).to validate_numericality.even
|
210
|
+
end
|
110
211
|
end
|
111
212
|
|
112
|
-
|
113
|
-
|
213
|
+
context 'and not validating with even' do
|
214
|
+
it 'rejects since it does not disallow odd numbers' do
|
215
|
+
record = build_record_validating_numericality
|
216
|
+
assertion = -> { expect(record).to validate_numericality.even }
|
217
|
+
expect(&assertion).to fail_with_message_including(
|
218
|
+
'Expected errors to include "must be even"'
|
219
|
+
)
|
220
|
+
end
|
114
221
|
end
|
222
|
+
end
|
115
223
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
224
|
+
context 'qualified with is_less_than_or_equal_to' do
|
225
|
+
context 'and validating with less_than_or_equal_to' do
|
226
|
+
it 'accepts' do
|
227
|
+
record = build_record_validating_numericality(
|
228
|
+
less_than_or_equal_to: 18
|
229
|
+
)
|
230
|
+
expect(record).to validate_numericality.is_less_than_or_equal_to(18)
|
231
|
+
end
|
232
|
+
|
233
|
+
context 'if the given value is right at the allowed max value for the column' do
|
234
|
+
it 'does not raise an error' do
|
235
|
+
record = build_record_with_integer_column_of_limit(2,
|
236
|
+
less_than_or_equal_to: 32767
|
237
|
+
)
|
238
|
+
assertion = lambda do
|
239
|
+
expect(record).
|
240
|
+
to validate_numericality.
|
241
|
+
is_less_than_or_equal_to(32767)
|
242
|
+
end
|
243
|
+
expect(&assertion).not_to raise_error
|
244
|
+
end
|
245
|
+
end
|
123
246
|
end
|
124
|
-
end
|
125
247
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
248
|
+
context 'and not validating with less_than_or_equal_to' do
|
249
|
+
it 'rejects since it does not disallow numbers greater than the value' do
|
250
|
+
record = build_record_validating_numericality
|
251
|
+
assertion = lambda do
|
252
|
+
expect(record).
|
253
|
+
to validate_numericality.
|
254
|
+
is_less_than_or_equal_to(18)
|
255
|
+
end
|
256
|
+
expect(&assertion).to fail_with_message_including(
|
257
|
+
'Expected errors to include "must be less than or equal to 18"'
|
258
|
+
)
|
259
|
+
end
|
133
260
|
end
|
134
261
|
end
|
135
262
|
|
136
|
-
context 'qualified with
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
expect(record).
|
141
|
-
|
142
|
-
|
263
|
+
context 'qualified with is_less_than' do
|
264
|
+
context 'and validating with less_than' do
|
265
|
+
it 'accepts' do
|
266
|
+
record = build_record_validating_numericality(less_than: 18)
|
267
|
+
expect(record).
|
268
|
+
to validate_numericality.
|
269
|
+
is_less_than(18)
|
270
|
+
end
|
271
|
+
|
272
|
+
context 'if the given value is right at the allowed max value for the column' do
|
273
|
+
it 'does not raise an error' do
|
274
|
+
record = build_record_with_integer_column_of_limit(2, less_than: 32767)
|
275
|
+
assertion = lambda do
|
276
|
+
expect(record).to validate_numericality.is_less_than(32767)
|
277
|
+
end
|
278
|
+
expect(&assertion).not_to raise_error
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'and not validating with less_than' do
|
284
|
+
it 'rejects since it does not disallow numbers greater than or equal to the value' do
|
285
|
+
record = build_record_validating_numericality
|
286
|
+
assertion = lambda do
|
287
|
+
expect(record).
|
288
|
+
to validate_numericality.
|
289
|
+
is_less_than(18)
|
290
|
+
end
|
291
|
+
expect(&assertion).to fail_with_message_including(
|
292
|
+
'Expected errors to include "must be less than 18"'
|
293
|
+
)
|
294
|
+
end
|
143
295
|
end
|
144
296
|
end
|
145
297
|
|
146
|
-
context 'qualified with
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
expect(record).to
|
151
|
-
|
152
|
-
|
298
|
+
context 'qualified with is_equal_to' do
|
299
|
+
context 'and validating with equal_to' do
|
300
|
+
it 'accepts' do
|
301
|
+
record = build_record_validating_numericality(equal_to: 18)
|
302
|
+
expect(record).to validate_numericality.is_equal_to(18)
|
303
|
+
end
|
304
|
+
|
305
|
+
context 'if the given value is right at the allowed min value for the column' do
|
306
|
+
it 'does not raise an error' do
|
307
|
+
record = build_record_with_integer_column_of_limit(2, equal_to: -32768)
|
308
|
+
assertion = lambda do
|
309
|
+
expect(record).to validate_numericality.is_equal_to(-32768)
|
310
|
+
end
|
311
|
+
expect(&assertion).not_to raise_error
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context 'if the given value is right at the allowed max value for the column' do
|
316
|
+
it 'does not raise an error' do
|
317
|
+
record = build_record_with_integer_column_of_limit(2, equal_to: 32767)
|
318
|
+
assertion = lambda do
|
319
|
+
expect(record).to validate_numericality.is_equal_to(32767)
|
320
|
+
end
|
321
|
+
expect(&assertion).not_to raise_error
|
322
|
+
end
|
323
|
+
end
|
153
324
|
end
|
154
325
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
326
|
+
context 'and not validating with equal_to' do
|
327
|
+
it 'rejects since it does not disallow numbers that are not the value' do
|
328
|
+
record = build_record_validating_numericality
|
329
|
+
assertion = lambda do
|
330
|
+
expect(record).to validate_numericality.is_equal_to(18)
|
331
|
+
end
|
332
|
+
expect(&assertion).to fail_with_message_including(
|
333
|
+
'Expected errors to include "must be equal to 18"'
|
334
|
+
)
|
335
|
+
end
|
161
336
|
end
|
162
337
|
end
|
163
338
|
|
164
|
-
context 'qualified with
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
339
|
+
context 'qualified with is_greater_than_or_equal to' do
|
340
|
+
context 'validating with greater_than_or_equal_to' do
|
341
|
+
it 'accepts' do
|
342
|
+
record = build_record_validating_numericality(
|
343
|
+
greater_than_or_equal_to: 18
|
344
|
+
)
|
170
345
|
expect(record).
|
171
|
-
to
|
172
|
-
is_greater_than_or_equal_to(
|
173
|
-
|
174
|
-
|
346
|
+
to validate_numericality.
|
347
|
+
is_greater_than_or_equal_to(18)
|
348
|
+
end
|
349
|
+
|
350
|
+
context 'if the given value is right at the allowed min value for the column' do
|
351
|
+
it 'does not raise an error' do
|
352
|
+
record = build_record_with_integer_column_of_limit(2,
|
353
|
+
greater_than_or_equal_to: -32768
|
354
|
+
)
|
355
|
+
assertion = lambda do
|
356
|
+
expect(record).
|
357
|
+
to validate_numericality_of(:attr).
|
358
|
+
is_greater_than_or_equal_to(-32768)
|
359
|
+
end
|
360
|
+
expect(&assertion).not_to raise_error
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
context 'not validating with greater_than_or_equal_to' do
|
366
|
+
it 'rejects since it does not disallow numbers that are less than the value' do
|
367
|
+
record = build_record_validating_numericality
|
368
|
+
assertion = lambda do
|
369
|
+
expect(record).
|
370
|
+
to validate_numericality.
|
371
|
+
is_greater_than_or_equal_to(18)
|
372
|
+
end
|
373
|
+
expect(&assertion).to fail_with_message_including(
|
374
|
+
'Expected errors to include "must be greater than or equal to 18"'
|
375
|
+
)
|
376
|
+
end
|
175
377
|
end
|
176
378
|
end
|
177
379
|
|
178
|
-
context 'qualified with
|
179
|
-
|
180
|
-
|
181
|
-
greater_than:
|
182
|
-
)
|
183
|
-
assertion = -> {
|
380
|
+
context 'qualified with is_greater_than' do
|
381
|
+
context 'and validating with greater_than' do
|
382
|
+
it 'accepts' do
|
383
|
+
record = build_record_validating_numericality(greater_than: 18)
|
184
384
|
expect(record).
|
185
|
-
to
|
186
|
-
is_greater_than(
|
187
|
-
|
188
|
-
|
385
|
+
to validate_numericality.
|
386
|
+
is_greater_than(18)
|
387
|
+
end
|
388
|
+
|
389
|
+
context 'if the given value is right at the allowed min value for the column' do
|
390
|
+
it 'does not raise an error' do
|
391
|
+
record = build_record_with_integer_column_of_limit(2,
|
392
|
+
greater_than: -32768
|
393
|
+
)
|
394
|
+
assertion = lambda do
|
395
|
+
expect(record).
|
396
|
+
to validate_numericality_of(:attr).
|
397
|
+
is_greater_than(-32768)
|
398
|
+
end
|
399
|
+
expect(&assertion).not_to raise_error
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
context 'and not validating with greater_than' do
|
405
|
+
it 'rejects since it does not disallow numbers that are less than or equal to the value' do
|
406
|
+
record = build_record_validating_numericality
|
407
|
+
assertion = lambda do
|
408
|
+
expect(record).
|
409
|
+
to validate_numericality.
|
410
|
+
is_greater_than(18)
|
411
|
+
end
|
412
|
+
expect(&assertion).to fail_with_message_including(
|
413
|
+
'Expected errors to include "must be greater than 18"'
|
414
|
+
)
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
context 'qualified with with_message' do
|
420
|
+
context 'and validating with the same message' do
|
421
|
+
it 'accepts' do
|
422
|
+
record = build_record_validating_numericality(message: 'custom')
|
423
|
+
expect(record).to validate_numericality.with_message(/custom/)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
context 'and validating with a different message' do
|
428
|
+
it 'rejects' do
|
429
|
+
record = build_record_validating_numericality(message: 'custom')
|
430
|
+
expect(record).not_to validate_numericality.with_message(/wrong/)
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
context 'and no message is provided' do
|
435
|
+
it 'ignores the qualifier' do
|
436
|
+
record = build_record_validating_numericality
|
437
|
+
expect(record).to validate_numericality.with_message(nil)
|
438
|
+
end
|
189
439
|
end
|
190
440
|
end
|
191
441
|
|
192
|
-
context 'with
|
193
|
-
context '
|
194
|
-
it do
|
195
|
-
|
196
|
-
|
442
|
+
context 'qualified with strict' do
|
443
|
+
context 'and validating strictly' do
|
444
|
+
it 'accepts' do
|
445
|
+
record = build_record_validating_numericality(strict: true)
|
446
|
+
expect(record).to validate_numericality.strict
|
197
447
|
end
|
448
|
+
end
|
198
449
|
|
199
|
-
|
200
|
-
|
201
|
-
|
450
|
+
context 'and not validating strictly' do
|
451
|
+
it 'rejects since ActiveModel::StrictValidationFailed is never raised' do
|
452
|
+
record = build_record_validating_numericality(attribute_name: :attr)
|
453
|
+
assertion = lambda do
|
454
|
+
expect(record).to validate_numericality_of(:attr).strict
|
455
|
+
end
|
456
|
+
expect(&assertion).to fail_with_message_including(
|
457
|
+
'Expected exception to include "Attr is not a number"'
|
458
|
+
)
|
202
459
|
end
|
203
|
-
|
204
|
-
|
205
|
-
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
context 'qualified with on and validating with on' do
|
464
|
+
it 'accepts' do
|
465
|
+
record = build_record_validating_numericality(on: :customizable)
|
466
|
+
expect(record).to validate_numericality.on(:customizable)
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
context 'qualified with on but not validating with on' do
|
471
|
+
it 'accepts since the validation never considers a context' do
|
472
|
+
record = build_record_validating_numericality
|
473
|
+
expect(record).to validate_numericality.on(:customizable)
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
context 'not qualified with on but validating with on' do
|
478
|
+
it 'rejects since the validation never runs' do
|
479
|
+
record = build_record_validating_numericality(on: :customizable)
|
480
|
+
assertion = lambda do
|
481
|
+
expect(record).to validate_numericality
|
206
482
|
end
|
483
|
+
expect(&assertion).to fail_with_message_including(
|
484
|
+
'Expected errors to include "is not a number"'
|
485
|
+
)
|
486
|
+
end
|
487
|
+
end
|
207
488
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
489
|
+
context 'with combinations of qualifiers together' do
|
490
|
+
all_qualifier_combinations.each do |combination|
|
491
|
+
if combination.size > 1
|
492
|
+
it do
|
493
|
+
validation_options = build_validation_options(for: combination)
|
494
|
+
record = build_record_validating_numericality(validation_options)
|
495
|
+
validate_numericality = self.validate_numericality
|
496
|
+
apply_qualifiers!(for: combination, to: validate_numericality)
|
497
|
+
expect(record).to validate_numericality
|
498
|
+
end
|
214
499
|
end
|
215
500
|
end
|
216
501
|
|
217
|
-
context 'the
|
218
|
-
|
219
|
-
|
220
|
-
|
502
|
+
context 'when the qualifiers do not match the validation options' do
|
503
|
+
specify 'such as validating even but testing that only_integer is validated' do
|
504
|
+
record = build_record_validating_numericality(
|
505
|
+
even: true,
|
506
|
+
greater_than: 18
|
507
|
+
)
|
508
|
+
assertion = lambda do
|
509
|
+
expect(record).
|
510
|
+
to validate_numericality.
|
511
|
+
only_integer.
|
512
|
+
is_greater_than(18)
|
513
|
+
end
|
514
|
+
message = format_message_according_to_rails_version(
|
515
|
+
<<-MESSAGE.strip_heredoc
|
516
|
+
Expected errors to include "must be an integer" when attr is set to 0.1,
|
517
|
+
got errors:
|
518
|
+
* "must be greater than 18" (attribute: attr, value: "0.1")
|
519
|
+
MESSAGE
|
520
|
+
)
|
521
|
+
expect(&assertion).to fail_with_message(message)
|
221
522
|
end
|
222
523
|
|
223
|
-
|
224
|
-
|
225
|
-
|
524
|
+
specify 'such as not validating only_integer but testing that only_integer is validated' do
|
525
|
+
record = build_record_validating_numericality(greater_than: 18)
|
526
|
+
assertion = lambda do
|
527
|
+
expect(record).
|
528
|
+
to validate_numericality.
|
529
|
+
only_integer.
|
530
|
+
is_greater_than(18)
|
531
|
+
end
|
532
|
+
message = format_message_according_to_rails_version(
|
533
|
+
<<-MESSAGE.strip_heredoc
|
534
|
+
Expected errors to include "must be an integer" when attr is set to 0.1,
|
535
|
+
got errors:
|
536
|
+
* "must be greater than 18" (attribute: attr, value: "0.1")
|
537
|
+
MESSAGE
|
538
|
+
)
|
539
|
+
expect(&assertion).to fail_with_message(message)
|
226
540
|
end
|
227
541
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
542
|
+
specify 'such as validating greater_than_or_equal_to (+ even) but testing that greater_than is validated' do
|
543
|
+
record = build_record_validating_numericality(
|
544
|
+
even: true,
|
545
|
+
greater_than_or_equal_to: 18
|
546
|
+
)
|
547
|
+
assertion = lambda do
|
548
|
+
expect(record).
|
549
|
+
to validate_numericality.
|
550
|
+
even.
|
551
|
+
is_greater_than(18)
|
552
|
+
end
|
553
|
+
message = format_message_according_to_rails_version(
|
554
|
+
<<-MESSAGE.strip_heredoc
|
555
|
+
Expected errors to include "must be greater than 18" when attr is set to 18,
|
556
|
+
got no errors
|
557
|
+
MESSAGE
|
558
|
+
)
|
559
|
+
expect(&assertion).to fail_with_message(message)
|
232
560
|
end
|
233
561
|
|
234
|
-
|
235
|
-
|
236
|
-
|
562
|
+
specify 'such as validating odd (+ greater_than) but testing that even is validated' do
|
563
|
+
record = build_record_validating_numericality(
|
564
|
+
odd: true,
|
565
|
+
greater_than: 18
|
566
|
+
)
|
567
|
+
assertion = lambda do
|
568
|
+
expect(record).
|
569
|
+
to validate_numericality.
|
570
|
+
even.
|
571
|
+
is_greater_than(18)
|
572
|
+
end
|
573
|
+
message = format_message_according_to_rails_version(
|
574
|
+
<<-MESSAGE.strip_heredoc
|
575
|
+
Expected errors to include "must be even" when attr is set to 1,
|
576
|
+
got errors:
|
577
|
+
* "must be greater than 18" (attribute: attr, value: "1")
|
578
|
+
MESSAGE
|
579
|
+
)
|
580
|
+
expect(&assertion).to fail_with_message(message)
|
237
581
|
end
|
238
582
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
583
|
+
specify 'such as validating greater_than_or_equal_to (+ odd) but testing that is_less_than_or_equal_to is validated' do
|
584
|
+
record = build_record_validating_numericality(
|
585
|
+
odd: true,
|
586
|
+
greater_than_or_equal_to: 99
|
587
|
+
)
|
588
|
+
assertion = lambda do
|
589
|
+
expect(record).
|
590
|
+
to validate_numericality.
|
591
|
+
odd.
|
592
|
+
is_less_than_or_equal_to(99)
|
593
|
+
end
|
594
|
+
message = format_message_according_to_rails_version(
|
595
|
+
<<-MESSAGE.strip_heredoc
|
596
|
+
Expected errors to include "must be less than or equal to 99" when attr is set to 101,
|
597
|
+
got no errors
|
598
|
+
MESSAGE
|
599
|
+
)
|
600
|
+
expect(&assertion).to fail_with_message(message)
|
245
601
|
end
|
246
602
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
603
|
+
specify 'such as validating greater_than_or_equal_to (+ only_integer + less_than) but testing that greater_than is validated' do
|
604
|
+
record = build_record_validating_numericality(
|
605
|
+
only_integer: true,
|
606
|
+
greater_than_or_equal_to: 18,
|
607
|
+
less_than: 99
|
608
|
+
)
|
609
|
+
assertion = lambda do
|
610
|
+
expect(record).
|
611
|
+
to validate_numericality.
|
612
|
+
only_integer.
|
613
|
+
is_greater_than(18).
|
614
|
+
is_less_than(99)
|
615
|
+
end
|
616
|
+
message = format_message_according_to_rails_version(
|
617
|
+
<<-MESSAGE.strip_heredoc
|
618
|
+
Expected errors to include "must be greater than 18" when attr is set to 18,
|
619
|
+
got no errors
|
620
|
+
MESSAGE
|
621
|
+
)
|
622
|
+
expect(&assertion).to fail_with_message(message)
|
254
623
|
end
|
255
624
|
end
|
256
625
|
|
257
|
-
context 'the
|
258
|
-
|
259
|
-
|
260
|
-
|
626
|
+
context 'when qualifiers match the validation options but the values are different' do
|
627
|
+
specify 'such as testing greater_than (+ only_integer) with lower value' do
|
628
|
+
record = build_record_validating_numericality(
|
629
|
+
only_integer: true,
|
630
|
+
greater_than: 19
|
631
|
+
)
|
632
|
+
assertion = lambda do
|
633
|
+
expect(record).
|
634
|
+
to validate_numericality.
|
635
|
+
only_integer.
|
636
|
+
is_greater_than(18)
|
637
|
+
end
|
638
|
+
message = format_message_according_to_rails_version(
|
639
|
+
<<-MESSAGE.strip_heredoc
|
640
|
+
Expected errors to include "must be greater than 18" when attr is set to 18,
|
641
|
+
got errors:
|
642
|
+
* "must be greater than 19" (attribute: attr, value: "19")
|
643
|
+
MESSAGE
|
644
|
+
)
|
645
|
+
expect(&assertion).to fail_with_message(message)
|
261
646
|
end
|
262
647
|
|
263
|
-
|
264
|
-
|
265
|
-
|
648
|
+
specify 'such as testing greater_than (+ only_integer) with higher value' do
|
649
|
+
record = build_record_validating_numericality(
|
650
|
+
only_integer: true,
|
651
|
+
greater_than: 17
|
652
|
+
)
|
653
|
+
assertion = lambda do
|
654
|
+
expect(record).
|
655
|
+
to validate_numericality.
|
656
|
+
only_integer.
|
657
|
+
is_greater_than(18)
|
658
|
+
end
|
659
|
+
message = format_message_according_to_rails_version(
|
660
|
+
<<-MESSAGE.strip_heredoc
|
661
|
+
Expected errors to include "must be greater than 18" when attr is set to 18,
|
662
|
+
got no errors
|
663
|
+
MESSAGE
|
664
|
+
)
|
665
|
+
expect(&assertion).to fail_with_message(message)
|
266
666
|
end
|
267
667
|
|
268
|
-
|
269
|
-
|
270
|
-
|
668
|
+
specify 'such as testing greater_than (+ even) with lower value' do
|
669
|
+
record = build_record_validating_numericality(
|
670
|
+
even: true,
|
671
|
+
greater_than: 20
|
672
|
+
)
|
673
|
+
assertion = lambda do
|
674
|
+
expect(record).
|
675
|
+
to validate_numericality.
|
676
|
+
even.
|
677
|
+
is_greater_than(18)
|
678
|
+
end
|
679
|
+
message = format_message_according_to_rails_version(
|
680
|
+
<<-MESSAGE.strip_heredoc
|
681
|
+
Expected errors to include "must be greater than 18" when attr is set to 18,
|
682
|
+
got errors:
|
683
|
+
* "must be greater than 20" (attribute: attr, value: "20")
|
684
|
+
MESSAGE
|
685
|
+
)
|
686
|
+
expect(&assertion).to fail_with_message(message)
|
271
687
|
end
|
272
688
|
|
273
|
-
|
274
|
-
|
275
|
-
|
689
|
+
specify 'such as testing greater than (+ even) with higher value' do
|
690
|
+
record = build_record_validating_numericality(
|
691
|
+
even: true,
|
692
|
+
greater_than: 16
|
693
|
+
)
|
694
|
+
assertion = lambda do
|
695
|
+
expect(record).
|
696
|
+
to validate_numericality.
|
697
|
+
even.
|
698
|
+
is_greater_than(18)
|
699
|
+
end
|
700
|
+
message = format_message_according_to_rails_version(
|
701
|
+
<<-MESSAGE.strip_heredoc
|
702
|
+
Expected errors to include "must be greater than 18" when attr is set to 18,
|
703
|
+
got no errors
|
704
|
+
MESSAGE
|
705
|
+
)
|
706
|
+
expect(&assertion).to fail_with_message(message)
|
276
707
|
end
|
277
708
|
|
278
|
-
|
279
|
-
|
280
|
-
|
709
|
+
specify 'such as testing less_than_or_equal_to (+ odd) with lower value' do
|
710
|
+
record = build_record_validating_numericality(
|
711
|
+
odd: true,
|
712
|
+
less_than_or_equal_to: 101
|
713
|
+
)
|
714
|
+
assertion = lambda do
|
715
|
+
expect(record).
|
716
|
+
to validate_numericality.
|
717
|
+
odd.
|
718
|
+
is_less_than_or_equal_to(99)
|
719
|
+
end
|
720
|
+
message = format_message_according_to_rails_version(
|
721
|
+
<<-MESSAGE.strip_heredoc
|
722
|
+
Expected errors to include "must be less than or equal to 99" when attr is set to 101,
|
723
|
+
got no errors
|
724
|
+
MESSAGE
|
725
|
+
)
|
726
|
+
expect(&assertion).to fail_with_message(message)
|
281
727
|
end
|
282
728
|
|
283
|
-
|
284
|
-
|
285
|
-
|
729
|
+
specify 'such as testing less_than_or_equal_to (+ odd) with higher value' do
|
730
|
+
record = build_record_validating_numericality(
|
731
|
+
odd: true,
|
732
|
+
less_than_or_equal_to: 97
|
733
|
+
)
|
734
|
+
assertion = lambda do
|
735
|
+
expect(record).
|
736
|
+
to validate_numericality.
|
737
|
+
odd.
|
738
|
+
is_less_than_or_equal_to(99)
|
739
|
+
end
|
740
|
+
message = format_message_according_to_rails_version(
|
741
|
+
<<-MESSAGE.strip_heredoc
|
742
|
+
Expected errors to include "must be less than or equal to 99" when attr is set to 101,
|
743
|
+
got errors:
|
744
|
+
* "must be less than or equal to 97" (attribute: attr, value: "101")
|
745
|
+
MESSAGE
|
746
|
+
)
|
747
|
+
expect(&assertion).to fail_with_message(message)
|
286
748
|
end
|
287
749
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
750
|
+
specify 'such as testing greater_than (+ only_integer + less_than) with lower value' do
|
751
|
+
record = build_record_validating_numericality(
|
752
|
+
only_integer: true,
|
753
|
+
greater_than: 19,
|
754
|
+
less_than: 99
|
755
|
+
)
|
756
|
+
assertion = lambda do
|
757
|
+
expect(record).
|
758
|
+
to validate_numericality.
|
759
|
+
only_integer.
|
760
|
+
is_greater_than(18).
|
761
|
+
is_less_than(99)
|
762
|
+
end
|
763
|
+
message = format_message_according_to_rails_version(
|
764
|
+
<<-MESSAGE.strip_heredoc
|
765
|
+
Expected errors to include "must be greater than 18" when attr is set to 18,
|
766
|
+
got errors:
|
767
|
+
* "must be greater than 19" (attribute: attr, value: "19")
|
768
|
+
MESSAGE
|
769
|
+
)
|
770
|
+
expect(&assertion).to fail_with_message(message)
|
293
771
|
end
|
294
772
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
773
|
+
specify 'such as testing less_than (+ only_integer + greater_than) with higher value' do
|
774
|
+
record = build_record_validating_numericality(
|
775
|
+
only_integer: true,
|
776
|
+
greater_than: 18,
|
777
|
+
less_than: 100
|
778
|
+
)
|
779
|
+
assertion = lambda do
|
780
|
+
expect(record).
|
781
|
+
to validate_numericality.
|
782
|
+
only_integer.
|
783
|
+
is_greater_than(18).
|
784
|
+
is_less_than(99)
|
785
|
+
end
|
786
|
+
message = format_message_according_to_rails_version(
|
787
|
+
<<-MESSAGE.strip_heredoc
|
788
|
+
Expected errors to include "must be less than 99" when attr is set to 100,
|
789
|
+
got errors:
|
790
|
+
* "must be less than 100" (attribute: attr, value: "100")
|
791
|
+
MESSAGE
|
792
|
+
)
|
793
|
+
expect(&assertion).to fail_with_message(message)
|
300
794
|
end
|
301
795
|
end
|
302
796
|
end
|
303
797
|
|
304
798
|
context 'with large numbers' do
|
305
799
|
it do
|
306
|
-
|
307
|
-
|
800
|
+
record = build_record_validating_numericality(greater_than: 100_000)
|
801
|
+
expect(record).to validate_numericality.is_greater_than(100_000)
|
308
802
|
end
|
309
803
|
|
310
804
|
it do
|
311
|
-
|
312
|
-
|
805
|
+
record = build_record_validating_numericality(less_than: 100_000)
|
806
|
+
expect(record).to validate_numericality.is_less_than(100_000)
|
313
807
|
end
|
314
808
|
|
315
809
|
it do
|
316
|
-
|
317
|
-
|
810
|
+
record = build_record_validating_numericality(
|
811
|
+
greater_than_or_equal_to: 100_000
|
812
|
+
)
|
813
|
+
expect(record).
|
814
|
+
to validate_numericality.
|
815
|
+
is_greater_than_or_equal_to(100_000)
|
318
816
|
end
|
319
817
|
|
320
818
|
it do
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
it 'accepts when the messages match' do
|
328
|
-
expect(validating_numericality(message: 'custom')).
|
329
|
-
to matcher.with_message(/custom/)
|
330
|
-
end
|
331
|
-
|
332
|
-
it 'rejects when the messages do not match' do
|
333
|
-
expect(validating_numericality(message: 'custom')).
|
334
|
-
not_to matcher.with_message(/wrong/)
|
819
|
+
record = build_record_validating_numericality(
|
820
|
+
less_than_or_equal_to: 100_000
|
821
|
+
)
|
822
|
+
expect(record).
|
823
|
+
to validate_numericality.
|
824
|
+
is_less_than_or_equal_to(100_000)
|
335
825
|
end
|
336
826
|
end
|
337
827
|
|
338
828
|
context 'when the subject is stubbed' do
|
339
|
-
it 'retains
|
340
|
-
|
829
|
+
it 'retains that stub while the validate_numericality is matching' do
|
830
|
+
model = define_model :example, attr: :string do
|
341
831
|
validates_numericality_of :attr, odd: true
|
342
832
|
before_validation :set_attr!
|
343
833
|
def set_attr!; self.attr = 5 end
|
344
|
-
end
|
834
|
+
end
|
345
835
|
|
346
|
-
|
347
|
-
|
836
|
+
record = model.new
|
837
|
+
allow(record).to receive(:set_attr!)
|
838
|
+
|
839
|
+
expect(record).to validate_numericality_of(:attr).odd
|
348
840
|
end
|
349
841
|
end
|
350
842
|
|
351
843
|
describe '#description' do
|
352
|
-
context '
|
353
|
-
it
|
844
|
+
context 'qualified with nothing' do
|
845
|
+
it 'describes that it allows numbers' do
|
846
|
+
matcher = validate_numericality_of(:attr)
|
847
|
+
expect(matcher.description).to eq 'only allow numbers for attr'
|
848
|
+
end
|
354
849
|
end
|
355
850
|
|
356
|
-
context 'with
|
357
|
-
it do
|
358
|
-
|
359
|
-
|
851
|
+
context 'qualified with only_integer' do
|
852
|
+
it 'describes that it allows integers' do
|
853
|
+
matcher = validate_numericality_of(:attr).only_integer
|
854
|
+
expect(matcher.description).to eq 'only allow integers for attr'
|
360
855
|
end
|
361
856
|
end
|
362
857
|
|
363
|
-
|
364
|
-
context "with #{
|
365
|
-
it do
|
366
|
-
|
367
|
-
|
858
|
+
qualifiers_under(:cardinality).each do |qualifier|
|
859
|
+
context "qualified with #{qualifier[:name]}" do
|
860
|
+
it "describes that it allows #{qualifier[:name]} numbers" do
|
861
|
+
matcher = validate_numericality_of(:attr).__send__(qualifier[:name])
|
862
|
+
expect(matcher.description).
|
863
|
+
to eq "only allow #{qualifier[:name]} numbers for attr"
|
368
864
|
end
|
369
865
|
end
|
370
866
|
end
|
371
867
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
.to eq(
|
381
|
-
|
382
|
-
"#{comparison.to_s.sub('is_', '').gsub('_', ' ')} 18"
|
868
|
+
qualifiers_under(:comparison).each do |qualifier|
|
869
|
+
comparison_phrase = qualifier[:validation_name].to_s.gsub('_', ' ')
|
870
|
+
|
871
|
+
context "qualified with #{qualifier[:name]}" do
|
872
|
+
it "describes that it allows numbers #{comparison_phrase} a certain value" do
|
873
|
+
matcher = validate_numericality_of(:attr).
|
874
|
+
__send__(qualifier[:name], 18)
|
875
|
+
|
876
|
+
expect(matcher.description).to eq(
|
877
|
+
"only allow numbers for attr which are #{comparison_phrase} 18"
|
383
878
|
)
|
384
879
|
end
|
385
880
|
end
|
386
881
|
end
|
387
882
|
|
388
|
-
context 'with odd
|
389
|
-
it do
|
390
|
-
|
391
|
-
.
|
392
|
-
|
393
|
-
|
883
|
+
context 'qualified with odd + is_greater_than_or_equal_to' do
|
884
|
+
it "describes that it allows odd numbers greater than or equal to a certain value" do
|
885
|
+
matcher = validate_numericality_of(:attr).
|
886
|
+
odd.
|
887
|
+
is_greater_than_or_equal_to(18)
|
888
|
+
|
889
|
+
expect(matcher.description).to eq(
|
890
|
+
'only allow odd numbers for attr which are greater than or equal to 18'
|
891
|
+
)
|
892
|
+
end
|
893
|
+
end
|
894
|
+
|
895
|
+
context 'qualified with only integer + is_greater_than + less_than_or_equal_to' do
|
896
|
+
it 'describes that it allows integer greater than one value and less than or equal to another' do
|
897
|
+
matcher = validate_numericality_of(:attr).
|
898
|
+
only_integer.
|
899
|
+
is_greater_than(18).
|
900
|
+
is_less_than_or_equal_to(100)
|
901
|
+
|
902
|
+
expect(matcher.description).to eq(
|
903
|
+
'only allow integers for attr which are greater than 18 and less than or equal to 100'
|
904
|
+
)
|
905
|
+
end
|
906
|
+
end
|
907
|
+
|
908
|
+
context 'qualified with strict' do
|
909
|
+
it 'describes that it relies upon a strict validation' do
|
910
|
+
matcher = validate_numericality_of(:attr).strict
|
911
|
+
expect(matcher.description).to eq(
|
912
|
+
'only allow numbers for attr, strictly'
|
913
|
+
)
|
914
|
+
end
|
915
|
+
|
916
|
+
context 'and qualified with a comparison qualifier' do
|
917
|
+
it 'places the comparison description after "strictly"' do
|
918
|
+
matcher = validate_numericality_of(:attr).is_less_than(18).strict
|
919
|
+
expect(matcher.description).to eq(
|
920
|
+
'only allow numbers for attr, strictly, which are less than 18'
|
394
921
|
)
|
922
|
+
end
|
395
923
|
end
|
396
924
|
end
|
925
|
+
end
|
397
926
|
|
398
|
-
|
399
|
-
|
400
|
-
|
927
|
+
def build_validation_options(args)
|
928
|
+
combination = args.fetch(:for)
|
929
|
+
|
930
|
+
combination.each_with_object({}) do |qualifier, hash|
|
931
|
+
value = self.class.default_validation_values.fetch(qualifier[:validation_name])
|
932
|
+
hash[qualifier[:validation_name]] = value
|
401
933
|
end
|
402
934
|
end
|
403
935
|
|
936
|
+
def apply_qualifiers!(args)
|
937
|
+
combination = args.fetch(:for)
|
938
|
+
matcher = args.fetch(:to)
|
939
|
+
|
940
|
+
combination.each do |qualifier|
|
941
|
+
args = self.class.default_qualifier_arguments.fetch(qualifier[:name])
|
942
|
+
matcher.__send__(qualifier[:name], *args)
|
943
|
+
end
|
944
|
+
end
|
945
|
+
|
946
|
+
def define_model_validating_numericality(options = {})
|
947
|
+
attribute_name = options.delete(:attribute_name) { self.attribute_name }
|
948
|
+
|
949
|
+
define_model 'Example', attribute_name => :string do |model|
|
950
|
+
model.validates_numericality_of(attribute_name, options)
|
951
|
+
end
|
952
|
+
end
|
404
953
|
|
405
|
-
def
|
406
|
-
|
407
|
-
validates_numericality_of :attr, options
|
408
|
-
end.new
|
954
|
+
def build_record_validating_numericality(options = {})
|
955
|
+
define_model_validating_numericality(options).new
|
409
956
|
end
|
410
957
|
|
411
|
-
def
|
412
|
-
define_model(
|
958
|
+
def define_model_validating_nothing
|
959
|
+
define_model('Example', attribute_name => :string)
|
413
960
|
end
|
414
961
|
|
415
|
-
def
|
416
|
-
|
962
|
+
def build_record_validating_nothing
|
963
|
+
define_model_validating_nothing.new
|
417
964
|
end
|
418
965
|
|
419
|
-
def
|
966
|
+
def validate_numericality
|
967
|
+
validate_numericality_of(attribute_name)
|
968
|
+
end
|
969
|
+
|
970
|
+
def attribute_name
|
971
|
+
:attr
|
972
|
+
end
|
973
|
+
|
974
|
+
def define_model_with_integer_column_of_limit(limit, validation_options = {})
|
420
975
|
column_options = { type: :integer, options: { limit: limit } }
|
421
|
-
define_model :example,
|
422
|
-
validates_numericality_of
|
423
|
-
end
|
976
|
+
define_model :example, attribute_name => column_options do |model|
|
977
|
+
model.validates_numericality_of(attribute_name, validation_options)
|
978
|
+
end
|
979
|
+
end
|
980
|
+
|
981
|
+
def build_record_with_integer_column_of_limit(limit, validation_options = {})
|
982
|
+
define_model_with_integer_column_of_limit(limit, validation_options).new
|
983
|
+
end
|
984
|
+
|
985
|
+
def format_message_according_to_rails_version(message)
|
986
|
+
if rails_gte_4_2?
|
987
|
+
message
|
988
|
+
else
|
989
|
+
message.gsub(/"((?:\d+)(?:\.\d+)?)"/, '\1')
|
990
|
+
end
|
424
991
|
end
|
425
992
|
end
|