shoulda-matchers 3.0.1 → 3.1.0

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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -3
  4. data/CONTRIBUTING.md +60 -28
  5. data/Gemfile +1 -0
  6. data/Gemfile.lock +15 -12
  7. data/NEWS.md +111 -0
  8. data/README.md +94 -6
  9. data/Rakefile +10 -8
  10. data/custom_plan.rb +88 -0
  11. data/gemfiles/4.0.0.gemfile +1 -0
  12. data/gemfiles/4.0.0.gemfile.lock +21 -18
  13. data/gemfiles/4.0.1.gemfile +1 -0
  14. data/gemfiles/4.0.1.gemfile.lock +21 -18
  15. data/gemfiles/4.1.gemfile +1 -0
  16. data/gemfiles/4.1.gemfile.lock +21 -18
  17. data/gemfiles/4.2.gemfile +1 -0
  18. data/gemfiles/4.2.gemfile.lock +24 -21
  19. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +6 -11
  20. data/lib/shoulda/matchers/active_model.rb +10 -1
  21. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +258 -180
  22. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
  23. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
  24. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +236 -0
  25. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
  26. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
  27. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
  28. data/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
  29. data/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
  30. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +34 -14
  31. data/lib/shoulda/matchers/active_model/helpers.rb +9 -17
  32. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +13 -6
  33. data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +13 -2
  34. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +19 -35
  35. data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +13 -2
  36. data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +12 -2
  37. data/lib/shoulda/matchers/active_model/qualifiers.rb +12 -0
  38. data/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
  39. data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
  40. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +30 -32
  41. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +5 -8
  42. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +22 -22
  43. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +27 -16
  44. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +58 -15
  45. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +22 -12
  46. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +165 -87
  47. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +7 -9
  48. data/lib/shoulda/matchers/active_model/validation_matcher.rb +111 -49
  49. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +60 -0
  50. data/lib/shoulda/matchers/active_model/validator.rb +71 -52
  51. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +19 -5
  52. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +450 -124
  53. data/lib/shoulda/matchers/util.rb +43 -0
  54. data/lib/shoulda/matchers/util/word_wrap.rb +59 -31
  55. data/lib/shoulda/matchers/version.rb +1 -1
  56. data/script/update_gem_in_all_appraisals +1 -1
  57. data/script/update_gems_in_all_appraisals +1 -1
  58. data/spec/acceptance/multiple_libraries_integration_spec.rb +5 -2
  59. data/spec/acceptance/rails_integration_spec.rb +6 -2
  60. data/spec/spec_helper.rb +1 -3
  61. data/spec/support/acceptance/helpers/step_helpers.rb +4 -1
  62. data/spec/support/tests/current_bundle.rb +21 -7
  63. data/spec/support/unit/active_record/create_table.rb +54 -0
  64. data/spec/support/unit/attribute.rb +47 -0
  65. data/spec/support/unit/capture.rb +6 -0
  66. data/spec/support/unit/change_value.rb +111 -0
  67. data/spec/support/unit/create_model_arguments/basic.rb +135 -0
  68. data/spec/support/unit/create_model_arguments/has_many.rb +15 -0
  69. data/spec/support/unit/create_model_arguments/uniqueness_matcher.rb +74 -0
  70. data/spec/support/unit/helpers/active_record_versions.rb +1 -1
  71. data/spec/support/unit/helpers/class_builder.rb +61 -47
  72. data/spec/support/unit/helpers/database_helpers.rb +5 -3
  73. data/spec/support/unit/helpers/model_builder.rb +77 -97
  74. data/spec/support/unit/helpers/validation_matcher_scenario_helpers.rb +44 -0
  75. data/spec/support/unit/load_environment.rb +12 -0
  76. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +2 -2
  77. data/spec/support/unit/matchers/fail_with_message_matcher.rb +12 -1
  78. data/spec/support/unit/model_creation_strategies/active_model.rb +111 -0
  79. data/spec/support/unit/model_creation_strategies/active_record.rb +77 -0
  80. data/spec/support/unit/model_creators.rb +19 -0
  81. data/spec/support/unit/model_creators/active_model.rb +39 -0
  82. data/spec/support/unit/model_creators/active_record.rb +43 -0
  83. data/spec/support/unit/model_creators/active_record/has_and_belongs_to_many.rb +95 -0
  84. data/spec/support/unit/model_creators/active_record/has_many.rb +67 -0
  85. data/spec/support/unit/model_creators/active_record/uniqueness_matcher.rb +42 -0
  86. data/spec/support/unit/model_creators/basic.rb +97 -0
  87. data/spec/support/unit/rails_application.rb +1 -1
  88. data/spec/support/unit/record_validating_confirmation_builder.rb +3 -7
  89. data/spec/support/unit/shared_examples/ignoring_interference_by_writer.rb +79 -0
  90. data/spec/support/unit/validation_matcher_scenario.rb +62 -0
  91. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +4 -0
  92. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +575 -140
  93. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +115 -15
  94. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +42 -4
  95. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +92 -6
  96. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +122 -10
  97. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +306 -58
  98. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +122 -3
  99. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +805 -131
  100. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +196 -29
  101. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +82 -40
  102. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +600 -101
  103. data/spec/unit/shoulda/matchers/util/word_wrap_spec.rb +88 -33
  104. data/spec/unit_spec_helper.rb +10 -22
  105. data/zeus.json +11 -0
  106. metadata +64 -23
  107. data/lib/shoulda/matchers/active_model/strict_validator.rb +0 -51
  108. data/spec/support/unit/shared_examples/numerical_type_submatcher.rb +0 -15
  109. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +0 -288
  110. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +0 -100
  111. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +0 -100
  112. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +0 -100
