shoulda-matchers 5.2.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97aebe50b9fb389687c99bc5dc1229a27abc5255f15e2330c9d1409d957fb689
4
- data.tar.gz: 7cd8151aae87feb29121f4b4c152f963e5cc1c7a136e0a2115344af225fb1dcd
3
+ metadata.gz: d083d22f49f99bf60d6c6bdfed7ea08ea1f838a90b4aed439d84108ebc814af9
4
+ data.tar.gz: 90cc8440d8c63da1c338306b3d9f129cc9af8dc1a80277d9e7f5b233f2bbe115
5
5
  SHA512:
6
- metadata.gz: 351c2bc9565abf151db5eeef3d17280989cdc8ec1841b0a099de8be8533767324494b04bfcc4464290852f5b022f6595fb5759e79c4534f50b6e464c94e44679
7
- data.tar.gz: 529b6d0815299c10c0f52664371e37b948ec4b8403c0096065f11649fb1849851454634f736e747820f06e27fc4d48a0616d9adfbc34b560f14a8dad364e4268
6
+ metadata.gz: '09b1dcf7e19179b50992d34cf73a86e72727cf27a1db911f2adb98fe291dc4d3d711da962d3efdbec60d2b1f280dcecd441e725a7e6a701a152ff60fdd8e340c'
7
+ data.tar.gz: 8ba54626246e133cfd86b84aba3d3b05487166d6359b2ba97256af242a057b5ff6cd40d5eae35bd35f619c9a9b0f39cc2c8b6508e299b44e2605e3cdf4f64078
@@ -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
- all_bounds_correct?
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
- def submatchers_and_results
116
- @_submatchers_and_results ||= submatchers.map do |matcher|
117
- { matcher: matcher, matched: matcher.matches?(@subject) }
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 ||= begin
59
- DisallowValueMatcher.new(disallowed_value).tap do |matcher|
60
- matcher.for(attribute)
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
@@ -108,7 +108,7 @@ module Shoulda
108
108
  obj
109
109
  end
110
110
  elsif array_column?
111
- ['an arbitary value']
111
+ ['an arbitrary value']
112
112
  elsif enum_column?
113
113
  enum_values.first
114
114
  else
@@ -118,6 +118,7 @@ module Shoulda
118
118
  when :datetime, :time, :timestamp then Time.current
119
119
  when :date then Date.new
120
120
  when :binary then '0'
121
+ when :uuid then SecureRandom.uuid
121
122
  else 'an arbitrary value'
122
123
  end
123
124
  end
@@ -33,9 +33,9 @@ module Shoulda
33
33
  #
34
34
  # class Game
35
35
  # include ActiveModel::Model
36
- # attr_accessor :supported_os
36
+ # attr_accessor :floors_with_enemies
37
37
  #
38
- # validates_exclusion_of :supported_os, in: 5..8
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(:state).in_range(1..5) }
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(:state).in_range(1..5)
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 = 'shoulda-matchers test string'.freeze
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)
@@ -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
@@ -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
@@ -26,6 +26,8 @@ require 'shoulda/matchers/active_model/numericality_matchers/comparison_matcher'
26
26
  require 'shoulda/matchers/active_model/numericality_matchers/odd_number_matcher'
27
27
  require 'shoulda/matchers/active_model/numericality_matchers/even_number_matcher'
28
28
  require 'shoulda/matchers/active_model/numericality_matchers/only_integer_matcher'
29
+ require 'shoulda/matchers/active_model/numericality_matchers/range_matcher'
30
+ require 'shoulda/matchers/active_model/numericality_matchers/submatchers'
29
31
  require 'shoulda/matchers/active_model/errors'
30
32
  require 'shoulda/matchers/active_model/have_secure_password_matcher'
31
33
 
@@ -25,8 +25,8 @@ module Shoulda
25
25
  Gem::Version.new('0')
26
26
  end
27
27
 
28
- def active_model_gte_7?
29
- Gem::Requirement.new('>= 7').satisfied_by?(active_model_version)
28
+ def active_model_st_6_1?
29
+ Gem::Requirement.new('< 6.1').satisfied_by?(active_model_version)
30
30
  end
31
31
 
32
32
  def active_model_lt_7?
@@ -92,7 +92,7 @@ module Shoulda
92
92
  if line.list_item?
93
93
  combined_lines << line
94
94
  else
95
- combined_lines.last << (" #{line}").squeeze(' ')
95
+ combined_lines.last << " #{line}".squeeze(' ')
96
96
  end
97
97
 
98
98
  combined_lines
@@ -1,6 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- VERSION = '5.2.0'.freeze
4
+ VERSION = '5.3.0'.freeze
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shoulda-matchers
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.0
4
+ version: 5.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tammer Saleh
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2022-09-17 00:00:00.000000000 Z
17
+ date: 2022-12-16 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: activesupport
@@ -79,6 +79,8 @@ files:
79
79
  - lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb
80
80
  - lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb
81
81
  - lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb
82
+ - lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb
83
+ - lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb
82
84
  - lib/shoulda/matchers/active_model/qualifiers.rb
83
85
  - lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb
84
86
  - lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb
@@ -193,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
195
  - !ruby/object:Gem::Version
194
196
  version: '0'
195
197
  requirements: []
196
- rubygems_version: 3.2.32
198
+ rubygems_version: 3.3.7
197
199
  signing_key:
198
200
  specification_version: 4
199
201
  summary: Simple one-liner tests for common Rails functionality