matchi 3.1.1 → 3.3.1

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: 294443e7f304a5c154aa48af9c20145bba9ff2caaf090bb7336c9bb7538be19d
4
- data.tar.gz: c89f84d45eaf0923a7a023bd11b9cf54830054a178ce93e1074aea63cb7a9658
3
+ metadata.gz: 1b329fa6d8f4acd083fa33dc5a875ab30d521ad598a9a98d87e2e9fa0f3a4ea9
4
+ data.tar.gz: 122df6c5b532ae6ce316108ac76b32b5528dde249318c45272793df55a6bf240
5
5
  SHA512:
6
- metadata.gz: 9fe569142636d1acbba97f47dc7efbe38da3c02e9b19e77ab7ad723b6c03a52c03c3d8cd730a9948b4c45b21cdb6e807c29c181fd5d27f77aeee11c92c9738f4
7
- data.tar.gz: 2bd24bb8f545496e7bbb115f9bd1577f60d03e67198a0452cd2393f977f063ac0e168f699930c6819a0c478a9c208627db75f7c49a63e5f5905256ba0ef3c8ca
6
+ metadata.gz: 61dc6797282ee0c2643e57a259b45d0f3b857cc0c725bd55adc1de4fddce61d7822bb25a6dc5bfac30b160c1130a7f76d6b0912a960d8ca930c7485fbfcb84bc
7
+ data.tar.gz: 40d1d11e0b104d82bd30198de0eb1dba07f0a4fcc725f6936f8ccbec47276e2cbf91e67f4f57065f79e43dcb46b623ea4c5a085c37ac0d70b7516baad3e0d5f7
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2021 Cyril Kato
3
+ Copyright (c) 2015-2022 Cyril Kato
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -8,12 +8,13 @@
8
8
 
9
9
  > Collection of expectation matchers for Rubyists 🤹
10
10
 
