shoulda-matchers 4.5.1 → 5.3.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/LICENSE +1 -1
- data/README.md +15 -13
- data/lib/shoulda/matchers/action_controller/callback_matcher.rb +0 -87
- data/lib/shoulda/matchers/action_controller/flash_store.rb +2 -4
- data/lib/shoulda/matchers/action_controller/permit_matcher.rb +3 -6
- data/lib/shoulda/matchers/active_model/helpers.rb +1 -1
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +13 -34
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +3 -5
- data/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +71 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +43 -0
- data/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
- data/lib/shoulda/matchers/active_model/qualifiers.rb +1 -0
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +14 -2
- data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +6 -4
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +47 -1
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +31 -6
- data/lib/shoulda/matchers/active_model/validator.rb +1 -6
- data/lib/shoulda/matchers/active_model.rb +2 -1
- data/lib/shoulda/matchers/active_record/association_matcher.rb +20 -22
- data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +125 -22
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +21 -3
- data/lib/shoulda/matchers/rails_shim.rb +14 -39
- data/lib/shoulda/matchers/util/word_wrap.rb +2 -2
- data/lib/shoulda/matchers/version.rb +1 -1
- data/shoulda-matchers.gemspec +3 -3
- metadata +10 -8
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +0 -161
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d083d22f49f99bf60d6c6bdfed7ea08ea1f838a90b4aed439d84108ebc814af9
|
4
|
+
data.tar.gz: 90cc8440d8c63da1c338306b3d9f129cc9af8dc1a80277d9e7f5b233f2bbe115
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09b1dcf7e19179b50992d34cf73a86e72727cf27a1db911f2adb98fe291dc4d3d711da962d3efdbec60d2b1f280dcecd441e725a7e6a701a152ff60fdd8e340c'
|
7
|
+
data.tar.gz: 8ba54626246e133cfd86b84aba3d3b05487166d6359b2ba97256af242a057b5ff6cd40d5eae35bd35f619c9a9b0f39cc2c8b6508e299b44e2605e3cdf4f64078
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
# Shoulda Matchers [![Gem Version][version-badge]][rubygems] [![Build Status][
|
1
|
+
# Shoulda Matchers [![Gem Version][version-badge]][rubygems] [![Build Status][github-actions-badge]][github-actions] [![Total Downloads][downloads-total]][rubygems] [![Downloads][downloads-badge]][rubygems]
|
2
2
|
|
3
3
|
[version-badge]: https://img.shields.io/gem/v/shoulda-matchers.svg
|
4
4
|
[rubygems]: https://rubygems.org/gems/shoulda-matchers
|
5
|
-
[
|
6
|
-
[
|
5
|
+
[github-actions-badge]: https://img.shields.io/github/workflow/status/thoughtbot/shoulda-matchers/Test
|
6
|
+
[github-actions]: https://github.com/thoughtbot/shoulda-matchers/actions
|
7
7
|
[downloads-total]: https://img.shields.io/gem/dt/shoulda-matchers.svg
|
8
8
|
[downloads-badge]: https://img.shields.io/gem/dtv/shoulda-matchers.svg
|
9
9
|
[downloads-badge]: https://img.shields.io/gem/dtv/shoulda-matchers.svg
|
@@ -19,7 +19,7 @@ complex, and error-prone.
|
|
19
19
|
|
20
20
|
## Quick links
|
21
21
|
|
22
|
-
📖 **[Read the documentation for the latest version][rubydocs].**
|
22
|
+
📖 **[Read the documentation for the latest version][rubydocs].**
|
23
23
|
📢 **[See what's changed in recent versions][changelog].**
|
24
24
|
|
25
25
|
[rubydocs]: https://matchers.shoulda.io/docs
|
@@ -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', '~> 5.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', '~> 5.0'
|
121
121
|
end
|
122
122
|
```
|
123
123
|
|
@@ -430,11 +430,11 @@ about any of them, make sure to [consult the documentation][rubydocs]!
|
|
430
430
|
makes assertions on the `session` hash.
|
431
431
|
* **[set_flash](lib/shoulda/matchers/action_controller/set_flash_matcher.rb)**
|
432
432
|
makes assertions on the `flash` hash.
|
433
|
-
* **[use_after_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#
|
433
|
+
* **[use_after_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#L29)**
|
434
434
|
tests that an `after_action` callback is defined in your controller.
|
435
|
-
* **[use_around_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#
|
435
|
+
* **[use_around_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#L75)**
|
436
436
|
tests that an `around_action` callback is defined in your controller.
|
437
|
-
* **[use_before_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#
|
437
|
+
* **[use_before_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#L4)**
|
438
438
|
tests that a `before_action` callback is defined in your controller.
|
439
439
|
|
440
440
|
### Routing matchers
|
@@ -468,12 +468,14 @@ machine, understanding the codebase, and creating a good pull request.
|
|
468
468
|
|
469
469
|
## Compatibility
|
470
470
|
|
471
|
-
Shoulda Matchers is
|
472
|
-
|
471
|
+
Shoulda Matchers is tested and supported against Ruby 2.6+, Rails
|
472
|
+
5.2+, RSpec 3.x, and Minitest 5.x.
|
473
473
|
|
474
|
-
For Ruby < 2.4 and Rails < 4.1 compatibility, please use [v3.1.3][v3.1.3].
|
474
|
+
- For Ruby < 2.4 and Rails < 4.1 compatibility, please use [v3.1.3][v3.1.3].
|
475
|
+
- For Ruby < 3.0 and Rails < 6.1 compatibility, please use [v4.5.1][v4.5.1].
|
475
476
|
|
476
477
|
[v3.1.3]: https://github.com/thoughtbot/shoulda-matchers/tree/v3.1.3
|
478
|
+
[v4.5.1]: https://github.com/thoughtbot/shoulda-matchers/tree/v4.5.1
|
477
479
|
|
478
480
|
## Versioning
|
479
481
|
|
@@ -490,7 +492,7 @@ Albuk][guialbuk].
|
|
490
492
|
|
491
493
|
## Copyright/License
|
492
494
|
|
493
|
-
Shoulda Matchers is copyright © 2006-
|
495
|
+
Shoulda Matchers is copyright © 2006-2022 Tammer Saleh and [thoughtbot,
|
494
496
|
inc][thoughtbot-website]. It is free and opensource software and may be
|
495
497
|
redistributed under the terms specified in the [LICENSE](LICENSE) file.
|
496
498
|
|
@@ -1,64 +1,6 @@
|
|
1
1
|
module Shoulda
|
2
2
|
module Matchers
|
3
3
|
module ActionController
|
4
|
-
# The `use_before_filter` matcher is used to test that a before_filter
|
5
|
-
# callback is defined within your controller.
|
6
|
-
#
|
7
|
-
# class UsersController < ApplicationController
|
8
|
-
# before_filter :authenticate_user!
|
9
|
-
# end
|
10
|
-
#
|
11
|
-
# # RSpec
|
12
|
-
# RSpec.describe UsersController, type: :controller do
|
13
|
-
# it { should use_before_filter(:authenticate_user!) }
|
14
|
-
# it { should_not use_before_filter(:prevent_ssl) }
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# # Minitest (Shoulda)
|
18
|
-
# class UsersControllerTest < ActionController::TestCase
|
19
|
-
# should use_before_filter(:authenticate_user!)
|
20
|
-
# should_not use_before_filter(:prevent_ssl)
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# @note This method is only available when using shoulda-matchers under
|
24
|
-
# Rails 4.x.
|
25
|
-
# @return [CallbackMatcher]
|
26
|
-
#
|
27
|
-
if RailsShim.action_pack_lt_5?
|
28
|
-
def use_before_filter(callback)
|
29
|
-
CallbackMatcher.new(callback, :before, :filter)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# The `use_after_filter` matcher is used to test that an after_filter
|
34
|
-
# callback is defined within your controller.
|
35
|
-
#
|
36
|
-
# class IssuesController < ApplicationController
|
37
|
-
# after_filter :log_activity
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# # RSpec
|
41
|
-
# RSpec.describe IssuesController, type: :controller do
|
42
|
-
# it { should use_after_filter(:log_activity) }
|
43
|
-
# it { should_not use_after_filter(:destroy_user) }
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# # Minitest (Shoulda)
|
47
|
-
# class IssuesControllerTest < ActionController::TestCase
|
48
|
-
# should use_after_filter(:log_activity)
|
49
|
-
# should_not use_after_filter(:destroy_user)
|
50
|
-
# end
|
51
|
-
#
|
52
|
-
# @note This method is only available when using shoulda-matchers under
|
53
|
-
# Rails 4.x.
|
54
|
-
# @return [CallbackMatcher]
|
55
|
-
#
|
56
|
-
if RailsShim.action_pack_lt_5?
|
57
|
-
def use_after_filter(callback)
|
58
|
-
CallbackMatcher.new(callback, :after, :filter)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
4
|
# The `use_before_action` matcher is used to test that a before_action
|
63
5
|
# callback is defined within your controller.
|
64
6
|
#
|
@@ -109,35 +51,6 @@ module Shoulda
|
|
109
51
|
CallbackMatcher.new(callback, :after, :action)
|
110
52
|
end
|
111
53
|
|
112
|
-
# The `use_around_filter` matcher is used to test that an around_filter
|
113
|
-
# callback is defined within your controller.
|
114
|
-
#
|
115
|
-
# class ChangesController < ApplicationController
|
116
|
-
# around_filter :wrap_in_transaction
|
117
|
-
# end
|
118
|
-
#
|
119
|
-
# # RSpec
|
120
|
-
# RSpec.describe ChangesController, type: :controller do
|
121
|
-
# it { should use_around_filter(:wrap_in_transaction) }
|
122
|
-
# it { should_not use_around_filter(:save_view_context) }
|
123
|
-
# end
|
124
|
-
#
|
125
|
-
# # Minitest (Shoulda)
|
126
|
-
# class ChangesControllerTest < ActionController::TestCase
|
127
|
-
# should use_around_filter(:wrap_in_transaction)
|
128
|
-
# should_not use_around_filter(:save_view_context)
|
129
|
-
# end
|
130
|
-
#
|
131
|
-
# @note This method is only available when using shoulda-matchers under
|
132
|
-
# Rails 4.x.
|
133
|
-
# @return [CallbackMatcher]
|
134
|
-
#
|
135
|
-
if RailsShim.action_pack_lt_5?
|
136
|
-
def use_around_filter(callback)
|
137
|
-
CallbackMatcher.new(callback, :around, :filter)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
54
|
# The `use_around_action` matcher is used to test that an around_action
|
142
55
|
# callback is defined within your controller.
|
143
56
|
#
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
1
2
|
module Shoulda
|
2
3
|
module Matchers
|
3
4
|
module ActionController
|
@@ -34,10 +35,7 @@ module Shoulda
|
|
34
35
|
expected_value === actual_value
|
35
36
|
end
|
36
37
|
end
|
37
|
-
|
38
|
-
def empty?
|
39
|
-
flash.empty?
|
40
|
-
end
|
38
|
+
delegate :empty?, to: :flash
|
41
39
|
|
42
40
|
def use_now!
|
43
41
|
@use_now = true
|
@@ -251,12 +251,9 @@ module Shoulda
|
|
251
251
|
parameters_double_registry.register
|
252
252
|
|
253
253
|
Doublespeak.with_doubles_activated do
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
action,
|
258
|
-
request_params,
|
259
|
-
)
|
254
|
+
params = { params: request_params }
|
255
|
+
|
256
|
+
context.__send__(verb, action, **params)
|
260
257
|
end
|
261
258
|
|
262
259
|
unpermitted_parameter_names.empty?
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
|
1
3
|
module Shoulda
|
2
4
|
module Matchers
|
3
5
|
module ActiveModel
|
@@ -31,6 +33,8 @@ module Shoulda
|
|
31
33
|
},
|
32
34
|
}.freeze
|
33
35
|
|
36
|
+
delegate :failure_message, :failure_message_when_negated, to: :submatchers
|
37
|
+
|
34
38
|
def initialize(numericality_matcher, value, operator)
|
35
39
|
super(nil)
|
36
40
|
unless numericality_matcher.respond_to? :diff_to_compare
|
@@ -72,49 +76,24 @@ module Shoulda
|
|
72
76
|
|
73
77
|
def matches?(subject)
|
74
78
|
@subject = subject
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
def failure_message
|
79
|
-
last_failing_submatcher.failure_message
|
80
|
-
end
|
81
|
-
|
82
|
-
def failure_message_when_negated
|
83
|
-
last_failing_submatcher.failure_message_when_negated
|
79
|
+
submatchers.matches?(subject)
|
84
80
|
end
|
85
81
|
|
86
82
|
def comparison_description
|
87
83
|
"#{comparison_expectation} #{@value}"
|
88
84
|
end
|
89
85
|
|
90
|
-
private
|
91
|
-
|
92
|
-
def all_bounds_correct?
|
93
|
-
failing_submatchers.empty?
|
94
|
-
end
|
95
|
-
|
96
|
-
def failing_submatchers
|
97
|
-
submatchers_and_results.
|
98
|
-
select { |x| !x[:matched] }.
|
99
|
-
map { |x| x[:matcher] }
|
100
|
-
end
|
101
|
-
|
102
|
-
def last_failing_submatcher
|
103
|
-
failing_submatchers.last
|
104
|
-
end
|
105
|
-
|
106
86
|
def submatchers
|
107
|
-
@_submatchers ||=
|
108
|
-
comparison_combos.map do |diff, submatcher_method_name|
|
109
|
-
matcher = __send__(submatcher_method_name, diff, nil)
|
110
|
-
matcher.with_message(@message, values: { count: @value })
|
111
|
-
matcher
|
112
|
-
end
|
87
|
+
@_submatchers ||= NumericalityMatchers::Submatchers.new(build_submatchers)
|
113
88
|
end
|
114
89
|
|
115
|
-
|
116
|
-
|
117
|
-
|
90
|
+
private
|
91
|
+
|
92
|
+
def build_submatchers
|
93
|
+
comparison_combos.map do |diff, submatcher_method_name|
|
94
|
+
matcher = __send__(submatcher_method_name, diff, nil)
|
95
|
+
matcher.with_message(@message, values: { count: @value })
|
96
|
+
matcher
|
118
97
|
end
|
119
98
|
end
|
120
99
|
|
@@ -55,11 +55,9 @@ module Shoulda
|
|
55
55
|
private
|
56
56
|
|
57
57
|
def disallow_value_matcher
|
58
|
-
@_disallow_value_matcher ||=
|
59
|
-
|
60
|
-
|
61
|
-
wrap_disallow_value_matcher(matcher)
|
62
|
-
end
|
58
|
+
@_disallow_value_matcher ||= DisallowValueMatcher.new(disallowed_value).tap do |matcher|
|
59
|
+
matcher.for(attribute)
|
60
|
+
wrap_disallow_value_matcher(matcher)
|
63
61
|
end
|
64
62
|
end
|
65
63
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
|
3
|
+
module Shoulda
|
4
|
+
module Matchers
|
5
|
+
module ActiveModel
|
6
|
+
module NumericalityMatchers
|
7
|
+
# @private
|
8
|
+
class RangeMatcher < ValidationMatcher
|
9
|
+
OPERATORS = [:>=, :<=].freeze
|
10
|
+
|
11
|
+
delegate :failure_message, to: :submatchers
|
12
|
+
|
13
|
+
def initialize(numericality_matcher, attribute, range)
|
14
|
+
super(attribute)
|
15
|
+
unless numericality_matcher.respond_to? :diff_to_compare
|
16
|
+
raise ArgumentError, 'numericality_matcher is invalid'
|
17
|
+
end
|
18
|
+
|
19
|
+
@numericality_matcher = numericality_matcher
|
20
|
+
@range = range
|
21
|
+
@attribute = attribute
|
22
|
+
end
|
23
|
+
|
24
|
+
def matches?(subject)
|
25
|
+
@subject = subject
|
26
|
+
submatchers.matches?(subject)
|
27
|
+
end
|
28
|
+
|
29
|
+
def simple_description
|
30
|
+
description = ''
|
31
|
+
|
32
|
+
if expects_strict?
|
33
|
+
description << ' strictly'
|
34
|
+
end
|
35
|
+
|
36
|
+
description +
|
37
|
+
"disallow :#{attribute} from being a number that is not " +
|
38
|
+
range_description
|
39
|
+
end
|
40
|
+
|
41
|
+
def range_description
|
42
|
+
"from #{Shoulda::Matchers::Util.inspect_range(@range)}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def submatchers
|
46
|
+
@_submatchers ||= NumericalityMatchers::Submatchers.new(build_submatchers)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def build_submatchers
|
52
|
+
submatcher_combos.map do |value, operator|
|
53
|
+
build_comparison_submatcher(value, operator)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def submatcher_combos
|
58
|
+
@range.minmax.zip(OPERATORS)
|
59
|
+
end
|
60
|
+
|
61
|
+
def build_comparison_submatcher(value, operator)
|
62
|
+
NumericalityMatchers::ComparisonMatcher.new(@numericality_matcher, value, operator).
|
63
|
+
for(@attribute).
|
64
|
+
with_message(@message).
|
65
|
+
on(@context)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel
|
4
|
+
module NumericalityMatchers
|
5
|
+
# @private
|
6
|
+
class Submatchers
|
7
|
+
def initialize(submatchers)
|
8
|
+
@submatchers = submatchers
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches?(subject)
|
12
|
+
@subject = subject
|
13
|
+
failing_submatchers.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
def failure_message
|
17
|
+
last_failing_submatcher.failure_message
|
18
|
+
end
|
19
|
+
|
20
|
+
def failure_message_when_negated
|
21
|
+
last_failing_submatcher.failure_message_when_negated
|
22
|
+
end
|
23
|
+
|
24
|
+
def add(submatcher)
|
25
|
+
@submatchers << submatcher
|
26
|
+
end
|
27
|
+
|
28
|
+
def last_failing_submatcher
|
29
|
+
failing_submatchers.last
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def failing_submatchers
|
35
|
+
@_failing_submatchers ||= @submatchers.reject do |submatcher|
|
36
|
+
submatcher.matches?(@subject)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel
|
4
|
+
module Qualifiers
|
5
|
+
# @private
|
6
|
+
module AllowBlank
|
7
|
+
def initialize(*args)
|
8
|
+
super
|
9
|
+
@expects_to_allow_blank = false
|
10
|
+
end
|
11
|
+
|
12
|
+
def allow_blank
|
13
|
+
@expects_to_allow_blank = true
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def expects_to_allow_blank?
|
20
|
+
@expects_to_allow_blank
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -108,14 +108,17 @@ module Shoulda
|
|
108
108
|
obj
|
109
109
|
end
|
110
110
|
elsif array_column?
|
111
|
-
['an
|
111
|
+
['an arbitrary value']
|
112
|
+
elsif enum_column?
|
113
|
+
enum_values.first
|
112
114
|
else
|
113
115
|
case column_type
|
114
116
|
when :integer, :float then 1
|
115
117
|
when :decimal then BigDecimal(1, 0)
|
116
|
-
when :datetime, :time, :timestamp then Time.
|
118
|
+
when :datetime, :time, :timestamp then Time.current
|
117
119
|
when :date then Date.new
|
118
120
|
when :binary then '0'
|
121
|
+
when :uuid then SecureRandom.uuid
|
119
122
|
else 'an arbitrary value'
|
120
123
|
end
|
121
124
|
end
|
@@ -145,6 +148,15 @@ module Shoulda
|
|
145
148
|
@subject.class.columns_hash[@attribute.to_s].respond_to?(:array) &&
|
146
149
|
@subject.class.columns_hash[@attribute.to_s].array
|
147
150
|
end
|
151
|
+
|
152
|
+
def enum_column?
|
153
|
+
@subject.class.respond_to?(:defined_enums) &&
|
154
|
+
@subject.class.defined_enums.key?(@attribute.to_s)
|
155
|
+
end
|
156
|
+
|
157
|
+
def enum_values
|
158
|
+
@subject.class.defined_enums[@attribute.to_s].values
|
159
|
+
end
|
148
160
|
end
|
149
161
|
end
|
150
162
|
end
|
@@ -33,9 +33,9 @@ module Shoulda
|
|
33
33
|
#
|
34
34
|
# class Game
|
35
35
|
# include ActiveModel::Model
|
36
|
-
# attr_accessor :
|
36
|
+
# attr_accessor :floors_with_enemies
|
37
37
|
#
|
38
|
-
# validates_exclusion_of :
|
38
|
+
# validates_exclusion_of :floors_with_enemies, in: 5..8
|
39
39
|
# end
|
40
40
|
#
|
41
41
|
# # RSpec
|
@@ -3,6 +3,8 @@ require 'date'
|
|
3
3
|
|
4
4
|
module Shoulda
|
5
5
|
module Matchers
|
6
|
+
class ExampleClass; end
|
7
|
+
|
6
8
|
module ActiveModel
|
7
9
|
# The `validate_inclusion_of` matcher tests usage of the
|
8
10
|
# `validates_inclusion_of` validation, asserting that an attribute can
|
@@ -43,12 +45,12 @@ module Shoulda
|
|
43
45
|
#
|
44
46
|
# # RSpec
|
45
47
|
# RSpec.describe Issue, type: :model do
|
46
|
-
# it { should validate_inclusion_of(:
|
48
|
+
# it { should validate_inclusion_of(:priority).in_range(1..5) }
|
47
49
|
# end
|
48
50
|
#
|
49
51
|
# # Minitest (Shoulda)
|
50
52
|
# class IssueTest < ActiveSupport::TestCase
|
51
|
-
# should validate_inclusion_of(:
|
53
|
+
# should validate_inclusion_of(:priority).in_range(1..5)
|
52
54
|
# end
|
53
55
|
#
|
54
56
|
# #### Caveats
|
@@ -269,7 +271,7 @@ module Shoulda
|
|
269
271
|
# @private
|
270
272
|
class ValidateInclusionOfMatcher < ValidationMatcher
|
271
273
|
BLANK_VALUES = ['', ' ', "\n", "\r", "\t", "\f"].freeze
|
272
|
-
ARBITRARY_OUTSIDE_STRING =
|
274
|
+
ARBITRARY_OUTSIDE_STRING = Shoulda::Matchers::ExampleClass.name
|
273
275
|
ARBITRARY_OUTSIDE_INTEGER = 123456789
|
274
276
|
ARBITRARY_OUTSIDE_DECIMAL = BigDecimal('0.123456789')
|
275
277
|
ARBITRARY_OUTSIDE_DATE = Date.jd(9999999)
|
@@ -355,7 +357,7 @@ EOT
|
|
355
357
|
description = "validate that :#{@attribute}"
|
356
358
|
|
357
359
|
description <<
|
358
|
-
if @array.
|
360
|
+
if @array.count > 1
|
359
361
|
" is either #{inspected_array}"
|
360
362
|
else
|
361
363
|
" is #{inspected_array}"
|
@@ -276,6 +276,33 @@ module Shoulda
|
|
276
276
|
# should validate_numericality_of(:birth_day).odd
|
277
277
|
# end
|
278
278
|
#
|
279
|
+
# ##### is_in
|
280
|
+
#
|
281
|
+
# Use `is_in` to test usage of the `:in` option.
|
282
|
+
# This asserts that the attribute can take a number which is contained
|
283
|
+
# in the given range.
|
284
|
+
#
|
285
|
+
# class Person
|
286
|
+
# include ActiveModel::Model
|
287
|
+
# attr_accessor :legal_age
|
288
|
+
#
|
289
|
+
# validates_numericality_of :birth_month, in: 1..12
|
290
|
+
# end
|
291
|
+
#
|
292
|
+
# # RSpec
|
293
|
+
# RSpec.describe Person, type: :model do
|
294
|
+
# it do
|
295
|
+
# should validate_numericality_of(:birth_month).
|
296
|
+
# is_in(1..12)
|
297
|
+
# end
|
298
|
+
# end
|
299
|
+
#
|
300
|
+
# # Minitest (Shoulda)
|
301
|
+
# class PersonTest < ActiveSupport::TestCase
|
302
|
+
# should validate_numericality_of(:birth_month).
|
303
|
+
# is_in(1..12)
|
304
|
+
# end
|
305
|
+
#
|
279
306
|
# ##### with_message
|
280
307
|
#
|
281
308
|
# Use `with_message` if you are using a custom validation message.
|
@@ -426,6 +453,13 @@ module Shoulda
|
|
426
453
|
self
|
427
454
|
end
|
428
455
|
|
456
|
+
def is_in(range)
|
457
|
+
prepare_submatcher(
|
458
|
+
NumericalityMatchers::RangeMatcher.new(self, @attribute, range),
|
459
|
+
)
|
460
|
+
self
|
461
|
+
end
|
462
|
+
|
429
463
|
def with_message(message)
|
430
464
|
@expects_custom_validation_message = true
|
431
465
|
@expected_message = message
|
@@ -457,6 +491,10 @@ module Shoulda
|
|
457
491
|
description << "validate that :#{@attribute} looks like "
|
458
492
|
description << Shoulda::Matchers::Util.a_or_an(full_allowed_type)
|
459
493
|
|
494
|
+
if range_description.present?
|
495
|
+
description << " #{range_description}"
|
496
|
+
end
|
497
|
+
|
460
498
|
if comparison_descriptions.present?
|
461
499
|
description << " #{comparison_descriptions}"
|
462
500
|
end
|
@@ -643,7 +681,7 @@ module Shoulda
|
|
643
681
|
if number_of_submatchers_for_failure_message > 1
|
644
682
|
"In checking that #{model.name} #{submatcher_description}, " +
|
645
683
|
failure_message[0].downcase +
|
646
|
-
failure_message[1
|
684
|
+
failure_message[1..]
|
647
685
|
else
|
648
686
|
failure_message
|
649
687
|
end
|
@@ -673,6 +711,14 @@ module Shoulda
|
|
673
711
|
end
|
674
712
|
end
|
675
713
|
|
714
|
+
def range_description
|
715
|
+
range_submatcher = @submatchers.detect do |submatcher|
|
716
|
+
submatcher.respond_to? :range_description
|
717
|
+
end
|
718
|
+
|
719
|
+
range_submatcher&.range_description
|
720
|
+
end
|
721
|
+
|
676
722
|
def model
|
677
723
|
@subject.class
|
678
724
|
end
|