shoulda-matchers 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,21 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveModel
4
+ module Qualifiers
5
+ # @private
6
+ module IgnoringInterferenceByWriter
7
+ attr_reader :ignore_interference_by_writer
8
+
9
+ def initialize(*args)
10
+ @ignore_interference_by_writer = IgnoreInterferenceByWriter.new
11
+ end
12
+
13
+ def ignoring_interference_by_writer(value = :always)
14
+ @ignore_interference_by_writer.set(value)
15
+ self
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -4,21 +4,21 @@ module Shoulda
4
4
  # The `validate_absence_of` matcher tests the usage of the
5
5
  # `validates_absence_of` validation.
6
6
  #
7
- # class Artillery
7
+ # class PowerHungryCountry
8
8
  # include ActiveModel::Model
9
- # attr_accessor :arms
9
+ # attr_accessor :nuclear_weapons
10
10
  #
11
- # validates_absence_of :arms
11
+ # validates_absence_of :nuclear_weapons
12
12
  # end
13
13
  #
14
14
  # # RSpec
15
- # describe Artillery do
16
- # it { should validate_absence_of(:arms) }
15
+ # describe PowerHungryCountry do
16
+ # it { should validate_absence_of(:nuclear_weapons) }
17
17
  # end
18
18
  #
19
19
  # # Minitest (Shoulda)
20
- # class ArtilleryTest < ActiveSupport::TestCase
21
- # should validate_absence_of(:arms)
20
+ # class PowerHungryCountryTest < ActiveSupport::TestCase
21
+ # should validate_absence_of(:nuclear_weapons)
22
22
  # end
23
23
  #
24
24
  # #### Qualifiers
@@ -27,47 +27,47 @@ module Shoulda
27
27
  #
28
28
  # Use `on` if your validation applies only under a certain context.
29
29
  #
30
- # class Artillery
30
+ # class PowerHungryCountry
31
31
  # include ActiveModel::Model
32
- # attr_accessor :arms
32
+ # attr_accessor :nuclear_weapons
33
33
  #
34
- # validates_absence_of :arms, on: :create
34
+ # validates_absence_of :nuclear_weapons, on: :create
35
35
  # end
36
36
  #
37
37
  # # RSpec
38
- # describe Artillery do
39
- # it { should validate_absence_of(:arms).on(:create) }
38
+ # describe PowerHungryCountry do
39
+ # it { should validate_absence_of(:nuclear_weapons).on(:create) }
40
40
  # end
41
41
  #
42
42
  # # Minitest (Shoulda)
43
- # class ArtilleryTest < ActiveSupport::TestCase
44
- # should validate_absence_of(:arms).on(:create)
43
+ # class PowerHungryCountryTest < ActiveSupport::TestCase
44
+ # should validate_absence_of(:nuclear_weapons).on(:create)
45
45
  # end
46
46
  #
47
47
  # ##### with_message
48
48
  #
49
49
  # Use `with_message` if you are using a custom validation message.
50
50
  #
51
- # class Artillery
51
+ # class PowerHungryCountry
52
52
  # include ActiveModel::Model
53
- # attr_accessor :arms
53
+ # attr_accessor :nuclear_weapons
54
54
  #
55
- # validates_absence_of :arms,
56
- # message: "We're fresh outta arms here, soldier!"
55
+ # validates_absence_of :nuclear_weapons,
56
+ # message: "there shall be peace on Earth"
57
57
  # end
58
58
  #
59
59
  # # RSpec
60
- # describe Artillery do
60
+ # describe PowerHungryCountry do
61
61
  # it do
62
- # should validate_absence_of(:arms).
63
- # with_message("We're fresh outta arms here, soldier!")
62
+ # should validate_absence_of(:nuclear_weapons).
63
+ # with_message("there shall be peace on Earth")
64
64
  # end
65
65
  # end
66
66
  #
67
67
  # # Minitest (Shoulda)
68
- # class ArtilleryTest < ActiveSupport::TestCase
69
- # should validate_absence_of(:arms).
70
- # with_message("We're fresh outta arms here, soldier!")
68
+ # class PowerHungryCountryTest < ActiveSupport::TestCase
69
+ # should validate_absence_of(:nuclear_weapons).
70
+ # with_message("there shall be peace on Earth")
71
71
  # end
72
72
  #
73
73
  # @return [ValidateAbsenceOfMatcher}
@@ -78,20 +78,18 @@ module Shoulda
78
78
 
79
79
  # @private
80
80
  class ValidateAbsenceOfMatcher < ValidationMatcher
