shoulda-matchers 3.1.3 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.hound/ruby.yml +336 -316
  3. data/.python-version +1 -0
  4. data/.rubocop.yml +3 -1
  5. data/.travis.yml +7 -6
  6. data/Appraisals +76 -44
  7. data/CONTRIBUTING.md +137 -66
  8. data/Gemfile +5 -5
  9. data/Gemfile.lock +30 -35
  10. data/MAINTAINING.md +250 -0
  11. data/MIT-LICENSE +1 -1
  12. data/NEWS.md +176 -4
  13. data/README.md +138 -200
  14. data/Rakefile +7 -0
  15. data/bin/setup +190 -0
  16. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +4 -0
  17. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -6
  18. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -17
  19. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +27 -0
  20. data/gemfiles/4.2.gemfile +21 -20
  21. data/gemfiles/4.2.gemfile.lock +143 -140
  22. data/gemfiles/5.0.gemfile +37 -0
  23. data/gemfiles/5.0.gemfile.lock +238 -0
  24. data/gemfiles/5.1.gemfile +38 -0
  25. data/gemfiles/5.1.gemfile.lock +254 -0
  26. data/gemfiles/5.2.gemfile +40 -0
  27. data/gemfiles/5.2.gemfile.lock +273 -0
  28. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +18 -6
  29. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +6 -1
  30. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
  31. data/lib/shoulda/matchers/action_controller/route_matcher.rb +87 -27
  32. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +1 -0
  33. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +0 -4
  34. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +5 -0
  35. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +5 -0
  36. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +26 -11
  37. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +39 -4
  38. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +116 -47
  39. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +127 -38
  40. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +55 -37
  41. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +30 -1
  42. data/lib/shoulda/matchers/active_model/validation_matcher.rb +11 -4
  43. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +11 -6
  44. data/lib/shoulda/matchers/active_record.rb +3 -0
  45. data/lib/shoulda/matchers/active_record/association_matcher.rb +172 -22
  46. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +1 -1
  47. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +11 -6
  48. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +46 -0
  49. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +51 -0
  50. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +268 -38
  51. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
  52. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +111 -0
  53. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +207 -79
  54. data/lib/shoulda/matchers/doublespeak/object_double.rb +5 -1
  55. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +100 -21
  56. data/lib/shoulda/matchers/rails_shim.rb +133 -52
  57. data/lib/shoulda/matchers/routing.rb +2 -2
  58. data/lib/shoulda/matchers/util.rb +23 -1
  59. data/lib/shoulda/matchers/util/word_wrap.rb +6 -2
  60. data/lib/shoulda/matchers/version.rb +1 -1
  61. data/script/install_gems_in_all_appraisals +3 -1
  62. data/script/run_all_tests +3 -1
  63. data/script/supported_ruby_versions +7 -0
  64. data/script/update_gem_in_all_appraisals +3 -1
  65. data/script/update_gems_in_all_appraisals +3 -1
  66. data/shoulda-matchers.gemspec +3 -3
  67. data/spec/acceptance/independent_matchers_spec.rb +2 -2
  68. data/spec/acceptance/multiple_libraries_integration_spec.rb +1 -1
  69. data/spec/acceptance/rails_integration_spec.rb +2 -2
  70. data/spec/spec_helper.rb +2 -3
  71. data/spec/support/acceptance/helpers.rb +2 -0
  72. data/spec/support/acceptance/helpers/command_helpers.rb +17 -4
  73. data/spec/support/acceptance/helpers/rails_migration_helpers.rb +21 -0
  74. data/spec/support/acceptance/helpers/step_helpers.rb +1 -1
  75. data/spec/support/tests/current_bundle.rb +3 -9
  76. data/spec/support/tests/filesystem.rb +2 -2
  77. data/spec/support/unit/attribute.rb +0 -2
  78. data/spec/support/unit/capture.rb +9 -3
  79. data/spec/support/unit/helpers/action_pack_versions.rb +22 -0
  80. data/spec/support/unit/helpers/active_model_versions.rb +4 -0
  81. data/spec/support/unit/helpers/active_record_versions.rb +22 -2
  82. data/spec/support/unit/helpers/active_resource_builder.rb +2 -2
  83. data/spec/support/unit/helpers/controller_builder.rb +1 -1
  84. data/spec/support/unit/helpers/message_helpers.rb +19 -0
  85. data/spec/support/unit/helpers/rails_versions.rb +14 -0
  86. data/spec/support/unit/matchers/fail_with_message_matcher.rb +7 -5
  87. data/spec/support/unit/matchers/print_warning_including.rb +21 -13
  88. data/spec/support/unit/model_creation_strategies/active_record.rb +1 -1
  89. data/spec/support/unit/model_creators/active_record.rb +0 -1
  90. data/spec/support/unit/model_creators/basic.rb +7 -2
  91. data/spec/support/unit/rails_application.rb +25 -0
  92. data/spec/support/unit/record_validating_confirmation_builder.rb +5 -2
  93. data/spec/support/unit/validation_matcher_scenario.rb +0 -2
  94. data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +18 -18
  95. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +33 -5
  96. data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +1 -1
  97. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +80 -78
  98. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +7 -9
  99. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +28 -4
  100. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +19 -1
  101. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +27 -4
  102. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +62 -5
  103. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +52 -18
  104. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +51 -4
  105. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +99 -71
  106. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +41 -15
  107. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +445 -15
  108. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +615 -93
  109. data/spec/unit/shoulda/matchers/active_record/have_secure_token_matcher_spec.rb +169 -0
  110. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +167 -97
  111. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +2 -4
  112. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +152 -19
  113. data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +258 -94
  114. data/spec/unit_spec_helper.rb +9 -1
  115. data/zeus.json +1 -1
  116. metadata +31 -16
  117. data/gemfiles/4.0.0.gemfile +0 -38
  118. data/gemfiles/4.0.0.gemfile.lock +0 -223
  119. data/gemfiles/4.0.1.gemfile +0 -38
  120. data/gemfiles/4.0.1.gemfile.lock +0 -225
  121. data/gemfiles/4.1.gemfile +0 -38
  122. data/gemfiles/4.1.gemfile.lock +0 -220
  123. data/script/SUPPORTED_VERSIONS +0 -1