11
- ![A Rubyist juggling between Matchi letters](https://github.com/fixrb/matchi/raw/main/img/matchi.jpg)
11
+ ![A Rubyist juggling between Matchi letters](https://github.com/fixrb/matchi/raw/main/img/matchi.png)
12
12
 
13
13
  ## Project goals
14
14
 
15
15
  * Adding matchers should be as simple as possible.
16
16
  * Being framework agnostic and easy to integrate.
17
+ * Avoid false positives/negatives due to malicious actual values.
17
18
 
18
19
  ## Installation
19
20
 
@@ -53,11 +54,7 @@ All examples here assume that this has been done.
53
54
 
54
55
  A __Matchi__ matcher is an object that must respond to the `matches?` method with a block as argument, and return a boolean.
55
56
 
56
- To facilitate the integration of the matchers in other tools, it is recommended to expose the expected value via the `expected` method.
57
-
58
- That's all it is.
59
-
60
- Let's see some examples.
57
+ To facilitate the integration of the matchers in other tools, __Matchi__ matchers may expose expected values via the `expected` method.
61
58
 
62
59
  ### Built-in matchers
63
60
 
@@ -81,6 +78,15 @@ matcher.expected # => :foo
81
78
  matcher.matches? { :foo } # => true
82
79
  ```
83
80
 
81
+ **Comparisons** matcher:
82
+
83
+ ```ruby
84
+ matcher = Matchi::BeWithin.new(8).of(37)
85
+
86
+ matcher.expected # => 37
87
+ matcher.matches? { 42 } # => true
88
+ ```
89
+
84
90
  **Regular expressions** matcher:
85
91
 
86
92
  ```ruby
@@ -108,6 +114,20 @@ matcher.expected # => "String"
108
114
  matcher.matches? { "foo" } # => true
109
115
  ```
110
116
 
117
+ **Predicate** matcher:
118
+
119
+ ```ruby
120
+ matcher = Matchi::Predicate.new(:be_empty)
121
+
122
+ matcher.expected # => [:empty?, [], {}, nil]
123
+ matcher.matches? { [] } # => true
124
+
125
+ matcher = Matchi::Predicate.new(:have_key, :foo)
126
+
127
+ matcher.expected # => [:has_key?, [:foo], {}, nil]
128
+ matcher.matches? { { foo: 42 } } # => true
129
+ ```
130
+
111
131
  **Change** matcher:
112
132
 
113
133
  ```ruby
@@ -183,8 +203,6 @@ require "prime"
183
203
 
184
204
  module Matchi
185
205
  class BePrime
186
- attr_reader :expected
187
-
188
206
  def matches?
189
207
  Prime.prime?(yield)
190
208
  end
@@ -193,7 +211,6 @@ end
193
211
 
194
212
  matcher = Matchi::BePrime.new
195
213
 
196
- matcher.expected # => nil
197
214
  matcher.matches? { 42 } # => false
198
215
  ```
199
216
 
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Matchi
4
+ class BeWithin
5
+ # *BeWithin of* matcher.
6
+ class Of
7
+ # @return [Numeric] An expected value.
8
+ attr_reader :expected
9
+
10
+ # Initialize the matcher with a delta and an expected value.
11
+ #
12
+ # @example
13
+ # require "matchi/be_within/of"
14
+ #
15
+ # Matchi::BeWithin::Of.new(1, 41)
16
+ #
17
+ # @param delta [Numeric] The accepted variation of the actual value.
18
+ # @param expected [Numeric] The expected value.
19
+ def initialize(delta, expected)
20
+ @delta = delta
21
+ @expected = expected
22
+ end
23
+
24
+ # Boolean comparison on the expected be_within by comparing the actual
25
+ # value and the expected value.
26
+ #
27
+ # @example
28
+ # require "matchi/be_within/of"
29
+ #
30
+ # matcher = Matchi::BeWithin::Of.new(1, 41)
31
+ #
32
+ # matcher.expected # => 41
33
+ # matcher.matches? { 42 } # => true
34
+ #
35
+ # @yieldreturn [Numeric] The block of code to execute.
36
+ #
37
+ # @return [Boolean] Comparison between the actual and the expected values.
38
+ def matches?
39
+ (expected - yield).abs <= @delta
40
+ end
41
+
42
+ # A string containing a human-readable representation of the matcher.
43
+ def inspect
44
+ "#{self.class}(#{@delta}, #{expected})"
45
+ end
46
+
47
+ # Returns a string representing the matcher.
48
+ def to_s
49
+ "be within #{@delta} of #{expected}"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative File.join("be_within", "of")
4
+
5
+ module Matchi
6
+ # Wraps the target of a be_within matcher.
7
+ class BeWithin
8
+ # Initialize a wrapper of the be_within matcher with a numeric value.
9
+ #
10
+ # @example
11
+ # require "matchi/be_within"
12
+ #
13
+ # Matchi::BeWithin.new(1)
14
+ #
15
+ # @param delta [Numeric] A numeric value.
16
+ def initialize(delta)
17
+ @delta = delta
18
+ end
19
+
20
+ # Specifies an expected numeric value.
21
+ #
22
+ # @example
23
+ # require "matchi/be_within"
24
+ #
25
+ # be_within_wrapper = Matchi::BeWithin.new(1)
26
+ # be_within_wrapper.of(41)
27
+ #
28
+ # @param expected [Numeric] The expected value.
29
+ #
30
+ # @return [#matches?] A *be_within of* matcher.
31
+ def of(expected)
32
+ Of.new(@delta, expected)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Matchi
4
+ # *Predicate* matcher.
5
+ class Predicate
6
+ # Initialize the matcher with a name and arguments.
7
+ #
8
+ # @example
9
+ # require "matchi/predicate"
10
+ #
11
+ # Matchi::Predicate.new(:be_empty)
12
+ #
13
+ # @param name [#to_s] A matcher name.
14
+ # @param args [Array] A list of parameters.
15
+ # @param kwargs [Hash] A list of keyword parameters.
16
+ # @param block [Proc] A block of code.
17
+ def initialize(name, *args, **kwargs, &block)
18
+ @name = String(name)
19
+
20
+ raise ::ArgumentError unless valid_name?
21
+
22
+ @args = args
23
+ @kwargs = kwargs
24
+ @block = block
25
+ end
26
+
27
+ # @return [Array] The method name with any arguments to send to the subject.
28
+ def expected
29
+ [method_name, @args, @kwargs, @block]
30
+ end
31
+
32
+ # Boolean comparison between the actual value and the expected value.
33
+ #
34
+ # @example
35
+ # require "matchi/predicate"
36
+ #
37
+ # matcher = Matchi::Predicate.new(:be_empty)
38
+ #
39
+ # matcher.expected # => [:empty?, [], {}, nil]
40
+ # matcher.matches? { [] } # => true
41
+ #
42
+ # @example
43
+ # require "matchi/predicate"
44
+ #
45
+ # matcher = Matchi::Predicate.new(:have_key, :foo)
46
+ #
47
+ # matcher.expected # => [:has_key?, [:foo], {}, nil]
48
+ # matcher.matches? { { foo: 42 } } # => true
49
+ #
50
+ # @yieldreturn [#object_id] The actual value to receive the method request.
51
+ #
52
+ # @return [Boolean] A boolean returned by the actual value being tested.
53
+ def matches?
54
+ value = yield.send(method_name, *@args, **@kwargs, &@block)
55
+ return value if [false, true].include?(value)
56
+
57
+ raise ::TypeError, "Boolean expected, but #{value.class} instance returned."
58
+ end
59
+
60
+ # A string containing a human-readable representation of the matcher.
61
+ def inspect
62
+ "#{self.class}(#{@name}, *#{@args.inspect}, **#{@kwargs.inspect}, &#{@block.inspect})"
63
+ end
64
+
65
+ # Returns a string representing the matcher.
66
+ def to_s
67
+ (
68
+ "#{@name.tr("_", " ")} " + [
69
+ @args.map(&:inspect).join(", "),
70
+ @kwargs.map { |k, v| "#{k}: #{v.inspect}" }.join(", "),
71
+ (@block.nil? ? "" : "&block")
72
+ ].reject { |i| i.eql?("") }.join(", ")
73
+ ).strip
74
+ end
75
+
76
+ private
77
+
78
+ # The name of the method to send to the object.
79
+ def method_name
80
+ if @name.start_with?("be_")
81
+ :"#{@name.gsub("be_", "")}?"
82
+ else
83
+ :"#{@name.gsub("have_", "has_")}?"
84
+ end
85
+ end
86
+
87
+ # Verify the matcher name structure.
88
+ def valid_name?
89
+ return false if @name.end_with?("?", "!")
90
+
91
+ @name.start_with?("be_", "have_")
92
+ end
93
+ end
94
+ end
data/lib/matchi.rb CHANGED
@@ -6,6 +6,6 @@
6
6
  module Matchi
7
7
  end
8
8
 
9
- Dir[File.join(File.dirname(__FILE__), "matchi", "*.rb")].each do |fname|
9
+ Dir[File.join(File.dirname(__FILE__), "matchi", "*.rb")].sort.each do |fname|
10
10
  require_relative fname
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matchi
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-23 00:00:00.000000000 Z
11
+ date: 2022-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -133,6 +133,8 @@ files:
133
133
  - lib/matchi.rb
134
134
  - lib/matchi/be.rb
135
135
  - lib/matchi/be_an_instance_of.rb
136
+ - lib/matchi/be_within.rb
137
+ - lib/matchi/be_within/of.rb
136
138
  - lib/matchi/change.rb
137
139
  - lib/matchi/change/by.rb
138
140
  - lib/matchi/change/by_at_least.rb
@@ -142,12 +144,14 @@ files:
142
144
  - lib/matchi/change/to.rb
143
145
  - lib/matchi/eq.rb
144
146
  - lib/matchi/match.rb
147
+ - lib/matchi/predicate.rb
145
148
  - lib/matchi/raise_exception.rb
146
149
  - lib/matchi/satisfy.rb
147
150
  homepage: https://github.com/fixrb/matchi
148
151
  licenses:
149
152
  - MIT
150
- metadata: {}
153
+ metadata:
154
+ rubygems_mfa_required: 'true'
151
155
  post_install_message:
152
156
  rdoc_options: []
153
157
  require_paths:
@@ -156,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
160
  requirements:
157
161
  - - ">="
158
162
  - !ruby/object:Gem::Version
159
- version: 2.7.0
163
+ version: 2.7.6
160
164
  required_rubygems_version: !ruby/object:Gem::Requirement
161
165
  requirements:
162
166
  - - ">="