81
- def with_message(message)
82
- @expected_message = message
83
- self
81
+ def initialize(attribute)
82
+ super
83
+ @expected_message = :present
84
84
  end
85
85
 
86
86
  def matches?(subject)
87
87
  super(subject)
88
- @expected_message ||= :present
89
-
90
88
  disallows_value_of(value, @expected_message)
91
89
  end
92
90
 
93
- def description
94
- "require #{@attribute} to not be set"
91
+ def simple_description
92
+ "validate that :#{@attribute} is empty/falsy"
95
93
  end
96
94
 
97
95
  private
@@ -110,7 +108,7 @@ module Shoulda
110
108
  when :decimal then BigDecimal.new(1, 0)
111
109
  when :datetime, :time, :timestamp then Time.now
112
110
  when :date then Date.new
113
- when :binary then "0"
111
+ when :binary then '0'
114
112
  else 'an arbitrary value'
115
113
  end
116
114
  end
@@ -81,21 +81,18 @@ module Shoulda
81
81
 
82
82
  # @private
83
83
  class ValidateAcceptanceOfMatcher < ValidationMatcher
84
- def with_message(message)
85
- if message
86
- @expected_message = message
87
- end
88
- self
84
+ def initialize(attribute)
85
+ super
86
+ @expected_message = :accepted
89
87
  end
90
88
 
91
89
  def matches?(subject)
92
90
  super(subject)
93
- @expected_message ||= :accepted
94
91
  disallows_value_of(false, @expected_message)
95
92
  end
96
93
 