@@ -332,6 +332,7 @@ module Shoulda
332
332
  @context = nil
333
333
  @values_to_preset = {}
334
334
  @failure_message_preface = nil
335
+ @attribute_changed_value_message = nil
335
336
  end
336
337
 
337
338
  def for(attribute_name)
@@ -225,10 +225,6 @@ module Shoulda
225
225
  def active_resource_object?
226
226
  object.respond_to?(:known_attributes)
227
227
  end
228
-
229
- def model
230
- object.class
231
- end
232
228
  end
233
229
  end
234
230
  end
@@ -88,6 +88,11 @@ module Shoulda
88
88
  disallows_value_of(value, @expected_message)
89
89
  end
90
90
 
91
+ def does_not_match?(subject)
92
+ super(subject)
93
+ allows_value_of(value, @expected_message)
94
+ end
95
+
91
96
  def simple_description
92
97
  "validate that :#{@attribute} is empty/falsy"
93
98
  end
@@ -91,6 +91,11 @@ module Shoulda
91
91
  disallows_value_of(false, @expected_message)
92
92
  end
93
93
 
94
+ def does_not_match?(subject)
95
+ super(subject)
96
+ allows_value_of(false, @expected_message)
97
+ end
98
+
94
99
  def simple_description
95
100
  %(validate that :#{@attribute} has been set to "1")
96
101
  end
@@ -100,8 +100,22 @@ module Shoulda
100
100
  allows_missing_confirmation
101
101
  end
102
102
 
103
+ def does_not_match?(subject)
104
+ super(subject)
105
+
106
+ allows_different_value ||
107
+ disallows_same_value ||
108
+ disallows_missing_confirmation
109
+ end
110
+
103
111
  private
104
112
 
113
+ def allows_different_value
114
+ allows_value_of('different value') do |matcher|
115
+ qualify_matcher(matcher, 'some value')
116
+ end
117
+ end
118
+
105
119
  def disallows_different_value
106
120
  disallows_value_of('different value') do |matcher|
107
121
  qualify_matcher(matcher, 'some value')
@@ -114,12 +128,24 @@ module Shoulda
114
128
  end
115
129
  end
116
130
 
131
+ def disallows_same_value
132
+ disallows_value_of('same value') do |matcher|
133
+ qualify_matcher(matcher, 'same value')
134
+ end
135
+ end
136
+
117
137
  def allows_missing_confirmation
118
138
  allows_value_of('any value') do |matcher|
119
139
  qualify_matcher(matcher, nil)
120
140
  end
121
141
  end
122
142
 
143
+ def disallows_missing_confirmation
144
+ disallows_value_of('any value') do |matcher|
145
+ qualify_matcher(matcher, nil)
146
+ end
147
+ end
148
+
123
149
  def qualify_matcher(matcher, confirmation_attribute_value)
124
150
  matcher.values_to_preset = {
125
151
  confirmation_attribute => confirmation_attribute_value
@@ -130,17 +156,6 @@ module Shoulda
130
156
  values: { attribute: attribute }
131
157
  )
132
158
  end
133
-
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
- end
144
159
  end
145
160
  end
146
161
  end
@@ -162,15 +162,34 @@ module Shoulda
162
162
  if @range
163
163
  allows_lower_value &&
164
164
  disallows_minimum_value &&
165
- allows_higher_value &&
166
- disallows_maximum_value
165
+ disallows_maximum_value &&
166
+ allows_higher_value
167
167
  elsif @array
168
168
  disallows_all_values_in_array?
169
169
  end
170
170
  end
171
171
 
172
+ def does_not_match?(subject)
173
+ super(subject)
174
+
175
+ if @range
176
+ disallows_lower_value ||
177
+ allows_minimum_value ||
178
+ allows_maximum_value ||
179
+ disallows_higher_value
180
+ elsif @array
181
+ allows_any_values_in_array?
182
+ end
183
+ end
184
+
172
185
  private
173
186
 
187
+ def allows_any_values_in_array?
188
+ @array.any? do |value|
189
+ allows_value_of(value, @expected_message)
190
+ end
191
+ end
192
+
174
193
  def disallows_all_values_in_array?
175
194
  @array.all? do |value|
176
195
  disallows_value_of(value, @expected_message)
@@ -181,18 +200,34 @@ module Shoulda
181
200
  @minimum == 0 || allows_value_of(@minimum - 1, @expected_message)
182
201
  end
183
202
 
184
- def allows_higher_value
185
- allows_value_of(@maximum + 1, @expected_message)
203
+ def disallows_lower_value
204
+ @minimum != 0 && disallows_value_of(@minimum - 1, @expected_message)
205
+ end
206
+
207
+ def allows_minimum_value
208
+ allows_value_of(@minimum, @expected_message)
186
209
  end
187
210
 
188
211
  def disallows_minimum_value
189
212
  disallows_value_of(@minimum, @expected_message)
190
213
  end
191
214
 
215
+ def allows_maximum_value
216
+ allows_value_of(@maximum, @expected_message)
217
+ end
218
+
192
219
  def disallows_maximum_value
193
220
  disallows_value_of(@maximum, @expected_message)
194
221
  end
195
222
 
223
+ def allows_higher_value
224
+ allows_value_of(@maximum + 1, @expected_message)
225
+ end
226
+
227
+ def disallows_higher_value
228
+ disallows_value_of(@maximum + 1, @expected_message)
229
+ end
230
+
196
231
  def inspect_message
197
232
  if @range
198
233
  @range.inspect
@@ -268,8 +268,9 @@ module Shoulda
268
268
 
269
269
  # @private
270
270
  class ValidateInclusionOfMatcher < ValidationMatcher
271
+ BLANK_VALUES = ['', ' ', "\n", "\r", "\t", "\f"]
271
272
  ARBITRARY_OUTSIDE_STRING = 'shoulda-matchers test string'
272
- ARBITRARY_OUTSIDE_FIXNUM = 123456789
273
+ ARBITRARY_OUTSIDE_INTEGER = 123456789
273
274
  ARBITRARY_OUTSIDE_DECIMAL = BigDecimal('0.123456789')
274
275
  ARBITRARY_OUTSIDE_DATE = Date.jd(9999999)
275
276
  ARBITRARY_OUTSIDE_DATETIME = DateTime.jd(9999999)
@@ -294,8 +295,8 @@ EOT
294
295
  @range = nil
295
296
  @minimum = nil
296
297
  @maximum = nil
297
- @low_message = nil
298
- @high_message = nil
298
+ @low_message = :inclusion
299
+ @high_message = :inclusion
299
300
  end
300
301
 
301
302
  def in_array(array)
@@ -310,8 +311,8 @@ EOT
310
311
  self
311
312
  end
312
313
 
313
- def allow_blank(allow_blank = true)
314
- @options[:allow_blank] = allow_blank
314
+ def allow_blank
315
+ @options[:allow_blank] = true
315
316
  self
316
317
  end
317
318
 
@@ -319,9 +320,8 @@ EOT
319
320
  @options[:allow_blank]
320
321
  end
321
322
 
322
- def allow_nil(allow_nil = true)
323
- @options[:allow_nil] = allow_nil
324
- self
323
+ def allow_nil
324
+ @options[:allow_nil] = true
325
325
  end
326
326
 
327
327
  def expects_to_allow_nil?
@@ -376,8 +376,6 @@ EOT
376
376
  super(subject)
377
377
 
378
378
  if @range
379
- @low_message ||= :inclusion
380
- @high_message ||= :inclusion
381
379
  matches_for_range?
382
380
  elsif @array
383
381
  if matches_for_array?
@@ -389,47 +387,55 @@ EOT
389
387
  end
390
388
  end
391
389
 
390
+ def does_not_match?(subject)
391
+ super(subject)
392
+
393
+ if @range
394
+ does_not_match_for_range?
395
+ elsif @array
396
+ if does_not_match_for_array?
397
+ true
398
+ else
399
+ @failure_message = "#{@array} matches array in validation"
400
+ false
401
+ end
402
+ end
403
+ end
404
+
392
405
  private
393
406
 
394
407
  def matches_for_range?
395
408
  disallows_lower_value &&
396
409
  allows_minimum_value &&
397
- disallows_higher_value &&
398
- allows_maximum_value
410
+ allows_maximum_value &&
411
+ disallows_higher_value
412
+ end
413
+
414
+ def does_not_match_for_range?
415
+ allows_lower_value ||
416
+ disallows_minimum_value ||
417
+ disallows_maximum_value ||
418
+ allows_higher_value
399
419
  end
400
420
 
401
421
  def matches_for_array?
402
422
  allows_all_values_in_array? &&
403
- allows_blank_value? &&
423
+ disallows_all_values_outside_of_array? &&
404
424
  allows_nil_value? &&
405
- disallows_value_outside_of_array?
425
+ allows_blank_value?
406
426
  end
407
427
 
408
- def allows_blank_value?
409
- if @options.key?(:allow_blank)
410
- blank_values = ['', ' ', "\n", "\r", "\t", "\f"]
411
- @options[:allow_blank] == blank_values.all? { |value| allows_value_of(value) }
412
- else
413
- true
414
- end
428
+ def does_not_match_for_array?
429
+ disallows_any_values_in_array? ||
430
+ allows_any_value_outside_of_array? ||
431
+ disallows_nil_value? ||
432
+ disallows_blank_value?
415
433
  end
416
434
 
417
- def allows_nil_value?
418
- if @options.key?(:allow_nil)
419
- @options[:allow_nil] == allows_value_of(nil)
420
- else
421
- true
422
- end
423
- end
424
-
425
- def inspect_message
426
- @range.nil? ? @array.inspect : @range.inspect
427
- end
428
-
429
- def allows_all_values_in_array?
430
- @array.all? do |value|
431
- allows_value_of(value, @low_message)
432
- end
435
+ def allows_lower_value
436
+ @minimum &&
437
+ @minimum != 0 &&
438
+ allows_value_of(@minimum - 1, @low_message)
433
439
  end
434
440
 
435
441
  def disallows_lower_value
@@ -438,19 +444,43 @@ EOT
438
444
  disallows_value_of(@minimum - 1, @low_message)
439
445
  end
440
446
 
441
- def disallows_higher_value
442
- disallows_value_of(@maximum + 1, @high_message)
443
- end
444
-
445
447
  def allows_minimum_value
446
448
  allows_value_of(@minimum, @low_message)
447
449
  end
448
450
 
451
+ def disallows_minimum_value
452
+ disallows_value_of(@minimum, @low_message)
453
+ end
454
+
449
455
  def allows_maximum_value
450
456
  allows_value_of(@maximum, @high_message)
451
457
  end
452
458
 
453
- def disallows_value_outside_of_array?
459
+ def disallows_maximum_value
460
+ disallows_value_of(@maximum, @high_message)
461
+ end
462
+
463
+ def allows_higher_value
464
+ allows_value_of(@maximum + 1, @high_message)
465
+ end
466
+
467
+ def disallows_higher_value
468
+ disallows_value_of(@maximum + 1, @high_message)
469
+ end
470
+
471
+ def allows_all_values_in_array?
472
+ @array.all? do |value|
473
+ allows_value_of(value, @low_message)
474
+ end
475
+ end
476
+
477
+ def disallows_any_values_in_array?
478
+ @array.any? do |value|
479
+ disallows_value_of(value, @low_message)
480
+ end
481
+ end
482
+
483
+ def allows_any_value_outside_of_array?
454
484
  if attribute_type == :boolean
455
485
  case @array
456
486
  when [false, true], [true, false]
@@ -466,11 +496,32 @@ EOT
466
496
  end
467
497
  end
468
498
 
469
- !values_outside_of_array.any? do |value|
499
+ values_outside_of_array.any? do |value|
470
500
  allows_value_of(value, @low_message)
471
501
  end
472
502
  end
473
503
 
504
+ def disallows_all_values_outside_of_array?
505
+ if attribute_type == :boolean
506
+ case @array
507
+ when [false, true], [true, false]
508
+ Shoulda::Matchers.warn BOOLEAN_ALLOWS_BOOLEAN_MESSAGE
509
+ return true
510
+ when [nil]
511
+ if attribute_column.null
512
+ Shoulda::Matchers.warn BOOLEAN_ALLOWS_NIL_MESSAGE
513
+ return true
514
+ else
515
+ raise NonNullableBooleanError.create(@attribute)
516
+ end
517
+ end
518
+ end
519
+
520
+ values_outside_of_array.all? do |value|
521
+ disallows_value_of(value, @low_message)
522
+ end
523
+ end
524
+
474
525
  def values_outside_of_array
475
526
  if !(@array & outside_values).empty?
476
527
  raise CouldNotDetermineValueOutsideOfArray
@@ -483,8 +534,8 @@ EOT
483
534
  case attribute_type
484
535
  when :boolean
485
536
  boolean_outside_values
486
- when :fixnum
487
- [ARBITRARY_OUTSIDE_FIXNUM]
537
+ when :integer
538
+ [ARBITRARY_OUTSIDE_INTEGER]
488
539
  when :decimal
489
540
  [ARBITRARY_OUTSIDE_DECIMAL]
490
541
  when :date
@@ -538,7 +589,7 @@ EOT
538
589
 
539
590
  def column_type_to_attribute_type(type)
540
591
  case type
541
- when :integer, :float then :fixnum
592
+ when :float then :integer
542
593
  when :timestamp then :datetime
543
594
  else type
544
595
  end
@@ -548,7 +599,7 @@ EOT
548
599
  case value
549
600
  when true, false then :boolean
550
601
  when BigDecimal then :decimal
551
- when Fixnum then :fixnum
602
+ when Integer then :integer
552
603
  when Date then :date
553
604
  when DateTime then :datetime
554
605
  when Time then :time
@@ -556,6 +607,24 @@ EOT
556
607
  end
557
608
  end
558
609
 
610
+ def allows_nil_value?
611
+ @options[:allow_nil] != true || allows_value_of(nil)
612
+ end
613
+
614
+ def disallows_nil_value?
615
+ @options[:allow_nil] && disallows_value_of(nil)
616
+ end
617
+
618
+ def allows_blank_value?
619
+ @options[:allow_blank] != true ||
620
+ BLANK_VALUES.all? { |value| allows_value_of(value) }
621
+ end
622
+
623
+ def disallows_blank_value?
624
+ @options[:allow_blank] &&
625
+ BLANK_VALUES.any? { |value| disallows_value_of(value) }
626
+ end
627
+
559
628
  def inspected_array
560
629
  Shoulda::Matchers::Util.inspect_values(@array).to_sentence(
561
630
  two_words_connector: " or ",