shoulda-matchers 2.8.0 → 3.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|