shoulda-matchers 6.0.0 → 6.2.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.
- checksums.yaml +4 -4
- data/README.md +18 -9
- data/lib/shoulda/matchers/action_controller/permit_matcher.rb +6 -8
- data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +13 -15
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +37 -1
- data/lib/shoulda/matchers/active_model/comparison_matcher.rb +1 -6
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +7 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +0 -5
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +0 -6
- data/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +11 -13
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +20 -8
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +9 -11
- data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +6 -7
- data/lib/shoulda/matchers/active_record/association_matcher.rb +543 -15
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +9 -1
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +1 -0
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +4 -0
- data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +23 -19
- data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +27 -23
- data/lib/shoulda/matchers/active_record/encrypt_matcher.rb +174 -0
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +10 -10
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/normalize_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/uniqueness/model.rb +1 -1
- data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +82 -70
- data/lib/shoulda/matchers/active_record.rb +1 -0
- data/lib/shoulda/matchers/doublespeak/double_collection.rb +2 -6
- data/lib/shoulda/matchers/doublespeak/world.rb +2 -6
- data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +12 -14
- data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +7 -5
- data/lib/shoulda/matchers/integrations/libraries/routing.rb +5 -3
- data/lib/shoulda/matchers/util.rb +17 -19
- data/lib/shoulda/matchers/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d549ac8f3629ad37bc56d0d09daf37416ec23d78374a8ed6a630ea23e5c9e487
|
4
|
+
data.tar.gz: f09bc94b6be181564cdde56729c2055192a4725adee4ba8b6b7f8e84429fe9a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f3ba08a6d15ad56cb583c0a8289e180854f5d89020b3182b2d6140289800d71bca467f187c9a4718ba26078cc2562f6377d77b00a0e84f2e683079d62ef60d3
|
7
|
+
data.tar.gz: 45d0141c79d9642439c9c03ffcd8e41d1aee993eafaea11fc72812456ead1dcf17d1698e9eb7f311c40945c54c77fc4e573a820ffa115fc344e9b0049ed69479
|
data/README.md
CHANGED
@@ -55,7 +55,7 @@ Start by including `shoulda-matchers` in your Gemfile:
|
|
55
55
|
|
56
56
|
```ruby
|
57
57
|
group :test do
|
58
|
-
gem 'shoulda-matchers', '~>
|
58
|
+
gem 'shoulda-matchers', '~> 6.0'
|
59
59
|
end
|
60
60
|
```
|
61
61
|
|
@@ -117,7 +117,7 @@ Otherwise, add `shoulda-matchers` to your Gemfile:
|
|
117
117
|
|
118
118
|
```ruby
|
119
119
|
group :test do
|
120
|
-
gem 'shoulda-matchers', '~>
|
120
|
+
gem 'shoulda-matchers', '~> 6.0'
|
121
121
|
end
|
122
122
|
```
|
123
123
|
|
@@ -385,8 +385,10 @@ about any of them, make sure to [consult the documentation][rubydocs]!
|
|
385
385
|
tests your `belongs_to` associations.
|
386
386
|
* **[define_enum_for](lib/shoulda/matchers/active_record/define_enum_for_matcher.rb)**
|
387
387
|
tests usage of the `enum` macro.
|
388
|
-
* **[have_and_belong_to_many](lib/shoulda/matchers/active_record/association_matcher.rb
|
388
|
+
* **[have_and_belong_to_many](lib/shoulda/matchers/active_record/association_matcher.rb)**
|
389
389
|
tests your `has_and_belongs_to_many` associations.
|
390
|
+
* **[have_delegated_type](lib/shoulda/matchers/active_record/association_matcher.rb#L687)**
|
391
|
+
tests usage of the `delegated_type` macro.
|
390
392
|
* **[have_db_column](lib/shoulda/matchers/active_record/have_db_column_matcher.rb)**
|
391
393
|
tests that the table that backs your model has a specific column.
|
392
394
|
* **[have_db_index](lib/shoulda/matchers/active_record/have_db_index_matcher.rb)**
|
@@ -411,6 +413,8 @@ about any of them, make sure to [consult the documentation][rubydocs]!
|
|
411
413
|
tests usage of `validates_uniqueness_of`.
|
412
414
|
* **[normalize](lib/shoulda/matchers/active_record/normalize_matcher.rb)** tests
|
413
415
|
usage of the `normalize` macro
|
416
|
+
* **[encrypt](lib/shoulda/matchers/active_record/encrypt_matcher.rb)**
|
417
|
+
tests usage of the `encrypts` macro.
|
414
418
|
|
415
419
|
### ActionController matchers
|
416
420
|
|
@@ -513,16 +517,21 @@ redistributed under the terms specified in the [LICENSE](LICENSE) file.
|
|
513
517
|
|
514
518
|
[thoughtbot-website]: https://thoughtbot.com
|
515
519
|
|
520
|
+
<!-- START /templates/footer.md -->
|
516
521
|
## About thoughtbot
|
517
522
|
|
518
|
-
![thoughtbot]
|
519
|
-
|
520
|
-
[thoughtbot-logo]: https://thoughtbot.com/brand_assets/93:44.svg
|
523
|
+

|
521
524
|
|
525
|
+
This repo is maintained and funded by thoughtbot, inc.
|
522
526
|
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
523
527
|
|
524
|
-
We
|
525
|
-
|
528
|
+
We love open source software!
|
529
|
+
See [our other projects][community].
|
530
|
+
|
531
|
+
We are [available for hire][hire].
|
526
532
|
|
527
533
|
[community]: https://thoughtbot.com/community?utm_source=github
|
528
|
-
[hire]: https://thoughtbot.com?utm_source=github
|
534
|
+
[hire]: https://thoughtbot.com/hire-us?utm_source=github
|
535
|
+
|
536
|
+
|
537
|
+
<!-- END /templates/footer.md -->
|
@@ -276,16 +276,14 @@ module Shoulda
|
|
276
276
|
:context, :subparameter_name, :parameters_double_registry
|
277
277
|
|
278
278
|
def expectation
|
279
|
-
|
279
|
+
String.new('restrict parameters ').tap do |message|
|
280
|
+
if subparameter_name
|
281
|
+
message << "on #{subparameter_name.inspect} "
|
282
|
+
end
|
280
283
|
|
281
|
-
|
282
|
-
|
284
|
+
message << 'to '\
|
285
|
+
"#{format_parameter_names(expected_permitted_parameter_names)}"
|
283
286
|
end
|
284
|
-
|
285
|
-
message << 'to '\
|
286
|
-
"#{format_parameter_names(expected_permitted_parameter_names)}"
|
287
|
-
|
288
|
-
message
|
289
287
|
end
|
290
288
|
|
291
289
|
def reality
|
@@ -83,25 +83,23 @@ module Shoulda
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def expectation_description
|
86
|
-
|
87
|
-
|
88
|
-
string <<
|
89
|
-
if key_set?
|
90
|
-
" #{store.name}[#{key.inspect}]"
|
91
|
-
else
|
92
|
-
" any key in #{store.name}"
|
93
|
-
end
|
94
|
-
|
95
|
-
if expected_value_set?
|
86
|
+
String.new('set').tap do |string|
|
96
87
|
string <<
|
97
|
-
if
|
98
|
-
"
|
88
|
+
if key_set?
|
89
|
+
" #{store.name}[#{key.inspect}]"
|
99
90
|
else
|
100
|
-
"
|
91
|
+
" any key in #{store.name}"
|
101
92
|
end
|
102
|
-
end
|
103
93
|
|
104
|
-
|
94
|
+
if expected_value_set?
|
95
|
+
string <<
|
96
|
+
if expected_value.is_a?(Regexp)
|
97
|
+
" to a value matching #{expected_value.inspect}"
|
98
|
+
else
|
99
|
+
" to #{expected_value.inspect}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
105
103
|
end
|
106
104
|
end
|
107
105
|
end
|
@@ -169,6 +169,36 @@ module Shoulda
|
|
169
169
|
# on(:create)
|
170
170
|
# end
|
171
171
|
#
|
172
|
+
# ##### against
|
173
|
+
#
|
174
|
+
# Use `against` if the validation is on an attribute
|
175
|
+
# other than the attribute being validated:
|
176
|
+
#
|
177
|
+
# class UserProfile
|
178
|
+
# include ActiveModel::Model
|
179
|
+
# attr_accessor :website_url
|
180
|
+
#
|
181
|
+
# alias_attribute :url, :website_url
|
182
|
+
#
|
183
|
+
# validates_format_of :url, with: URI.regexp
|
184
|
+
# end
|
185
|
+
#
|
186
|
+
# # RSpec
|
187
|
+
# RSpec.describe UserProfile, type: :model do
|
188
|
+
# it do
|
189
|
+
# should allow_value('https://foo.com').
|
190
|
+
# for(:website_url).
|
191
|
+
# against(:url)
|
192
|
+
# end
|
193
|
+
# end
|
194
|
+
#
|
195
|
+
# # Minitest (Shoulda)
|
196
|
+
# class UserProfileTest < ActiveSupport::TestCase
|
197
|
+
# should allow_value('https://foo.com').
|
198
|
+
# for(:website_url).
|
199
|
+
# against(:url)
|
200
|
+
# end
|
201
|
+
#
|
172
202
|
# ##### with_message
|
173
203
|
#
|
174
204
|
# Use `with_message` if you are using a custom validation message.
|
@@ -349,6 +379,12 @@ module Shoulda
|
|
349
379
|
self
|
350
380
|
end
|
351
381
|
|
382
|
+
def against(attribute)
|
383
|
+
@attribute_to_check_message_against = attribute if attribute.present?
|
384
|
+
|
385
|
+
self
|
386
|
+
end
|
387
|
+
|
352
388
|
def with_message(message, given_options = {})
|
353
389
|
if message.present?
|
354
390
|
@expects_custom_validation_message = true
|
@@ -550,7 +586,7 @@ module Shoulda
|
|
550
586
|
end
|
551
587
|
|
552
588
|
def default_failure_message_preface
|
553
|
-
|
589
|
+
String.new.tap do |preface|
|
554
590
|
if descriptions_for_preset_values.any?
|
555
591
|
preface << 'After setting '
|
556
592
|
preface << descriptions_for_preset_values.to_sentence
|
@@ -50,7 +50,7 @@ module Shoulda
|
|
50
50
|
description = ''
|
51
51
|
|
52
52
|
if expects_strict?
|
53
|
-
description
|
53
|
+
description = ' strictly'
|
54
54
|
end
|
55
55
|
|
56
56
|
description +
|
@@ -78,11 +78,6 @@ module Shoulda
|
|
78
78
|
comparison_submatchers.matches?(subject)
|
79
79
|
end
|
80
80
|
|
81
|
-
def does_not_match?(subject)
|
82
|
-
@subject = subject
|
83
|
-
comparison_submatchers.does_not_match?(subject)
|
84
|
-
end
|
85
|
-
|
86
81
|
def comparison_description
|
87
82
|
"#{comparison_expectation} #{@value}"
|
88
83
|
end
|
@@ -47,6 +47,8 @@ module Shoulda
|
|
47
47
|
did_not_authenticate_correct_password: 'expected %{subject} to'\
|
48
48
|
' authenticate the correct %{attribute}',
|
49
49
|
method_not_found: 'expected %{subject} to respond to %{methods}',
|
50
|
+
should_not_have_secure_password: 'expected %{subject} to'\
|
51
|
+
' not %{description}!',
|
50
52
|
}.freeze
|
51
53
|
|
52
54
|
def initialize(attribute)
|
@@ -69,6 +71,11 @@ module Shoulda
|
|
69
71
|
failure.nil?
|
70
72
|
end
|
71
73
|
|
74
|
+
def failure_message_when_negated
|
75
|
+
MESSAGES[:should_not_have_secure_password] %
|
76
|
+
{ subject: @subject.class, description: description }
|
77
|
+
end
|
78
|
+
|
72
79
|
protected
|
73
80
|
|
74
81
|
attr_reader :subject
|
@@ -143,12 +143,6 @@ module Shoulda
|
|
143
143
|
@subject.class.reflect_on_association(@attribute)
|
144
144
|
end
|
145
145
|
|
146
|
-
def array_column?
|
147
|
-
@subject.class.respond_to?(:columns_hash) &&
|
148
|
-
@subject.class.columns_hash[@attribute.to_s].respond_to?(:array) &&
|
149
|
-
@subject.class.columns_hash[@attribute.to_s].array
|
150
|
-
end
|
151
|
-
|
152
146
|
def enum_column?
|
153
147
|
@subject.class.respond_to?(:defined_enums) &&
|
154
148
|
@subject.class.defined_enums.key?(@attribute.to_s)
|
@@ -13,12 +13,12 @@ module Shoulda
|
|
13
13
|
#
|
14
14
|
# # RSpec
|
15
15
|
# RSpec.describe Person, type: :model do
|
16
|
-
# it { should validate_comparison_of(:gpa).
|
16
|
+
# it { should validate_comparison_of(:gpa).is_greater_than(10) }
|
17
17
|
# end
|
18
18
|
#
|
19
19
|
# # Minitest (Shoulda)
|
20
20
|
# class PersonTest < ActiveSupport::TestCase
|
21
|
-
# should validate_comparison_of(:gpa).
|
21
|
+
# should validate_comparison_of(:gpa).is_greater_than(10)
|
22
22
|
# end
|
23
23
|
#
|
24
24
|
# #### Qualifiers
|
@@ -39,14 +39,14 @@ module Shoulda
|
|
39
39
|
# RSpec.describe Person, type: :model do
|
40
40
|
# it do
|
41
41
|
# should validate_comparison_of(:number_of_dependents).
|
42
|
-
#
|
42
|
+
# is_greater_than(0).
|
43
43
|
# on(:create)
|
44
44
|
# end
|
45
45
|
# end
|
46
46
|
#
|
47
47
|
# # Minitest (Shoulda)
|
48
48
|
# class PersonTest < ActiveSupport::TestCase
|
49
|
-
# should validate_comparison_of(:number_of_dependents).
|
49
|
+
# should validate_comparison_of(:number_of_dependents).is_greater_than(0).on(:create)
|
50
50
|
# end
|
51
51
|
#
|
52
52
|
# ##### is_less_than
|
@@ -353,16 +353,14 @@ module Shoulda
|
|
353
353
|
end
|
354
354
|
|
355
355
|
def simple_description
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
description << Shoulda::Matchers::Util.a_or_an(allowed_type_name)
|
356
|
+
String.new.tap do |description|
|
357
|
+
description << "validate that :#{attribute} looks like "
|
358
|
+
description << Shoulda::Matchers::Util.a_or_an(allowed_type_name)
|
360
359
|
|
361
|
-
|
362
|
-
|
360
|
+
if comparison_descriptions.present?
|
361
|
+
description << " #{comparison_descriptions}"
|
362
|
+
end
|
363
363
|
end
|
364
|
-
|
365
|
-
description
|
366
364
|
end
|
367
365
|
|
368
366
|
def failure_message
|
@@ -465,7 +463,7 @@ module Shoulda
|
|
465
463
|
def first_submatcher_that_fails_to_not_match
|
466
464
|
@_first_submatcher_that_fails_to_not_match ||=
|
467
465
|
@submatchers.detect do |submatcher|
|
468
|
-
|
466
|
+
submatcher.matches?(subject)
|
469
467
|
end
|
470
468
|
end
|
471
469
|
|
@@ -309,8 +309,8 @@ EOT
|
|
309
309
|
|
310
310
|
def in_range(range)
|
311
311
|
@range = range
|
312
|
-
@minimum =
|
313
|
-
@maximum =
|
312
|
+
@minimum = minimum_range_value
|
313
|
+
@maximum = maximum_range_value
|
314
314
|
self
|
315
315
|
end
|
316
316
|
|
@@ -400,6 +400,18 @@ EOT
|
|
400
400
|
|
401
401
|
private
|
402
402
|
|
403
|
+
def minimum_range_value
|
404
|
+
@range.begin
|
405
|
+
end
|
406
|
+
|
407
|
+
def maximum_range_value
|
408
|
+
if @range.exclude_end?
|
409
|
+
@range.end ? (@range.end - 1) : nil
|
410
|
+
else
|
411
|
+
@range.end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
403
415
|
def matches_for_range?
|
404
416
|
disallows_lower_value &&
|
405
417
|
allows_minimum_value &&
|
@@ -441,27 +453,27 @@ EOT
|
|
441
453
|
end
|
442
454
|
|
443
455
|
def allows_minimum_value
|
444
|
-
allows_value_of(@minimum, @low_message)
|
456
|
+
@minimum.nil? || allows_value_of(@minimum, @low_message)
|
445
457
|
end
|
446
458
|
|
447
459
|
def disallows_minimum_value
|
448
|
-
disallows_value_of(@minimum, @low_message)
|
460
|
+
@minimum.nil? || disallows_value_of(@minimum, @low_message)
|
449
461
|
end
|
450
462
|
|
451
463
|
def allows_maximum_value
|
452
|
-
allows_value_of(@maximum, @high_message)
|
464
|
+
@maximum.nil? || allows_value_of(@maximum, @high_message)
|
453
465
|
end
|
454
466
|
|
455
467
|
def disallows_maximum_value
|
456
|
-
disallows_value_of(@maximum, @high_message)
|
468
|
+
@maximum.nil? || disallows_value_of(@maximum, @high_message)
|
457
469
|
end
|
458
470
|
|
459
471
|
def allows_higher_value
|
460
|
-
allows_value_of(@maximum + 1, @high_message)
|
472
|
+
@maximum.nil? || allows_value_of(@maximum + 1, @high_message)
|
461
473
|
end
|
462
474
|
|
463
475
|
def disallows_higher_value
|
464
|
-
disallows_value_of(@maximum + 1, @high_message)
|
476
|
+
@maximum.nil? || disallows_value_of(@maximum + 1, @high_message)
|
465
477
|
end
|
466
478
|
|
467
479
|
def allows_all_values_in_array?
|
@@ -453,20 +453,18 @@ module Shoulda
|
|
453
453
|
end
|
454
454
|
|
455
455
|
def simple_description
|
456
|
-
|
456
|
+
String.new.tap do |description|
|
457
|
+
description << "validate that :#{attribute} looks like "
|
458
|
+
description << Shoulda::Matchers::Util.a_or_an(full_allowed_type)
|
457
459
|
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
if range_description.present?
|
462
|
-
description << " #{range_description}"
|
463
|
-
end
|
460
|
+
if range_description.present?
|
461
|
+
description << " #{range_description}"
|
462
|
+
end
|
464
463
|
|
465
|
-
|
466
|
-
|
464
|
+
if comparison_descriptions.present?
|
465
|
+
description << " #{comparison_descriptions}"
|
466
|
+
end
|
467
467
|
end
|
468
|
-
|
469
|
-
description
|
470
468
|
end
|
471
469
|
|
472
470
|
def failure_message
|
@@ -42,13 +42,12 @@ module Shoulda
|
|
42
42
|
description_clauses = []
|
43
43
|
|
44
44
|
if matcher.try(:expects_strict?)
|
45
|
-
description_clauses <<
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
description_clauses.last << ' on failure'
|
45
|
+
description_clauses <<
|
46
|
+
if matcher.try(:expects_custom_validation_message?)
|
47
|
+
'raising a validation exception with a custom message on failure'
|
48
|
+
else
|
49
|
+
'raising a validation exception on failure'
|
50
|
+
end
|
52
51
|
elsif matcher.try(:expects_custom_validation_message?)
|
53
52
|
description_clauses <<
|
54
53
|
'producing a custom validation error on failure'
|