@@ -1,51 +0,0 @@
1
- module Shoulda
2
- module Matchers
3
- module ActiveModel
4
- # @private
5
- module StrictValidator
6
- def allow_description(allowed_values)
7
- "doesn't raise when #{attribute} is set to #{allowed_values}"
8
- end
9
-
10
- def expected_message_from(attribute_message)
11
- "#{human_attribute_name} #{attribute_message}"
12
- end
13
-
14
- def formatted_messages
15
- [messages.first.message]
16
- end
17
-
18
- def messages_description
19
- if has_messages?
20
- ': ' + messages.first.message.inspect
21
- else
22
- ' no exception'
23
- end
24
- end
25
-
26
- def expected_messages_description(expected_message)
27
- if expected_message
28
- "exception to include #{expected_message.inspect}"
29
- else
30
- 'an exception to have been raised'
31
- end
32
- end
33
-
34
- protected
35
-
36
- def collect_messages
37
- validation_exceptions
38
- end
39
-
40
- private
41
-
42
- def validation_exceptions
43
- record.valid?(context)
44
- []
45
- rescue ::ActiveModel::StrictValidationFailed => exception
46
- [exception]
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,15 +0,0 @@
1
- shared_examples 'a numerical type submatcher' do
2
- it 'implements the allowed_type method' do
3
- expect(subject).to respond_to(:allowed_type).with(0).arguments
4
- expect { subject.allowed_type }.not_to raise_error
5
- end
6
-
7
- it 'implements the diff_to_compare' do
8
- expect(subject).to respond_to(:diff_to_compare).with(0).arguments
9
- expect { subject.diff_to_compare }.not_to raise_error
10
- end
11
-
12
- it 'returns itself when given a message' do
13
- expect(subject.with_message('some message')).to eq subject
14
- end
15
- end
@@ -1,288 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher do
4
- it_behaves_like 'a numerical submatcher' do
5
- subject { build_matcher }
6
- end
7
-
8
- shared_examples_for 'strict qualifier' do
9
- context 'asserting strict validation when validating strictly' do
10
- it 'accepts' do
11
- record = instance_with_validations(
12
- validation_qualifier => 1,
13
- strict: true
14
- )
15
- matcher = build_matcher(operator: operator, value: 1).strict
16
- expect(record).to matcher
17
- end
18
- end
19
-
20
- context 'asserting non-strict validation when validating strictly' do
21
- it 'rejects' do
22
- pending 'This needs to be fixed'
23
- record = instance_with_validations(
24
- validation_qualifier => 1,
25
- strict: true
26
- )
27
- matcher = build_matcher(operator: operator, value: 1)
28
- expect(record).not_to matcher
29
- end
30
- end
31
-
32
- context 'asserting strict validation when not validating strictly' do
33
- it 'rejects' do
34
- record = instance_with_validations(validation_qualifier => 1)
35
- matcher = build_matcher(operator: operator, value: 1).strict
36
- expect(record).not_to matcher
37
- end
38
- end
39
- end
40
-
41
- context 'when initialized without correct numerical matcher' do
42
- it 'raises an ArgumentError' do
43
- numericality_matcher = double
44
- expect { described_class.new(numericality_matcher, 0, :>) }.
45
- to raise_error(ArgumentError)
46
- end
47
- end
48
-
49
- describe 'is_greater_than' do
50
- include_examples 'strict qualifier'
51
-
52
- it do
53
- record = instance_with_validations(greater_than: 1.5)
54
- matcher = build_matcher(operator: :>, value: 2)
55
- expect(record).not_to matcher
56
- end
57
-
58
- it do
59
- record = instance_with_validations(greater_than: 2)
60
- matcher = build_matcher(operator: :>, value: 2)
61
- expect(record).to matcher
62
- end
63
-
64
- it do
65
- record = instance_with_validations(greater_than: 2.5)
66
- matcher = build_matcher(operator: :>, value: 2)
67
- expect(record).not_to matcher
68
- end
69
-
70
- it do
71
- record = instance_without_validations
72
- matcher = build_matcher(operator: :>, value: 2)
73
- expect(record).not_to matcher
74
- end
75
-
76
- def operator
77
- :>
78
- end
79
-
80
- def validation_qualifier
81
- :greater_than
82
- end
83
- end
84
-
85
- describe 'is_greater_than_or_equal_to' do
86
- include_examples 'strict qualifier'
87
-
88
- it do
89
- record = instance_with_validations(greater_than_or_equal_to: 1.5)
90
- matcher = build_matcher(operator: :>=, value: 2)
91
- expect(record).not_to matcher
92
- end
93
-
94
- it do
95
- record = instance_with_validations(greater_than_or_equal_to: 2)
96
- matcher = build_matcher(operator: :>=, value: 2)
97
- expect(record).to matcher
98
- end
99
-
100
- it do
101
- record = instance_with_validations(greater_than_or_equal_to: 2.5)
102
- matcher = build_matcher(operator: :>=, value: 2)
103
- expect(record).not_to matcher
104
- end
105
-
106
- it do
107
- record = instance_without_validations
108
- matcher = build_matcher(operator: :>=, value: 2)
109
- expect(record).not_to matcher
110
- end
111
-
112
- def operator
113
- :>=
114
- end
115
-
116
- def validation_qualifier
117
- :greater_than_or_equal_to
118
- end
119
- end
120
-
121
- describe 'is_less_than' do
122
- include_examples 'strict qualifier'
123
-
124
- it do
125
- record = instance_with_validations(less_than: 1.5)
126
- matcher = build_matcher(operator: :<, value: 2)
127
- expect(record).not_to matcher
128
- end
129
-
130
- it do
131
- record = instance_with_validations(less_than: 2)
132
- matcher = build_matcher(operator: :<, value: 2)
133
- expect(record).to matcher
134
- end
135
-
136
- it do
137
- record = instance_with_validations(less_than: 2.5)
138
- matcher = build_matcher(operator: :<, value: 2)
139
- expect(record).not_to matcher
140
- end
141
-
142
- it do
143
- record = instance_without_validations
144
- matcher = build_matcher(operator: :<, value: 2)
145
- expect(record).not_to matcher
146
- end
147
-
148
- def operator
149
- :<
150
- end
151
-
152
- def validation_qualifier
153
- :less_than
154
- end
155
- end
156
-
157
- describe 'is_less_than_or_equal_to' do
158
- include_examples 'strict qualifier'
159
-
160
- it do
161
- record = instance_with_validations(less_than_or_equal_to: 1.5)
162
- matcher = build_matcher(operator: :<=, value: 2)
163
- expect(record).not_to matcher
164
- end
165
-
166
- it do
167
- record = instance_with_validations(less_than_or_equal_to: 2)
168
- matcher = build_matcher(operator: :<=, value: 2)
169
- expect(record).to matcher
170
- end
171
-
172
- it do
173
- record = instance_with_validations(less_than_or_equal_to: 2.5)
174
- matcher = build_matcher(operator: :<=, value: 2)
175
- expect(record).not_to matcher
176
- end
177
-
178
- it do
179
- record = instance_without_validations
180
- matcher = build_matcher(operator: :<=, value: 2)
181
- expect(record).not_to matcher
182
- end
183
-
184
- def operator
185
- :<=
186
- end
187
-
188
- def validation_qualifier
189
- :less_than_or_equal_to
190
- end
191
- end
192
-
193
- describe 'is_equal_to' do
194
- include_examples 'strict qualifier'
195
-
196
- it do
197
- record = instance_with_validations(equal_to: 1.5)
198
- matcher = build_matcher(operator: :==, value: 2)
199
- expect(record).not_to matcher
200
- end
201
-
202
- it do
203
- record = instance_with_validations(equal_to: 2)
204
- matcher = build_matcher(operator: :==, value: 2)
205
- expect(record).to matcher
206
- end
207
-
208
- it do
209
- record = instance_with_validations(equal_to: 2.5)
210
- matcher = build_matcher(operator: :==, value: 2)
211
- expect(record).not_to matcher
212
- end
213
-
214
- it do
215
- record = instance_without_validations
216
- matcher = build_matcher(operator: :==, value: 2)
217
- expect(record).not_to matcher
218
- end
219
-
220
- def operator
221
- :==
222
- end
223
-
224
- def validation_qualifier
225
- :equal_to
226
- end
227
- end
228
-
229
- describe 'with_message' do
230
- it 'verifies the message for the validation' do
231
- instance = instance_with_validations(equal_to: 0, message: 'Must be zero')
232
- matcher = build_matcher.with_message('Must be zero')
233
- expect(instance).to matcher
234
- end
235
- end
236
-
237
- describe '#comparison_description' do
238
- tests = [
239
- { operator: :>, value: 0, expectation: 'greater than 0' },
240
- { operator: :>=, value: -1.0, expectation: 'greater than or equal to -1.0' },
241
- { operator: :==, value: 2.2, expectation: 'equal to 2.2' },
242
- { operator: :<, value: -3, expectation: 'less than -3' },
243
- { operator: :<=, value: 4, expectation: 'less than or equal to 4' },
244
- ]
245
-
246
- tests.each do |test|
247
- context "with :#{test[:operator]} as operator and #{test[:value]} as value" do
248
- it do
249
- matcher = build_matcher(operator: test[:operator], value: test[:value])
250
- expect(matcher.comparison_description).to eq test[:expectation]
251
- end
252
- end
253
- end
254
- end
255
-
256
- def model_with_validations(options = {})
257
- define_model :example, attribute_name => :string do |model|
258
- model.validates_numericality_of(attribute_name, options)
259
- model.attr_accessible(attribute_name)
260
- end
261
- end
262
-
263
- def instance_with_validations(options = {})
264
- model_with_validations(options).new(attribute_name => '1')
265
- end
266
-
267
- def model_without_validations
268
- define_model :example, attribute_name => :string do |model|
269
- model.attr_accessible(attribute_name)
270
- end
271
- end
272
-
273
- def instance_without_validations
274
- model_without_validations.new
275
- end
276
-
277
- def attribute_name
278
- :attr
279
- end
280
-
281
- def build_matcher(operator: :==, value: 0)
282
- described_class.new(numericality_matcher, value, operator).for(attribute_name)
283
- end
284
-
285
- def numericality_matcher
286
- double(diff_to_compare: 1, given_numeric_column?: nil)
287
- end
288
- end
@@ -1,100 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::EvenNumberMatcher do
4
- subject { described_class.new(numericality_matcher, :attr) }
5
-
6
- it_behaves_like 'a numerical submatcher'
7
- it_behaves_like 'a numerical type submatcher'
8
-
9
- it 'allows even number' do
10
- expect(subject.allowed_type).to eq 'even numbers'
11
- end
12
-
13
- describe '#diff_to_compare' do
14
- it { expect(subject.diff_to_compare).to eq 2 }
15
- end
16
-
17
- context 'when the model has an even validation' do
18
- it 'matches' do
19
- match = subject
20
- expect(validating_even_number).to match
21
- end
22
- end
23
-
24
- context 'when the model does not have an even validation' do
25
- it 'does not match' do
26
- match = subject
27
- expect(not_validating_even_number).not_to match
28
- end
29
-
30
- it 'fails with the ActiveRecord :even message' do
31
- match = subject
32
- expect {
33
- expect(not_validating_even_number).to match
34
- }.to fail_with_message_including('Expected errors to include "must be even"')
35
- end
36
- end
37
-
38
- context 'with custom validation message' do
39
- it 'only accepts even number values for that attribute with that message' do
40
- expect(validating_even_number(message: 'custom')).to subject.with_message(/custom/)
41
- end
42
-
43
- it 'fails even number values for that attribute with another message' do
44
- expect(validating_even_number(message: 'custom')).not_to subject.with_message(/wrong/)
45
- end
46
- end
47
-
48
- context 'asserting strict validation when validating strictly' do
49
- it 'accepts' do
50
- expect(validating_even_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_even_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_even_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_even_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_even_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_even_number(on: :customizable)).
83
- not_to subject
84
- end
85
- end
86
-
87
- def numericality_matcher
88
- double(:numericality_matcher, given_numeric_column?: nil)
89
- end
90
-
91
- def validating_even_number(options = {})
92
- define_model :example, attr: :string do
93
- validates_numericality_of :attr, { even: true }.merge(options)
94
- end.new
95
- end
96
-
97
- def not_validating_even_number
98
- define_model(:example, attr: :string).new
99
- end
100
- end