97
- def description
98
- "require #{@attribute} to be accepted"
94
+ def simple_description
95
+ %(validate that :#{@attribute} has been set to "1")
99
96
  end
100
97
  end
101
98
  end
@@ -83,22 +83,17 @@ module Shoulda
83
83
  attr_reader :attribute, :confirmation_attribute
84
84
 
85
85
  def initialize(attribute)
86
- super(attribute)
86
+ super
87
+ @expected_message = :confirmation
87
88
  @confirmation_attribute = "#{attribute}_confirmation"
88
89
  end
89
90
 
90
- def with_message(message)
91
- @message = message if message
92
- self
93
- end
94
-
95
- def description
96
- "require #{@confirmation_attribute} to match #{@attribute}"
91
+ def simple_description
92
+ "validate that :#{@confirmation_attribute} matches :#{@attribute}"
97
93
  end
98
94
 
99
95
  def matches?(subject)
100
96
  super(subject)
101
- @message ||= :confirmation
102
97
 
103
98
  disallows_different_value &&
104
99
  allows_same_value &&
@@ -108,38 +103,43 @@ module Shoulda
108
103
  private
109
104
 
110
105
  def disallows_different_value
111
- set_confirmation('some value')
112
106
  disallows_value_of('different value') do |matcher|
113
- qualify_matcher(matcher)
107
+ qualify_matcher(matcher, 'some value')
114
108
  end
115
109
  end
116
110
 
117
111
  def allows_same_value
118
- set_confirmation('same value')
119
112
  allows_value_of('same value') do |matcher|
120
- qualify_matcher(matcher)
113
+ qualify_matcher(matcher, 'same value')
121
114
  end
122
115
  end
123
116
 
124
117
  def allows_missing_confirmation
125
- set_confirmation(nil)
126
118
  allows_value_of('any value') do |matcher|
127
- qualify_matcher(matcher)
119
+ qualify_matcher(matcher, nil)
128
120
  end
129
121
  end
130
122
 
131
- def qualify_matcher(matcher)
132
- matcher.with_message(@message,
123
+ def qualify_matcher(matcher, confirmation_attribute_value)
124
+ matcher.values_to_preset = {
125
+ confirmation_attribute => confirmation_attribute_value
126
+ }
127
+ matcher.with_message(
128
+ @expected_message,
133
129
  against: confirmation_attribute,
134
130
  values: { attribute: attribute }
135
131
  )
136
132
  end
137
133
 
138
- def set_confirmation(val)
139
- setter = :"#{@confirmation_attribute}="
140
- if @subject.respond_to?(setter)
141
- @subject.__send__(setter, val)
142
- end
134
+ def set_confirmation(value)
135
+ @last_value_set_on_confirmation_attribute = value
136
+
137
+ AttributeSetter.set(
138
+ matcher_name: 'confirmation',
139
+ object: @subject,
140
+ attribute_name: confirmation_attribute,
141
+ value: value
142
+ )
143
143
  end
144
144
  end
145
145
  end
@@ -122,9 +122,9 @@ module Shoulda
122
122
  class ValidateExclusionOfMatcher < ValidationMatcher
123
123
  def initialize(attribute)
124
124
  super(attribute)
125
+ @expected_message = :exclusion
125
126
  @array = nil
126
127
  @range = nil
127
- @expected_message = nil
128
128
  end
129
129
 
130
130
  def in_array(array)
@@ -139,13 +139,21 @@ module Shoulda
139
139
  self
140
140
  end
141
141
 
142
- def with_message(message)
143
- @expected_message = message if message
144
- self
145
- end
142
+ def simple_description
143
+ if @range
144
+ "validate that :#{@attribute} lies outside the range " +
145
+ Shoulda::Matchers::Util.inspect_range(@range)
146
+ else
147
+ description = "validate that :#{@attribute}"
148
+
149
+ if @array.many?
150
+ description << " is neither #{inspected_array}"
151
+ else
152
+ description << " is not #{inspected_array}"
153
+ end
146
154
 
147
- def description
148
- "ensure exclusion of #{@attribute} in #{inspect_message}"
155
+ description
156
+ end
149
157
  end
150
158
 
151
159
  def matches?(subject)
@@ -165,28 +173,24 @@ module Shoulda
165
173
 
166
174
  def disallows_all_values_in_array?
167
175
  @array.all? do |value|
168
- disallows_value_of(value, expected_message)
176
+ disallows_value_of(value, @expected_message)
169
177
  end
170
178
  end
171
179
 
172
180
  def allows_lower_value
173
- @minimum == 0 || allows_value_of(@minimum - 1, expected_message)
181
+ @minimum == 0 || allows_value_of(@minimum - 1, @expected_message)
174
182
  end
175
183
 
176
184
  def allows_higher_value
177
- allows_value_of(@maximum + 1, expected_message)
185
+ allows_value_of(@maximum + 1, @expected_message)
178
186
  end
179
187
 
180
188
  def disallows_minimum_value
181
- disallows_value_of(@minimum, expected_message)
189
+ disallows_value_of(@minimum, @expected_message)
182
190
  end
183
191
 
184
192
  def disallows_maximum_value
185
- disallows_value_of(@maximum, expected_message)
186
- end
187
-
188
- def expected_message
189
- @expected_message || :exclusion
193
+ disallows_value_of(@maximum, @expected_message)
190
194
  end
191
195
 
192
196
  def inspect_message
@@ -196,6 +200,13 @@ module Shoulda
196
200
  @array.inspect
197
201
  end
198
202
  end
203
+
204
+ def inspected_array
205
+ Shoulda::Matchers::Util.inspect_values(@array).to_sentence(
206
+ two_words_connector: " nor ",
207
+ last_word_connector: ", nor "
208
+ )
209
+ end
199
210
  end
200
211
  end
201
212
  end
@@ -13,21 +13,22 @@ module Shoulda
13
13
  # include ActiveModel::Model
14
14
  # attr_accessor :state
15
15
  #
16
- # validates_inclusion_of :state, in: %w(open resolved unresolved)
16
+ # validates_inclusion_of :state,
17
+ # in: ['open', 'resolved', 'unresolved']
17
18
  # end
18
19
  #
19
20
  # # RSpec
20
21
  # describe Issue do
21
22
  # it do
22
23
  # should validate_inclusion_of(:state).
23
- # in_array(%w(open resolved unresolved))
24
+ # in_array(['open', 'resolved', 'unresolved'])
24
25
  # end
25
26
  # end
26
27
  #
27
28
  # # Minitest (Shoulda)
28
29
  # class IssueTest < ActiveSupport::TestCase
29
30
  # should validate_inclusion_of(:state).
30
- # in_array(%w(open resolved unresolved))
31
+ # in_array(['open', 'resolved', 'unresolved'])
31
32
  # end
32
33
  #
33
34
  # If your whitelist is a range of values, use `in_range`:
@@ -57,7 +58,10 @@ module Shoulda
57
58
  # one of these three values. That means there isn't any way we can refute
58
59
  # this logic in a test. Hence, this will produce a warning:
59
60
  #
60
- # it { should validate_inclusion_of(:imported).in_array([true, false]) }
61
+ # it do
62
+ # should validate_inclusion_of(:imported).
63
+ # in_array([true, false])
64
+ # end
61
65
  #
62
66
  # The only case where `validate_inclusion_of` *could* be appropriate is
63
67
  # for ensuring that a boolean column accepts nil, but we recommend
@@ -205,7 +209,7 @@ module Shoulda
205
209
  #
206
210
  # validates_presence_of :state
207
211
  # validates_inclusion_of :state,
208
- # in: %w(open resolved unresolved),
212
+ # in: ['open', 'resolved', 'unresolved'],
209
213
  # allow_nil: true
210
214
  # end
211
215
  #
@@ -213,7 +217,7 @@ module Shoulda
213
217
  # describe Issue do
214
218
  # it do
215
219
  # should validate_inclusion_of(:state).
216
- # in_array(%w(open resolved unresolved)).
220
+ # in_array(['open', 'resolved', 'unresolved']).
217
221
  # allow_nil
218
222
  # end
219
223
  # end
@@ -221,7 +225,7 @@ module Shoulda
221
225
  # # Minitest (Shoulda)
222
226
  # class IssueTest < ActiveSupport::TestCase
223
227
  # should validate_inclusion_of(:state).
224
- # in_array(%w(open resolved unresolved)).
228
+ # in_array(['open', 'resolved', 'unresolved']).
225
229
  # allow_nil
226
230
  # end
227
231
  #
@@ -235,7 +239,7 @@ module Shoulda
235
239
  #
236
240
  # validates_presence_of :state
237
241
  # validates_inclusion_of :state,
238
- # in: %w(open resolved unresolved),
242
+ # in: ['open', 'resolved', 'unresolved'],
239
243
  # allow_blank: true
240
244
  # end
241
245
  #
@@ -243,7 +247,7 @@ module Shoulda
243
247
  # describe Issue do
244
248
  # it do
245
249
  # should validate_inclusion_of(:state).
246
- # in_array(%w(open resolved unresolved)).
250
+ # in_array(['open', 'resolved', 'unresolved']).
247
251
  # allow_blank
248
252
  # end
249
253
  # end
@@ -251,7 +255,7 @@ module Shoulda
251
255
  # # Minitest (Shoulda)
252
256
  # class IssueTest < ActiveSupport::TestCase
253
257
  # should validate_inclusion_of(:state).
254
- # in_array(%w(open resolved unresolved)).
258
+ # in_array(['open', 'resolved', 'unresolved']).
255
259
  # allow_blank
256
260
  # end
257
261
  #
@@ -310,31 +314,61 @@ EOT
310
314
  self
311
315
  end
312
316
 
317
+ def expects_to_allow_blank?
318
+ @options[:allow_blank]
319
+ end
320
+
313
321
  def allow_nil(allow_nil = true)
314
322
  @options[:allow_nil] = allow_nil
315
323
  self
316
324
  end
317
325
 
326
+ def expects_to_allow_nil?
327
+ @options[:allow_nil]
328
+ end
329
+
318
330
  def with_message(message)
319
331
  if message
332
+ @expects_custom_validation_message = true
320
333
  @low_message = message
321
334
  @high_message = message
322
335
  end
336
+
323
337
  self
324
338
  end
325
339
 
326
340
  def with_low_message(message)
327
- @low_message = message if message
341
+ if message
342
+ @expects_custom_validation_message = true
343
+ @low_message = message
344
+ end
345
+
328
346
  self
329
347
  end
330
348
 
331
349
  def with_high_message(message)
332
- @high_message = message if message
350
+ if message
351
+ @high_message = message
352
+ end
353
+
333
354
  self
334
355
  end
335
356
 
336
- def description
337
- "ensure inclusion of #{@attribute} in #{inspect_message}"
357
+ def simple_description
358
+ if @range
359
+ "validate that :#{@attribute} lies inside the range " +
360
+ Shoulda::Matchers::Util.inspect_range(@range)
361
+ else
362
+ description = "validate that :#{@attribute}"
363
+
364
+ if @array.many?
365
+ description << " is either #{inspected_array}"
366
+ else
367
+ description << " is #{inspected_array}"
368
+ end
369
+
370
+ description
371
+ end
338
372
  end
339
373
 
340
374
  def matches?(subject)
@@ -398,7 +432,9 @@ EOT
398
432
  end
399
433
 
400
434
  def disallows_lower_value
401
- @minimum == 0 || disallows_value_of(@minimum - 1, @low_message)
435
+ @minimum.nil? ||
436
+ @minimum == 0 ||
437
+ disallows_value_of(@minimum - 1, @low_message)
402
438
  end
403
439
 
404
440
  def disallows_higher_value
@@ -518,6 +554,13 @@ EOT
518
554
  else :unknown
519
555
  end
520
556
  end
557
+
558
+ def inspected_array
559
+ Shoulda::Matchers::Util.inspect_values(@array).to_sentence(
560
+ two_words_connector: " or ",
561
+ last_word_connector: ", or "
562
+ )
563
+ end
521
564
  end
522
565
  end
523
566
  end