shoulda-matchers 4.0.0.rc1 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +72 -40
  4. data/lib/shoulda/matchers/action_controller.rb +2 -0
  5. data/lib/shoulda/matchers/active_model.rb +2 -3
  6. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +1 -0
  7. data/lib/shoulda/matchers/active_record.rb +2 -0
  8. data/lib/shoulda/matchers/active_record/association_matcher.rb +34 -0
  9. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +27 -4
  10. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +27 -4
  11. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1 -1
  12. data/lib/shoulda/matchers/independent.rb +2 -1
  13. data/lib/shoulda/matchers/rails_shim.rb +5 -9
  14. data/lib/shoulda/matchers/version.rb +1 -1
  15. data/lib/shoulda/matchers/warn.rb +1 -0
  16. data/shoulda-matchers.gemspec +11 -3
  17. metadata +13 -340
  18. data/.gitignore +0 -12
  19. data/.hound.yml +0 -3
  20. data/.hound/ruby.yml +0 -1062
  21. data/.python-version +0 -1
  22. data/.rubocop.yml +0 -15
  23. data/.travis.yml +0 -21
  24. data/.yardopts +0 -10
  25. data/Appraisals +0 -105
  26. data/CONTRIBUTING.md +0 -172
  27. data/Gemfile +0 -15
  28. data/Gemfile.lock +0 -59
  29. data/MAINTAINING.md +0 -250
  30. data/NEWS.md +0 -1235
  31. data/Rakefile +0 -46
  32. data/bin/setup +0 -190
  33. data/custom_plan.rb +0 -104
  34. data/doc_config/gh-pages/index.html.erb +0 -9
  35. data/doc_config/yard/setup.rb +0 -22
  36. data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +0 -5967
  37. data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +0 -12
  38. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +0 -66
  39. data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +0 -69
  40. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +0 -312
  41. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -26
  42. data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +0 -1
  43. data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +0 -8
  44. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -281
  45. data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +0 -1
  46. data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +0 -289
  47. data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +0 -6
  48. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +0 -35
  49. data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +0 -14
  50. data/doc_config/yard/templates/default/layout/html/fonts.erb +0 -1
  51. data/doc_config/yard/templates/default/layout/html/footer.erb +0 -6
  52. data/doc_config/yard/templates/default/layout/html/layout.erb +0 -23
  53. data/doc_config/yard/templates/default/layout/html/search.erb +0 -13
  54. data/doc_config/yard/templates/default/layout/html/setup.rb +0 -40
  55. data/doc_config/yard/templates/default/method_details/html/source.erb +0 -10
  56. data/doc_config/yard/templates/default/module/html/box_info.erb +0 -31
  57. data/gemfiles/4.2.gemfile +0 -39
  58. data/gemfiles/4.2.gemfile.lock +0 -246
  59. data/gemfiles/5.0.gemfile +0 -37
  60. data/gemfiles/5.0.gemfile.lock +0 -238
  61. data/gemfiles/5.1.gemfile +0 -38
  62. data/gemfiles/5.1.gemfile.lock +0 -254
  63. data/gemfiles/5.2.gemfile +0 -40
  64. data/gemfiles/5.2.gemfile.lock +0 -273
  65. data/script/install_gems_in_all_appraisals +0 -16
  66. data/script/run_all_tests +0 -16
  67. data/script/supported_ruby_versions +0 -7
  68. data/script/update_gem_in_all_appraisals +0 -17
  69. data/script/update_gems_in_all_appraisals +0 -16
  70. data/spec/acceptance/active_model_integration_spec.rb +0 -23
  71. data/spec/acceptance/independent_matchers_spec.rb +0 -125
  72. data/spec/acceptance/multiple_libraries_integration_spec.rb +0 -55
  73. data/spec/acceptance/rails_integration_spec.rb +0 -156
  74. data/spec/acceptance_spec_helper.rb +0 -23
  75. data/spec/doublespeak_spec_helper.rb +0 -2
  76. data/spec/report_warnings.rb +0 -7
  77. data/spec/spec_helper.rb +0 -20
  78. data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +0 -133
  79. data/spec/support/acceptance/helpers.rb +0 -33
  80. data/spec/support/acceptance/helpers/active_model_helpers.rb +0 -11
  81. data/spec/support/acceptance/helpers/array_helpers.rb +0 -13
  82. data/spec/support/acceptance/helpers/base_helpers.rb +0 -19
  83. data/spec/support/acceptance/helpers/command_helpers.rb +0 -68
  84. data/spec/support/acceptance/helpers/file_helpers.rb +0 -19
  85. data/spec/support/acceptance/helpers/gem_helpers.rb +0 -31
  86. data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -11
  87. data/spec/support/acceptance/helpers/n_unit_helpers.rb +0 -25
  88. data/spec/support/acceptance/helpers/pluralization_helpers.rb +0 -13
  89. data/spec/support/acceptance/helpers/rails_migration_helpers.rb +0 -21
  90. data/spec/support/acceptance/helpers/rails_version_helpers.rb +0 -11
  91. data/spec/support/acceptance/helpers/rspec_helpers.rb +0 -24
  92. data/spec/support/acceptance/helpers/ruby_version_helpers.rb +0 -9
  93. data/spec/support/acceptance/helpers/step_helpers.rb +0 -127
  94. data/spec/support/acceptance/matchers/have_output.rb +0 -31
  95. data/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +0 -55
  96. data/spec/support/acceptance/matchers/indicate_that_tests_were_run_matcher.rb +0 -103
  97. data/spec/support/tests/bundle.rb +0 -94
  98. data/spec/support/tests/command_runner.rb +0 -230
  99. data/spec/support/tests/current_bundle.rb +0 -55
  100. data/spec/support/tests/database.rb +0 -28
  101. data/spec/support/tests/database_adapters/postgresql.rb +0 -25
  102. data/spec/support/tests/database_adapters/sqlite3.rb +0 -26
  103. data/spec/support/tests/database_configuration.rb +0 -33
  104. data/spec/support/tests/database_configuration_registry.rb +0 -28
  105. data/spec/support/tests/filesystem.rb +0 -100
  106. data/spec/support/tests/version.rb +0 -45
  107. data/spec/support/unit/active_record/create_table.rb +0 -54
  108. data/spec/support/unit/attribute.rb +0 -45
  109. data/spec/support/unit/capture.rb +0 -46
  110. data/spec/support/unit/change_value.rb +0 -111
  111. data/spec/support/unit/create_model_arguments/basic.rb +0 -135
  112. data/spec/support/unit/create_model_arguments/has_many.rb +0 -15
  113. data/spec/support/unit/create_model_arguments/uniqueness_matcher.rb +0 -74
  114. data/spec/support/unit/helpers/action_pack_versions.rb +0 -22
  115. data/spec/support/unit/helpers/active_model_helpers.rb +0 -27
  116. data/spec/support/unit/helpers/active_model_versions.rb +0 -32
  117. data/spec/support/unit/helpers/active_record_versions.rb +0 -44
  118. data/spec/support/unit/helpers/active_resource_builder.rb +0 -27
  119. data/spec/support/unit/helpers/allow_value_matcher_helpers.rb +0 -15
  120. data/spec/support/unit/helpers/class_builder.rb +0 -90
  121. data/spec/support/unit/helpers/column_type_helpers.rb +0 -26
  122. data/spec/support/unit/helpers/confirmation_matcher_helpers.rb +0 -17
  123. data/spec/support/unit/helpers/controller_builder.rb +0 -63
  124. data/spec/support/unit/helpers/database_helpers.rb +0 -20
  125. data/spec/support/unit/helpers/i18n_faker.rb +0 -15
  126. data/spec/support/unit/helpers/mailer_builder.rb +0 -12
  127. data/spec/support/unit/helpers/message_helpers.rb +0 -19
  128. data/spec/support/unit/helpers/model_builder.rb +0 -114
  129. data/spec/support/unit/helpers/rails_versions.rb +0 -42
  130. data/spec/support/unit/helpers/validation_matcher_scenario_helpers.rb +0 -44
  131. data/spec/support/unit/i18n.rb +0 -7
  132. data/spec/support/unit/load_environment.rb +0 -12
  133. data/spec/support/unit/matchers/deprecate.rb +0 -60
  134. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +0 -51
  135. data/spec/support/unit/matchers/fail_with_message_matcher.rb +0 -64
  136. data/spec/support/unit/matchers/print_warning_including.rb +0 -67
  137. data/spec/support/unit/model_creation_strategies/active_model.rb +0 -111
  138. data/spec/support/unit/model_creation_strategies/active_record.rb +0 -77
  139. data/spec/support/unit/model_creators.rb +0 -19
  140. data/spec/support/unit/model_creators/active_model.rb +0 -39
  141. data/spec/support/unit/model_creators/active_record.rb +0 -42
  142. data/spec/support/unit/model_creators/active_record/has_and_belongs_to_many.rb +0 -95
  143. data/spec/support/unit/model_creators/active_record/has_many.rb +0 -67
  144. data/spec/support/unit/model_creators/active_record/uniqueness_matcher.rb +0 -42
  145. data/spec/support/unit/model_creators/basic.rb +0 -102
  146. data/spec/support/unit/rails_application.rb +0 -151
  147. data/spec/support/unit/record_builder_with_i18n_validation_message.rb +0 -69
  148. data/spec/support/unit/record_validating_confirmation_builder.rb +0 -54
  149. data/spec/support/unit/record_with_different_error_attribute_builder.rb +0 -92
  150. data/spec/support/unit/shared_examples/ignoring_interference_by_writer.rb +0 -79
  151. data/spec/support/unit/shared_examples/numerical_submatcher.rb +0 -17
  152. data/spec/support/unit/shared_examples/set_session_or_flash.rb +0 -360
  153. data/spec/support/unit/validation_matcher_scenario.rb +0 -60
  154. data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +0 -82
  155. data/spec/unit/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +0 -28
  156. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +0 -629
  157. data/spec/unit/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +0 -42
  158. data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +0 -76
  159. data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +0 -62
  160. data/spec/unit/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +0 -90
  161. data/spec/unit/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +0 -31
  162. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +0 -330
  163. data/spec/unit/shoulda/matchers/action_controller/route_params_spec.rb +0 -30
  164. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +0 -67
  165. data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +0 -17
  166. data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +0 -562
  167. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +0 -117
  168. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +0 -829
  169. data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +0 -86
  170. data/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +0 -20
  171. data/spec/unit/shoulda/matchers/active_model/helpers_spec.rb +0 -162
  172. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +0 -290
  173. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +0 -109
  174. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +0 -172
  175. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -264
  176. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -1049
  177. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -335
  178. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +0 -1865
  179. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -406
  180. data/spec/unit/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +0 -107
  181. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +0 -1672
  182. data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +0 -251
  183. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +0 -690
  184. data/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +0 -111
  185. data/spec/unit/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +0 -85
  186. data/spec/unit/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +0 -41
  187. data/spec/unit/shoulda/matchers/active_record/have_secure_token_matcher_spec.rb +0 -169
  188. data/spec/unit/shoulda/matchers/active_record/serialize_matcher_spec.rb +0 -86
  189. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +0 -1682
  190. data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +0 -190
  191. data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +0 -21
  192. data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +0 -271
  193. data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +0 -77
  194. data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +0 -72
  195. data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +0 -101
  196. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +0 -78
  197. data/spec/unit/shoulda/matchers/doublespeak_spec.rb +0 -27
  198. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher/stubbed_target_spec.rb +0 -43
  199. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +0 -650
  200. data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +0 -406
  201. data/spec/unit/shoulda/matchers/util/word_wrap_spec.rb +0 -252
  202. data/spec/unit_spec_helper.rb +0 -54
  203. data/spec/warnings_spy.rb +0 -64
  204. data/spec/warnings_spy/filesystem.rb +0 -45
  205. data/spec/warnings_spy/partitioner.rb +0 -36
  206. data/spec/warnings_spy/reader.rb +0 -53
  207. data/spec/warnings_spy/reporter.rb +0 -88
  208. data/tasks/documentation.rb +0 -199
  209. data/zeus.json +0 -11
@@ -1,1049 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :model do
4
- shared_context 'for a generic attribute' do
5
- def self.testing_values_of_option(option_name, &block)
6
- [nil, true, false].each do |option_value|
7
- context_name = "+ #{option_name}"
8
- option_args = []
9
- matches_or_not = ['matches', 'does not match']
10
- to_or_not_to = [:to, :not_to]
11
-
12
- unless option_value == nil
13
- context_name << "(#{option_value})"
14
- option_args = [option_value]
15
- end
16
-
17
- if option_value == false
18
- matches_or_not.reverse!
19
- to_or_not_to.reverse!
20
- end
21
- end
22
- end
23
-
24
- context 'against an integer attribute' do
25
- it_behaves_like 'it supports in_array',
26
- possible_values: (1..5).to_a,
27
- zero: 0,
28
- reserved_outside_value: described_class::ARBITRARY_OUTSIDE_INTEGER
29
-
30
- it_behaves_like 'it supports in_range',
31
- possible_values: 1..5,
32
- zero: 0
33
-
34
- context 'when attribute validates a range of values via custom validation' do
35
- it 'matches ensuring the correct range and messages' do
36
- expect_to_match_ensuring_range_and_messages(2..5, 2, 5)
37
- expect_to_match_ensuring_range_and_messages(2...5, 2, 4)
38
- end
39
- end
40
-
41
- def build_object(options = {}, &block)
42
- build_object_with_generic_attribute(
43
- options.merge(column_type: :integer, value: 1),
44
- &block
45
- )
46
- end
47
-
48
- def add_outside_value_to(values)
49
- values + [values.last + 1]
50
- end
51
-
52
- def validation_matcher_scenario_args
53
- super.deep_merge(column_type: :integer, default_value: 1)
54
- end
55
- end
56
-
57
- context 'against an attribute with a specific column limit' do
58
- it 'does not raise an exception when attempting to use the matcher' do
59
- possible_values = (1..5).to_a
60
- builder = build_object_allowing(possible_values)
61
- assertion = -> { expect_to_match_on_values(builder, possible_values) }
62
- expect(&assertion).not_to raise_error
63
- end
64
-
65
- def build_object(options = {}, &block)
66
- build_object_with_generic_attribute(
67
- options.merge(
68
- column_type: :integer,
69
- column_options: { limit: 2 },
70
- value: 1
71
- ),
72
- &block
73
- )
74
- end
75
-
76
- def expect_to_match_on_values(builder, values, &block)
77
- expect_to_match_in_array(builder, values, &block)
78
- end
79
- end
80
-
81
- context 'against a float attribute' do
82
- it_behaves_like 'it supports in_array',
83
- possible_values: [1.0, 2.0, 3.0, 4.0, 5.0],
84
- zero: 0.0,
85
- reserved_outside_value: described_class::ARBITRARY_OUTSIDE_INTEGER
86
-
87
- it_behaves_like 'it supports in_range',
88
- possible_values: 1.0..5.0,
89
- zero: 0.0
90
-
91
- def build_object(options = {}, &block)
92
- build_object_with_generic_attribute(
93
- options.merge(column_type: :float, value: 1.0),
94
- &block
95
- )
96
- end
97
-
98
- def add_outside_value_to(values)
99
- values + [values.last + 1]
100
- end
101
-
102
- def validation_matcher_scenario_args
103
- super.deep_merge(column_type: :float, default_value: 1.0)
104
- end
105
- end
106
-
107
- context 'against a decimal attribute' do
108
- it_behaves_like 'it supports in_array',
109
- possible_values: [1.0, 2.0, 3.0, 4.0, 5.0].map { |number|
110
- BigDecimal(number.to_s)
111
- },
112
- zero: BigDecimal('0.0'),
113
- reserved_outside_value: described_class::ARBITRARY_OUTSIDE_DECIMAL
114
-
115
- it_behaves_like 'it supports in_range',
116
- possible_values: BigDecimal('1.0') .. BigDecimal('5.0'),
117
- zero: BigDecimal('0.0')
118
-
119
- def build_object(options = {}, &block)
120
- build_object_with_generic_attribute(
121
- options.merge(column_type: :decimal, value: BigDecimal('1.0')),
122
- &block
123
- )
124
- end
125
-
126
- def add_outside_value_to(values)
127
- values + [values.last + 1]
128
- end
129
-
130
- def validation_matcher_scenario_args
131
- super.deep_merge(
132
- column_type: :decimal,
133
- default_value: BigDecimal('1.0')
134
- )
135
- end
136
- end
137
-
138
- context 'against a date attribute' do
139
- today = Date.today
140
-
141
- define_method(:today) { today }
142
-
143
- it_behaves_like 'it supports in_array',
144
- possible_values: (1..5).map { |n| today + n },
145
- reserved_outside_value: described_class::ARBITRARY_OUTSIDE_DATE
146
-
147
- it_behaves_like 'it supports in_range',
148
- possible_values: (today .. today + 5)
149
-
150
- define_method :build_object do |options = {}, &block|
151
- build_object_with_generic_attribute(
152
- options.merge(column_type: :date, value: today),
153
- &block
154
- )
155
- end
156
-
157
- def add_outside_value_to(values)
158
- values + [values.last + 1]
159
- end
160
-
161
- def validation_matcher_scenario_args
162
- super.deep_merge(column_type: :date, default_value: today)
163
- end
164
- end
165
-
166
- context 'against a datetime attribute' do
167
- now = DateTime.now
168
-
169
- define_method(:now) { now }
170
-
171
- it_behaves_like 'it supports in_array',
172
- possible_values: (1..5).map { |n| now + n },
173
- reserved_outside_value: described_class::ARBITRARY_OUTSIDE_DATETIME
174
-
175
- it_behaves_like 'it supports in_range',
176
- possible_values: (now .. now + 5)
177
-
178
- define_method :build_object do |options = {}, &block|
179
- build_object_with_generic_attribute(
180
- options.merge(column_type: :datetime, value: now),
181
- &block
182
- )
183
- end
184
-
185
- def add_outside_value_to(values)
186
- values + [values.last + 1]
187
- end
188
-
189
- def validation_matcher_scenario_args
190
- super.deep_merge(column_type: :datetime, default_value: now)
191
- end
192
- end
193
-
194
- context 'against a time attribute' do
195
- default_time = Time.zone.local(2000, 1, 1)
196
-
197
- define_method(:default_time) { default_time }
198
-
199
- it_behaves_like 'it supports in_array',
200
- possible_values: (1..3).map { |hour| default_time.change(hour: hour) }
201
-
202
- it_behaves_like 'it supports in_range',
203
- possible_values: (default_time.change(hour: 1) .. default_time.change(hour: 3))
204
-
205
- define_method :build_object do |options = {}, &block|
206
- build_object_with_generic_attribute(
207
- options.merge(column_type: :time, value: default_time),
208
- &block
209
- )
210
- end
211
-
212
- def add_outside_value_to(values)
213
- values + [values.last + 1]
214
- end
215
-
216
- def validation_matcher_scenario_args
217
- super.deep_merge(column_type: :time, default_value: default_time)
218
- end
219
- end
220
-
221
- context 'against a string attribute' do
222
- it_behaves_like 'it supports in_array',
223
- possible_values: %w(foo bar baz),
224
- reserved_outside_value: described_class::ARBITRARY_OUTSIDE_STRING
225
-
226
- def build_object(options = {}, &block)
227
- build_object_with_generic_attribute(
228
- options.merge(column_type: :string),
229
- &block
230
- )
231
- end
232
-
233
- def add_outside_value_to(values)
234
- values + %w(qux)
235
- end
236
-
237
- def validation_matcher_scenario_args
238
- super.deep_merge(column_type: :string)
239
- end
240
- end
241
- end
242
-
243
- shared_examples_for 'it supports allow_nil' do |args|
244
- valid_values = args.fetch(:valid_values)
245
-
246
- testing_values_of_option 'allow_nil' do |option_args, matches_or_not, to_or_not_to|
247
- it "#{matches_or_not[0]} when the validation specifies allow_nil" do
248
- builder = build_object_allowing(
249
- valid_values,
250
- validation_options: { allow_nil: true }
251
- )
252
-
253
- __send__("expect_#{to_or_not_to[0]}_match_on_values", builder, valid_values) do |matcher|
254
- matcher.allow_nil(*option_args)
255
- end
256
- end
257
-
258
- it "#{matches_or_not[1]} when the validation does not specify allow_nil" do
259
- builder = build_object_allowing(valid_values)
260
-
261
- __send__("expect_#{to_or_not_to[1]}_match_on_values", builder, valid_values) do |matcher|
262
- matcher.allow_nil(*option_args)
263
- end
264
- end
265
- end
266
-
267
- =begin
268
- it_supports(
269
- 'ignoring_interference_by_writer',
270
- tests: {
271
- accept_if_qualified_but_changing_value_does_not_interfere: {
272
- changing_values_with: -> (value) { value || valid_values.first }
273
- },
274
- reject_if_qualified_but_changing_value_interferes: {
275
- attribute_name: :attr,
276
- changing_values_with: :never_falsy,
277
- expected_message_includes: <<-MESSAGE.strip
278
- As indicated in the message above, :attr seems to be changing certain
279
- values as they are set, and this could have something to do with why
280
- this test is failing. If you've overridden the writer method for this
281
- attribute, then you may need to change it to make this test pass, or
282
- do something else entirely.
283
- MESSAGE
284
- }
285
- }
286
- )
287
- =end
288
-
289
- def validation_matcher_scenario_args
290
- super.deep_merge(validation_options: { allow_nil: true })
291
- end
292
-
293
- def configure_validation_matcher(matcher)
294
- super(matcher).allow_nil
295
- end
296
- end
297
-
298
- shared_examples_for 'it supports allow_blank' do |args|
299
- valid_values = args.fetch(:valid_values)
300
-
301
- testing_values_of_option 'allow_blank' do |option_args, matches_or_not, to_or_not_to|
302
- it "#{matches_or_not[0]} when the validation specifies allow_blank" do
303
- builder = build_object_allowing(
304
- valid_values,
305
- validation_options: { allow_blank: true }
306
- )
307
-
308
- __send__("expect_#{to_or_not_to[0]}_match_on_values", builder, valid_values) do |matcher|
309
- matcher.allow_blank(*option_args)
310
- end
311
- end
312
-
313
- it "#{matches_or_not[1]} when the validation does not specify allow_blank" do
314
- builder = build_object_allowing(valid_values)
315
-
316
- __send__("expect_#{to_or_not_to[1]}_match_on_values", builder, valid_values) do |matcher|
317
- matcher.allow_blank(*option_args)
318
- end
319
- end
320
- end
321
-
322
- =begin
323
- it_supports(
324
- 'ignoring_interference_by_writer',
325
- tests: {
326
- accept_if_qualified_but_changing_value_does_not_interfere: {
327
- changing_values_with: -> (value) {
328
- value.presence || valid_values.first
329
- }
330
- },
331
- reject_if_qualified_but_changing_value_interferes: {
332
- attribute_name: :attr,
333
- changing_values_with: :never_blank,
334
- expected_message_includes: <<-MESSAGE.strip
335
- As indicated in the message above, :attr seems to be changing certain
336
- values as they are set, and this could have something to do with why
337
- this test is failing. If you've overridden the writer method for this
338
- attribute, then you may need to change it to make this test pass, or
339
- do something else entirely.
340
- MESSAGE
341
- }
342
- }
343
- )
344
- =end
345
-
346
- def validation_matcher_scenario_args
347
- super.deep_merge(validation_options: { allow_blank: true })
348
- end
349
-
350
- def configure_validation_matcher(matcher)
351
- super(matcher).allow_blank
352
- end
353
- end
354
-
355
- shared_examples_for 'it supports with_message' do |args|
356
- valid_values = args.fetch(:valid_values)
357
-
358
- context 'given a string' do
359
- it 'matches when validation uses given message' do
360
- builder = build_object_allowing(
361
- valid_values,
362
- validation_options: { message: 'a message' }
363
- )
364
-
365
- expect_to_match_on_values(builder, valid_values) do |matcher|
366
- matcher.with_message('a message')
367
- end
368
- end
369
-
370
- it 'matches when validation uses given message that has an interpolated variable' do
371
- builder = build_object_allowing(
372
- valid_values,
373
- validation_options: { message: '%{value} is not included' },
374
- )
375
-
376
- expect_to_match_on_values(builder, valid_values) do |matcher|
377
- matcher.with_message(/ is not included\Z/)
378
- end
379
- end
380
-
381
- it 'does not match when validation uses the default message instead of given message' do
382
- builder = build_object_allowing(valid_values)
383
-
384
- expect_not_to_match_on_values(builder, valid_values) do |matcher|
385
- matcher.with_message('a message')
386
- end
387
- end
388
-
389
- it 'does not match when validation uses a message but it is not same as given' do
390
- builder = build_object_allowing(
391
- valid_values,
392
- validation_options: { message: 'a different message' }
393
- )
394
-
395
- expect_not_to_match_on_values(builder, valid_values) do |matcher|
396
- matcher.with_message('a message')
397
- end
398
- end
399
- end
400
-
401
- context 'given a regex' do
402
- it 'matches when validation uses a message that matches the regex' do
403
- builder = build_object_allowing(
404
- valid_values,
405
- validation_options: { message: 'this is a message' }
406
- )
407
-
408
- expect_to_match_on_values(builder, valid_values) do |matcher|
409
- matcher.with_message(/a message/)
410
- end
411
- end
412
-
413
- it 'does not match when validation uses the default message instead of given message' do
414
- builder = build_object_allowing(valid_values)
415
-
416
- expect_not_to_match_on_values(builder, valid_values) do |matcher|
417
- matcher.with_message(/a message/)
418
- end
419
- end
420
-
421
- it 'does not match when validation uses a message but it does not match regex' do
422
- builder = build_object_allowing(
423
- valid_values,
424
- validation_options: { message: 'a different message' }
425
- )
426
-
427
- expect_not_to_match_on_values(builder, valid_values) do |matcher|
428
- matcher.with_message(/a message/)
429
- end
430
- end
431
- end
432
-
433
- context 'given nil' do
434
- it 'is as if with_message had never been called' do
435
- builder = build_object_allowing(valid_values)
436
-
437
- expect_to_match_on_values(builder, valid_values) do |matcher|
438
- matcher.with_message(nil)
439
- end
440
- end
441
- end
442
- end
443
-
444
- shared_examples_for 'it supports in_array' do |args|
445
- possible_values = args.fetch(:possible_values)
446
- zero = args[:zero]
447
- reserved_outside_value = args[:reserved_outside_value]
448
-
449
- define_method(:valid_values) { args.fetch(:possible_values) }
450
-
451
- context 'when the record has no validations' do
452
- it 'passes when used in the negative' do
453
- builder = build_object
454
- expect_not_to_match_on_values(builder, possible_values)
455
- end
456
-
457
- it 'fails when used in the positive with an appropriate failure message' do
458
- builder = build_object
459
-
460
- assertion = lambda do
461
- expect_to_match_on_values(builder, possible_values)
462
- end
463
-
464
- expect(&assertion).to fail
465
- end
466
- end
467
-
468
- it 'matches given the same array of valid values' do
469
- builder = build_object_allowing(possible_values)
470
- expect_to_match_on_values(builder, possible_values)
471
- end
472
-
473
- it 'matches given a subset of the valid values' do
474
- builder = build_object_allowing(possible_values)
475
- expect_to_match_on_values(builder, possible_values[1..-1])
476
- end
477
-
478
- if zero
479
- it 'matches when one of the given values is a zero' do
480
- valid_values = possible_values + [zero]
481
- builder = build_object_allowing(valid_values)
482
- expect_to_match_on_values(builder, valid_values)
483
- end
484
- end
485
-
486
- it 'does not match when one of the given values is invalid' do
487
- builder = build_object_allowing(possible_values)
488
- expect_not_to_match_on_values(builder, add_outside_value_to(possible_values))
489
- end
490
-
491
- if reserved_outside_value
492
- it 'raises an error when valid and given value is our test outside value' do
493
- error_class = Shoulda::Matchers::ActiveModel::CouldNotDetermineValueOutsideOfArray
494
- builder = build_object_allowing([reserved_outside_value])
495
-
496
- expect { expect_to_match_on_values(builder, [reserved_outside_value]) }.
497
- to raise_error(error_class)
498
- end
499
- end
500
-
501
- it 'fails when used in the negative' do
502
- builder = build_object_allowing(possible_values)
503
-
504
- assertion = lambda do
505
- expect_not_to_match_on_values(builder, possible_values)
506
- end
507
-
508
- expect(&assertion).to fail
509
- end
510
-
511
- it_behaves_like 'it supports allow_nil', valid_values: possible_values
512
- it_behaves_like 'it supports allow_blank', valid_values: possible_values
513
- it_behaves_like 'it supports with_message', valid_values: possible_values
514
-
515
- if active_model_3_2?
516
- context '+ strict' do
517
- context 'when the validation specifies strict' do
518
- it 'matches when the given values match the valid values' do
519
- builder = build_object_allowing(
520
- possible_values,
521
- validation_options: { strict: true }
522
- )
523
-
524
- expect_to_match_on_values(builder, possible_values) do |matcher|
525
- matcher.strict
526
- end
527
- end
528
-
529
- it 'does not match when the given values do not match the valid values' do
530
- builder = build_object_allowing(
531
- possible_values,
532
- validation_options: { strict: true }
533
- )
534
-
535
- values = add_outside_value_to(possible_values)
536
- expect_not_to_match_on_values(builder, values) do |matcher|
537
- matcher.strict
538
- end
539
- end
540
- end
541
-
542
- context 'when the validation does not specify strict' do
543
- it 'does not match' do
544
- builder = build_object_allowing(possible_values)
545
-
546
- expect_not_to_match_on_values(builder, possible_values) do |matcher|
547
- matcher.strict
548
- end
549
- end
550
- end
551
- end
552
- end
553
-
554
- it_supports(
555
- 'ignoring_interference_by_writer',
556
- tests: {
557
- reject_if_qualified_but_changing_value_interferes: {
558
- attribute_name: :attr,
559
- changing_values_with: :next_value,
560
- expected_message_includes: <<-MESSAGE.strip
561
- As indicated in the message above, :attr seems to be changing certain
562
- values as they are set, and this could have something to do with why
563
- this test is failing. If you've overridden the writer method for this
564
- attribute, then you may need to change it to make this test pass, or
565
- do something else entirely.
566
- MESSAGE
567
- }
568
- }
569
- )
570
-
571
- def expect_to_match_on_values(builder, values, &block)
572
- expect_to_match_in_array(builder, values, &block)
573
- end
574
-
575
- def expect_not_to_match_on_values(builder, values, &block)
576
- expect_not_to_match_in_array(builder, values, &block)
577
- end
578
-
579
- def validation_matcher_scenario_args
580
- super.deep_merge(validation_options: { in: valid_values })
581
- end
582
-
583
- def configure_validation_matcher(matcher)
584
- super(matcher).in_array(valid_values)
585
- end
586
- end
587
-
588
- shared_examples_for 'it supports in_range' do |args|
589
- possible_values = args[:possible_values]
590
-
591
- define_method(:valid_values) { args.fetch(:possible_values) }
592
-
593
- it 'does not match a record with no validations' do
594
- builder = build_object
595
- expect_not_to_match_on_values(builder, possible_values)
596
- end
597
-
598
- it 'matches given a range that exactly matches the valid range' do
599
- builder = build_object_allowing(possible_values)
600
- expect_to_match_on_values(builder, possible_values)
601
- end
602
-
603
- it 'does not match given a range whose start value falls outside valid range' do
604
- builder = build_object_allowing(possible_values)
605
- expect_not_to_match_on_values(builder,
606
- Range.new(possible_values.first - 1, possible_values.last)
607
- )
608
- end
609
-
610
- it 'does not match given a range whose start value falls inside valid range' do
611
- builder = build_object_allowing(possible_values)
612
- expect_not_to_match_on_values(builder,
613
- Range.new(possible_values.first + 1, possible_values.last)
614
- )
615
- end
616
-
617
- it 'does not match given a range whose end value falls inside valid range' do
618
- builder = build_object_allowing(possible_values)
619
- expect_not_to_match_on_values(builder,
620
- Range.new(possible_values.first, possible_values.last - 1)
621
- )
622
- end
623
-
624
- it 'does not match given a range whose end value falls outside valid range' do
625
- builder = build_object_allowing(possible_values)
626
- expect_not_to_match_on_values(builder,
627
- Range.new(possible_values.first, possible_values.last + 1)
628
- )
629
- end
630
-
631
- it_behaves_like 'it supports allow_nil', valid_values: possible_values
632
- it_behaves_like 'it supports allow_blank', valid_values: possible_values
633
- it_behaves_like 'it supports with_message', valid_values: possible_values
634
-
635
- if active_model_3_2?
636
- context '+ strict' do
637
- context 'when the validation specifies strict' do
638
- it 'matches when the given range matches the range in the validation' do
639
- builder = build_object_allowing(
640
- possible_values,
641
- validation_options: { strict: true }
642
- )
643
-
644
- expect_to_match_on_values(builder, possible_values) do |matcher|
645
- matcher.strict
646
- end
647
- end
648
-
649
- it 'matches when the given range does not match the range in the validation' do
650
- builder = build_object_allowing(
651
- possible_values,
652
- validation_options: { strict: true }
653
- )
654
-
655
- range = Range.new(possible_values.first, possible_values.last + 1)
656
- expect_not_to_match_on_values(builder, range) do |matcher|
657
- matcher.strict
658
- end
659
- end
660
- end
661
-
662
- context 'when the validation does not specify strict' do
663
- it 'does not match' do
664
- builder = build_object_allowing(possible_values)
665
-
666
- expect_not_to_match_on_values(builder, possible_values) do |matcher|
667
- matcher.strict
668
- end
669
- end
670
- end
671
- end
672
- end
673
-
674
- it_supports(
675
- 'ignoring_interference_by_writer',
676
- tests: {
677
- reject_if_qualified_but_changing_value_interferes: {
678
- attribute_name: :attr,
679
- changing_values_with: :next_value,
680
- expected_message_includes: <<-MESSAGE.strip
681
- As indicated in the message above, :attr seems to be changing certain
682
- values as they are set, and this could have something to do with why
683
- this test is failing. If you've overridden the writer method for this
684
- attribute, then you may need to change it to make this test pass, or
685
- do something else entirely.
686
- MESSAGE
687
- }
688
- }
689
- )
690
-
691
- def expect_to_match_on_values(builder, range, &block)
692
- expect_to_match_in_range(builder, range, &block)
693
- end
694
-
695
- def expect_not_to_match_on_values(builder, range, &block)
696
- expect_not_to_match_in_range(builder, range, &block)
697
- end
698
-
699
- def validation_matcher_scenario_args
700
- super.deep_merge(validation_options: { in: valid_values })
701
- end
702
-
703
- def configure_validation_matcher(matcher)
704
- super(matcher).in_range(valid_values)
705
- end
706
- end
707
-
708
- shared_context 'against a boolean attribute for true and false' do
709
- context 'when ensuring inclusion of true' do
710
- it 'matches' do
711
- valid_values = [true]
712
- builder = build_object_allowing(valid_values)
713
- expect_to_match_in_array(builder, valid_values)
714
- end
715
- end
716
-
717
- context 'when ensuring inclusion of false' do
718
- it 'matches' do
719
- valid_values = [false]
720
- builder = build_object_allowing(valid_values)
721
- expect_to_match_in_array(builder, valid_values)
722
- end
723
- end
724
-
725
- context 'when ensuring inclusion of true and false' do
726
- it 'matches' do
727
- valid_values = [true, false]
728
- builder = build_object_allowing(valid_values)
729
- silence_stderr do
730
- expect_to_match_in_array(builder, valid_values)
731
- end
732
- end
733
-
734
- [[false, true], [true, false]].each do |booleans|
735
- it 'prints a warning' do
736
- valid_values = booleans
737
- builder = build_object_allowing(valid_values)
738
- message = 'You are using `validate_inclusion_of` to assert that a boolean column allows boolean values and disallows non-boolean ones'
739
-
740
- stderr = capture(:stderr) do
741
- expect_to_match_in_array(builder, valid_values)
742
- end
743
-
744
- expect(stderr.gsub(/\n+/, ' ')).to include(message)
745
- end
746
- end
747
- end
748
- end
749
-
750
- context 'for a database column' do
751
- include_context 'for a generic attribute'
752
-
753
- context 'against a timestamp column' do
754
- now = DateTime.now
755
-
756
- define_method(:now) { now }
757
-
758
- it_behaves_like 'it supports in_array',
759
- possible_values: (1..5).map { |n| now + n },
760
- reserved_outside_value: described_class::ARBITRARY_OUTSIDE_DATETIME
761
-
762
- it_behaves_like 'it supports in_range',
763
- possible_values: (now .. now + 5)
764
-
765
- define_method :build_object do |options = {}, &block|
766
- build_object_with_generic_attribute(
767
- options.merge(column_type: :timestamp, value: now),
768
- &block
769
- )
770
- end
771
-
772
- def add_outside_value_to(values)
773
- values + [values.last + 1]
774
- end
775
-
776
- def validation_matcher_scenario_args
777
- super.deep_merge(column_type: :timestamp, default_value: now)
778
- end
779
- end
780
-
781
- context 'against a boolean attribute' do
782
- context 'which is nullable' do
783
- include_context 'against a boolean attribute for true and false'
784
-
785
- context 'when ensuring inclusion of nil' do
786
- it 'matches' do
787
- valid_values = [nil]
788
- builder = build_object_allowing(valid_values)
789
- silence_stderr do
790
- expect_to_match_in_array(builder, valid_values)
791
- end
792
- end
793
-
794
- it 'prints a warning' do
795
- valid_values = [nil]
796
- builder = build_object_allowing(valid_values)
797
- message = 'You are using `validate_inclusion_of` to assert that a boolean column allows nil'
798
-
799
- stderr = capture(:stderr) do
800
- expect_to_match_in_array(builder, valid_values)
801
- end
802
-
803
- expect(stderr.gsub(/\n+/, ' ')).to include(message)
804
- end
805
- end
806
-
807
- def build_object(options = {}, &block)
808
- super(options.merge(column_options: { null: true }, value: true))
809
- end
810
- end
811
-
812
- context 'which is non-nullable' do
813
- include_context 'against a boolean attribute for true and false'
814
-
815
- context 'when ensuring inclusion of nil' do
816
- it 'raises a specific error' do
817
- valid_values = [nil]
818
- builder = build_object_allowing(valid_values)
819
- error_class = Shoulda::Matchers::ActiveModel::NonNullableBooleanError
820
-
821
- expect {
822
- expect_to_match_in_array(builder, valid_values)
823
- }.to raise_error(error_class)
824
- end
825
- end
826
-
827
- def build_object(options = {}, &block)
828
- super(options.merge(column_options: { null: false }))
829
- end
830
- end
831
-
832
- def build_object(options = {}, &block)
833
- build_object_with_generic_attribute(
834
- options.merge(column_type: :boolean),
835
- &block
836
- )
837
- end
838
- end
839
-
840
- def define_simple_model(attribute_name: :attr, column_options: {}, &block)
841
- define_model('Example', attribute_name => column_options, &block)
842
- end
843
-
844
- def validation_matcher_scenario_args
845
- super.deep_merge(model_creator: :active_record)
846
- end
847
- end
848
-
849
- context 'for a plain Ruby attribute' do
850
- include_context 'for a generic attribute'
851
-
852
- context 'against a boolean attribute (designated by true)' do
853
- include_context 'against a boolean attribute for true and false'
854
-
855
- def build_object(options = {}, &block)
856
- build_object_with_generic_attribute(options.merge(value: true))
857
- end
858
- end
859
-
860
- context 'against a boolean attribute (designated by false)' do
861
- include_context 'against a boolean attribute for true and false'
862
-
863
- def build_object(options = {}, &block)
864
- build_object_with_generic_attribute(options.merge(value: false))
865
- end
866
- end
867
-
868
- def define_simple_model(attribute_name: :attr, column_options: {}, &block)
869
- define_active_model_class('Example', accessors: [attribute_name], &block)
870
- end
871
-
872
- def validation_matcher_scenario_args
873
- super.deep_merge(model_creator: :active_model)
874
- end
875
- end
876
-
877
- describe '#description' do
878
- context 'given an array of values' do
879
- context 'when there is one value' do
880
- it 'returns the correct string' do
881
- matcher = validate_inclusion_of(:attr).in_array([true])
882
-
883
- expect(matcher.description).to eq(
884
- 'validate that :attr is ‹true›'
885
- )
886
- end
887
- end
888
-
889
- context 'when there are two values' do
890
- it 'returns the correct string' do
891
- matcher = validate_inclusion_of(:attr).in_array([true, 'dog'])
892
-
893
- expect(matcher.description).to eq(
894
- 'validate that :attr is either ‹true› or ‹"dog"›'
895
- )
896
- end
897
- end
898
-
899
- context 'when there are three or more values' do
900
- it 'returns the correct string' do
901
- matcher = validate_inclusion_of(:attr).in_array([true, 'dog', 'cat'])
902
-
903
- expect(matcher.description).to eq(
904
- 'validate that :attr is either ‹true›, ‹"dog"›, or ‹"cat"›'
905
- )
906
- end
907
- end
908
- end
909
-
910
- context 'given a range of values' do
911
- it 'returns the correct string' do
912
- matcher = validate_inclusion_of(:attr).in_range(1..10)
913
-
914
- expect(matcher.description).to eq(
915
- 'validate that :attr lies inside the range ‹1› to ‹10›'
916
- )
917
- end
918
- end
919
- end
920
-
921
- def object_builder_class
922
- @_object_builder_class ||= Struct.new(:attribute, :object, :validation_options)
923
- end
924
-
925
- def build_object_with_generic_attribute(
926
- attribute_name: :attr,
927
- validation_options: nil,
928
- value: nil,
929
- **other_options
930
- )
931
- model = define_model_validating_inclusion(
932
- attribute_name: attribute_name,
933
- validation_options: validation_options,
934
- **other_options
935
- )
936
-
937
- object = model.new
938
- object.__send__("#{attribute_name}=", value)
939
-
940
- object_builder_class.new(attribute_name, object, validation_options)
941
- end
942
-
943
- def define_model_validating_inclusion(
944
- attribute_name: :attr,
945
- column_type: :string,
946
- column_options: {},
947
- validation_options: nil,
948
- custom_validation: nil,
949
- customize_model_class: -> (object) { }
950
- )
951
- column_options = { type: column_type, options: column_options }
952
-
953
- define_simple_model(
954
- attribute_name: attribute_name,
955
- column_options: column_options
956
- ) do |model|
957
- if validation_options
958
- model.validates_inclusion_of(attribute_name, validation_options)
959
- end
960
-
961
- if custom_validation
962
- model.class_eval do
963
- define_method :custom_validation do
964
- custom_validation.call(self, attribute_name)
965
- end
966
-
967
- validate :custom_validation
968
- end
969
- end
970
-
971
- if customize_model_class
972
- model.instance_eval(&customize_model_class)
973
- end
974
- end
975
- end
976
-
977
- def build_object_allowing(values, validation_options: {}, **other_options)
978
- build_object(
979
- validation_options: validation_options.merge(in: values),
980
- **other_options
981
- )
982
- end
983
-
984
- def expect_to_match(builder)
985
- matcher = validate_inclusion_of(builder.attribute)
986
- yield matcher if block_given?
987
- expect(builder.object).to(matcher)
988
- end
989
-
990
- def expect_not_to_match(builder)
991
- matcher = validate_inclusion_of(builder.attribute)
992
- yield matcher if block_given?
993
- expect(builder.object).not_to(matcher)
994
- end
995
-
996
- def expect_to_match_in_array(builder, array)
997
- expect_to_match(builder) do |matcher|
998
- matcher.in_array(array)
999
- yield matcher if block_given?
1000
- end
1001
- end
1002
-
1003
- def expect_not_to_match_in_array(builder, array)
1004
- expect_not_to_match(builder) do |matcher|
1005
- matcher.in_array(array)
1006
- yield matcher if block_given?
1007
- end
1008
- end
1009
-
1010
- def expect_to_match_in_range(builder, range)
1011
- expect_to_match(builder) do |matcher|
1012
- matcher.in_range(range)
1013
- yield matcher if block_given?
1014
- end
1015
- end
1016
-
1017
- def expect_not_to_match_in_range(builder, range)
1018
- expect_not_to_match(builder) do |matcher|
1019
- matcher.in_range(range)
1020
- yield matcher if block_given?
1021
- end
1022
- end
1023
-
1024
- def expect_to_match_ensuring_range_and_messages(range, low_value, high_value)
1025
- low_message = 'too low'
1026
- high_message = 'too high'
1027
-
1028
- builder = build_object custom_validation: -> (object, attribute) {
1029
- value = object.public_send(attribute)
1030
-
1031
- if value < low_value
1032
- object.errors.add(attribute, low_message)
1033
- elsif value > high_value
1034
- object.errors.add(attribute, high_message)
1035
- end
1036
- }
1037
-
1038
- expect_to_match(builder) do |matcher|
1039
- matcher.
1040
- in_range(range).
1041
- with_low_message(low_message).
1042
- with_high_message(high_message)
1043
- end
1044
- end
1045
-
1046
- def validation_matcher_scenario_args
1047
- super.deep_merge(matcher_name: :validate_inclusion_of)
1048
- end
1049
- end