matchi 3.3.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.md +1 -1
- data/README.md +151 -101
- data/lib/matchi/be.rb +7 -13
- data/lib/matchi/be_a_kind_of.rb +81 -0
- data/lib/matchi/be_an_instance_of.rb +91 -21
- data/lib/matchi/be_within/of.rb +11 -13
- data/lib/matchi/be_within.rb +4 -1
- data/lib/matchi/change/by.rb +11 -14
- data/lib/matchi/change/by_at_least.rb +12 -14
- data/lib/matchi/change/by_at_most.rb +12 -14
- data/lib/matchi/change/from/to.rb +10 -14
- data/lib/matchi/change/from.rb +3 -1
- data/lib/matchi/change/to.rb +10 -14
- data/lib/matchi/change.rb +10 -9
- data/lib/matchi/eq.rb +7 -13
- data/lib/matchi/match.rb +9 -13
- data/lib/matchi/predicate.rb +8 -19
- data/lib/matchi/raise_exception.rb +30 -17
- data/lib/matchi/satisfy.rb +8 -12
- data/lib/matchi.rb +1 -1
- metadata +6 -120
data/lib/matchi/be_within/of.rb
CHANGED
@@ -4,9 +4,6 @@ module Matchi
|
|
4
4
|
class BeWithin
|
5
5
|
# *BeWithin of* matcher.
|
6
6
|
class Of
|
7
|
-
# @return [Numeric] An expected value.
|
8
|
-
attr_reader :expected
|
9
|
-
|
10
7
|
# Initialize the matcher with a delta and an expected value.
|
11
8
|
#
|
12
9
|
# @example
|
@@ -17,6 +14,10 @@ module Matchi
|
|
17
14
|
# @param delta [Numeric] The accepted variation of the actual value.
|
18
15
|
# @param expected [Numeric] The expected value.
|
19
16
|
def initialize(delta, expected)
|
17
|
+
raise ::ArgumentError, "delta must be a Numeric" unless delta.is_a?(::Numeric)
|
18
|
+
raise ::ArgumentError, "expected must be a Numeric" unless expected.is_a?(::Numeric)
|
19
|
+
raise ::ArgumentError, "delta must be non-negative" if delta.negative?
|
20
|
+
|
20
21
|
@delta = delta
|
21
22
|
@expected = expected
|
22
23
|
end
|
@@ -28,25 +29,22 @@ module Matchi
|
|
28
29
|
# require "matchi/be_within/of"
|
29
30
|
#
|
30
31
|
# matcher = Matchi::BeWithin::Of.new(1, 41)
|
31
|
-
#
|
32
|
-
# matcher.expected # => 41
|
33
|
-
# matcher.matches? { 42 } # => true
|
32
|
+
# matcher.match? { 42 } # => true
|
34
33
|
#
|
35
34
|
# @yieldreturn [Numeric] The block of code to execute.
|
36
35
|
#
|
37
36
|
# @return [Boolean] Comparison between the actual and the expected values.
|
38
|
-
def
|
39
|
-
|
40
|
-
end
|
37
|
+
def match?
|
38
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
41
39
|
|
42
|
-
|
43
|
-
def inspect
|
44
|
-
"#{self.class}(#{@delta}, #{expected})"
|
40
|
+
(@expected - yield).abs <= @delta
|
45
41
|
end
|
46
42
|
|
47
43
|
# Returns a string representing the matcher.
|
44
|
+
#
|
45
|
+
# @return [String] a human-readable description of the matcher
|
48
46
|
def to_s
|
49
|
-
"be within #{@delta} of #{expected}"
|
47
|
+
"be within #{@delta} of #{@expected}"
|
50
48
|
end
|
51
49
|
end
|
52
50
|
end
|
data/lib/matchi/be_within.rb
CHANGED
@@ -14,6 +14,9 @@ module Matchi
|
|
14
14
|
#
|
15
15
|
# @param delta [Numeric] A numeric value.
|
16
16
|
def initialize(delta)
|
17
|
+
raise ::ArgumentError, "delta must be a Numeric" unless delta.is_a?(::Numeric)
|
18
|
+
raise ::ArgumentError, "delta must be non-negative" if delta.negative?
|
19
|
+
|
17
20
|
@delta = delta
|
18
21
|
end
|
19
22
|
|
@@ -27,7 +30,7 @@ module Matchi
|
|
27
30
|
#
|
28
31
|
# @param expected [Numeric] The expected value.
|
29
32
|
#
|
30
|
-
# @return [#
|
33
|
+
# @return [#match?] A *be_within of* matcher.
|
31
34
|
def of(expected)
|
32
35
|
Of.new(@delta, expected)
|
33
36
|
end
|
data/lib/matchi/change/by.rb
CHANGED
@@ -4,9 +4,6 @@ module Matchi
|
|
4
4
|
class Change
|
5
5
|
# *Change by* matcher.
|
6
6
|
class By
|
7
|
-
# @return [#object_id] An expected delta.
|
8
|
-
attr_reader :expected
|
9
|
-
|
10
7
|
# Initialize the matcher with an object and a block.
|
11
8
|
#
|
12
9
|
# @example
|
@@ -20,6 +17,9 @@ module Matchi
|
|
20
17
|
# @param state [Proc] A block of code to execute to get the
|
21
18
|
# state of the object.
|
22
19
|
def initialize(expected, &state)
|
20
|
+
raise ::ArgumentError, "expected must be a Numeric" unless expected.is_a?(::Numeric)
|
21
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
22
|
+
|
23
23
|
@expected = expected
|
24
24
|
@state = state
|
25
25
|
end
|
@@ -33,30 +33,27 @@ module Matchi
|
|
33
33
|
# object = []
|
34
34
|
#
|
35
35
|
# matcher = Matchi::Change::By.new(1) { object.length }
|
36
|
-
#
|
37
|
-
# matcher.expected # => 1
|
38
|
-
# matcher.matches? { object << "foo" } # => true
|
36
|
+
# matcher.match? { object << "foo" } # => true
|
39
37
|
#
|
40
38
|
# @yieldreturn [#object_id] The block of code to execute.
|
41
39
|
#
|
42
40
|
# @return [Boolean] Comparison between the value before and after the
|
43
41
|
# code execution.
|
44
|
-
def
|
42
|
+
def match?
|
43
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
44
|
+
|
45
45
|
value_before = @state.call
|
46
46
|
yield
|
47
47
|
value_after = @state.call
|
48
48
|
|
49
|
-
expected == (value_after - value_before)
|
50
|
-
end
|
51
|
-
|
52
|
-
# A string containing a human-readable representation of the matcher.
|
53
|
-
def inspect
|
54
|
-
"#{self.class}(#{expected.inspect})"
|
49
|
+
@expected == (value_after - value_before)
|
55
50
|
end
|
56
51
|
|
57
52
|
# Returns a string representing the matcher.
|
53
|
+
#
|
54
|
+
# @return [String] a human-readable description of the matcher
|
58
55
|
def to_s
|
59
|
-
"change by #{expected.inspect}"
|
56
|
+
"change by #{@expected.inspect}"
|
60
57
|
end
|
61
58
|
end
|
62
59
|
end
|
@@ -4,9 +4,6 @@ module Matchi
|
|
4
4
|
class Change
|
5
5
|
# *Change by at least* matcher.
|
6
6
|
class ByAtLeast
|
7
|
-
# @return [#object_id] An expected delta.
|
8
|
-
attr_reader :expected
|
9
|
-
|
10
7
|
# Initialize the matcher with an object and a block.
|
11
8
|
#
|
12
9
|
# @example
|
@@ -20,6 +17,10 @@ module Matchi
|
|
20
17
|
# @param state [Proc] A block of code to execute to get the
|
21
18
|
# state of the object.
|
22
19
|
def initialize(expected, &state)
|
20
|
+
raise ::ArgumentError, "expected must be a Numeric" unless expected.is_a?(::Numeric)
|
21
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
22
|
+
raise ::ArgumentError, "expected must be non-negative" if expected.negative?
|
23
|
+
|
23
24
|
@expected = expected
|
24
25
|
@state = state
|
25
26
|
end
|
@@ -33,30 +34,27 @@ module Matchi
|
|
33
34
|
# object = []
|
34
35
|
#
|
35
36
|
# matcher = Matchi::Change::ByAtLeast.new(1) { object.length }
|
36
|
-
#
|
37
|
-
# matcher.expected # => 1
|
38
|
-
# matcher.matches? { object << "foo" } # => true
|
37
|
+
# matcher.match? { object << "foo" } # => true
|
39
38
|
#
|
40
39
|
# @yieldreturn [#object_id] The block of code to execute.
|
41
40
|
#
|
42
41
|
# @return [Boolean] Comparison between the value before and after the
|
43
42
|
# code execution.
|
44
|
-
def
|
43
|
+
def match?
|
44
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
45
|
+
|
45
46
|
value_before = @state.call
|
46
47
|
yield
|
47
48
|
value_after = @state.call
|
48
49
|
|
49
|
-
expected <= (value_after - value_before)
|
50
|
-
end
|
51
|
-
|
52
|
-
# A string containing a human-readable representation of the matcher.
|
53
|
-
def inspect
|
54
|
-
"#{self.class}(#{expected.inspect})"
|
50
|
+
@expected <= (value_after - value_before)
|
55
51
|
end
|
56
52
|
|
57
53
|
# Returns a string representing the matcher.
|
54
|
+
#
|
55
|
+
# @return [String] a human-readable description of the matcher
|
58
56
|
def to_s
|
59
|
-
"change by at least #{expected.inspect}"
|
57
|
+
"change by at least #{@expected.inspect}"
|
60
58
|
end
|
61
59
|
end
|
62
60
|
end
|
@@ -4,9 +4,6 @@ module Matchi
|
|
4
4
|
class Change
|
5
5
|
# *Change by at most* matcher.
|
6
6
|
class ByAtMost
|
7
|
-
# @return [#object_id] An expected delta.
|
8
|
-
attr_reader :expected
|
9
|
-
|
10
7
|
# Initialize the matcher with an object and a block.
|
11
8
|
#
|
12
9
|
# @example
|
@@ -20,6 +17,10 @@ module Matchi
|
|
20
17
|
# @param state [Proc] A block of code to execute to get the
|
21
18
|
# state of the object.
|
22
19
|
def initialize(expected, &state)
|
20
|
+
raise ::ArgumentError, "expected must be a Numeric" unless expected.is_a?(::Numeric)
|
21
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
22
|
+
raise ::ArgumentError, "expected must be non-negative" if expected.negative?
|
23
|
+
|
23
24
|
@expected = expected
|
24
25
|
@state = state
|
25
26
|
end
|
@@ -33,30 +34,27 @@ module Matchi
|
|
33
34
|
# object = []
|
34
35
|
#
|
35
36
|
# matcher = Matchi::Change::ByAtMost.new(1) { object.length }
|
36
|
-
#
|
37
|
-
# matcher.expected # => 1
|
38
|
-
# matcher.matches? { object << "foo" } # => true
|
37
|
+
# matcher.match? { object << "foo" } # => true
|
39
38
|
#
|
40
39
|
# @yieldreturn [#object_id] The block of code to execute.
|
41
40
|
#
|
42
41
|
# @return [Boolean] Comparison between the value before and after the
|
43
42
|
# code execution.
|
44
|
-
def
|
43
|
+
def match?
|
44
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
45
|
+
|
45
46
|
value_before = @state.call
|
46
47
|
yield
|
47
48
|
value_after = @state.call
|
48
49
|
|
49
|
-
expected >= (value_after - value_before)
|
50
|
-
end
|
51
|
-
|
52
|
-
# A string containing a human-readable representation of the matcher.
|
53
|
-
def inspect
|
54
|
-
"#{self.class}(#{expected.inspect})"
|
50
|
+
@expected >= (value_after - value_before)
|
55
51
|
end
|
56
52
|
|
57
53
|
# Returns a string representing the matcher.
|
54
|
+
#
|
55
|
+
# @return [String] a human-readable description of the matcher
|
58
56
|
def to_s
|
59
|
-
"change by at most #{expected.inspect}"
|
57
|
+
"change by at most #{@expected.inspect}"
|
60
58
|
end
|
61
59
|
end
|
62
60
|
end
|
@@ -5,9 +5,6 @@ module Matchi
|
|
5
5
|
class From
|
6
6
|
# *Change from to* matcher.
|
7
7
|
class To
|
8
|
-
# @return [#object_id] An expected new value.
|
9
|
-
attr_reader :expected
|
10
|
-
|
11
8
|
# Initialize the matcher with two objects and a block.
|
12
9
|
#
|
13
10
|
# @example
|
@@ -22,6 +19,8 @@ module Matchi
|
|
22
19
|
# @param state [Proc] A block of code to execute to
|
23
20
|
# get the state of the object.
|
24
21
|
def initialize(expected_init, expected_new_value, &state)
|
22
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
23
|
+
|
25
24
|
@expected_init = expected_init
|
26
25
|
@expected = expected_new_value
|
27
26
|
@state = state
|
@@ -36,32 +35,29 @@ module Matchi
|
|
36
35
|
# object = "foo"
|
37
36
|
#
|
38
37
|
# matcher = Matchi::Change::From::To.new("foo", "FOO") { object.to_s }
|
39
|
-
#
|
40
|
-
# matcher.expected # => "FOO"
|
41
|
-
# matcher.matches? { object.upcase! } # => true
|
38
|
+
# matcher.match? { object.upcase! } # => true
|
42
39
|
#
|
43
40
|
# @yieldreturn [#object_id] The block of code to execute.
|
44
41
|
#
|
45
42
|
# @return [Boolean] Comparison between the value before and after the
|
46
43
|
# code execution.
|
47
|
-
def
|
44
|
+
def match?
|
45
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
46
|
+
|
48
47
|
value_before = @state.call
|
49
48
|
return false unless @expected_init == value_before
|
50
49
|
|
51
50
|
yield
|
52
51
|
value_after = @state.call
|
53
52
|
|
54
|
-
expected == value_after
|
55
|
-
end
|
56
|
-
|
57
|
-
# A string containing a human-readable representation of the matcher.
|
58
|
-
def inspect
|
59
|
-
"#{self.class}(#{@expected_init.inspect}, #{expected.inspect})"
|
53
|
+
@expected == value_after
|
60
54
|
end
|
61
55
|
|
62
56
|
# Returns a string representing the matcher.
|
57
|
+
#
|
58
|
+
# @return [String] a human-readable description of the matcher
|
63
59
|
def to_s
|
64
|
-
"change from #{@expected_init.inspect} to #{expected.inspect}"
|
60
|
+
"change from #{@expected_init.inspect} to #{@expected.inspect}"
|
65
61
|
end
|
66
62
|
end
|
67
63
|
end
|
data/lib/matchi/change/from.rb
CHANGED
@@ -19,6 +19,8 @@ module Matchi
|
|
19
19
|
# @param state [Proc] A block of code to execute to get the
|
20
20
|
# state of the object.
|
21
21
|
def initialize(expected, &state)
|
22
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
23
|
+
|
22
24
|
@expected = expected
|
23
25
|
@state = state
|
24
26
|
end
|
@@ -35,7 +37,7 @@ module Matchi
|
|
35
37
|
#
|
36
38
|
# @param expected_new_value [#object_id] The new value to expect.
|
37
39
|
#
|
38
|
-
# @return [#
|
40
|
+
# @return [#match?] A *change from to* matcher.
|
39
41
|
def to(expected_new_value)
|
40
42
|
To.new(@expected, expected_new_value, &@state)
|
41
43
|
end
|
data/lib/matchi/change/to.rb
CHANGED
@@ -4,9 +4,6 @@ module Matchi
|
|
4
4
|
class Change
|
5
5
|
# *Change to* matcher.
|
6
6
|
class To
|
7
|
-
# @return [#object_id] An expected new value.
|
8
|
-
attr_reader :expected
|
9
|
-
|
10
7
|
# Initialize the matcher with an object and a block.
|
11
8
|
#
|
12
9
|
# @example
|
@@ -20,6 +17,8 @@ module Matchi
|
|
20
17
|
# @param state [Proc] A block of code to execute to get the
|
21
18
|
# state of the object.
|
22
19
|
def initialize(expected, &state)
|
20
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
21
|
+
|
23
22
|
@expected = expected
|
24
23
|
@state = state
|
25
24
|
end
|
@@ -33,29 +32,26 @@ module Matchi
|
|
33
32
|
# object = "foo"
|
34
33
|
#
|
35
34
|
# matcher = Matchi::Change::To.new("FOO") { object.to_s }
|
36
|
-
#
|
37
|
-
# matcher.expected # => "FOO"
|
38
|
-
# matcher.matches? { object.upcase! } # => true
|
35
|
+
# matcher.match? { object.upcase! } # => true
|
39
36
|
#
|
40
37
|
# @yieldreturn [#object_id] The block of code to execute.
|
41
38
|
#
|
42
39
|
# @return [Boolean] Comparison between the value before and after the
|
43
40
|
# code execution.
|
44
|
-
def
|
41
|
+
def match?
|
42
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
43
|
+
|
45
44
|
yield
|
46
45
|
value_after = @state.call
|
47
46
|
|
48
|
-
expected == value_after
|
49
|
-
end
|
50
|
-
|
51
|
-
# A string containing a human-readable representation of the matcher.
|
52
|
-
def inspect
|
53
|
-
"#{self.class}(#{expected.inspect})"
|
47
|
+
@expected == value_after
|
54
48
|
end
|
55
49
|
|
56
50
|
# Returns a string representing the matcher.
|
51
|
+
#
|
52
|
+
# @return [String] a human-readable description of the matcher
|
57
53
|
def to_s
|
58
|
-
"change to #{expected.inspect}"
|
54
|
+
"change to #{@expected.inspect}"
|
59
55
|
end
|
60
56
|
end
|
61
57
|
end
|
data/lib/matchi/change.rb
CHANGED
@@ -19,10 +19,11 @@ module Matchi
|
|
19
19
|
#
|
20
20
|
# @param object [#object_id] An object.
|
21
21
|
# @param method [Symbol] The name of a method.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
def initialize(object, method, ...)
|
23
|
+
raise ::ArgumentError, "method must be a Symbol" unless method.is_a?(::Symbol)
|
24
|
+
raise ::ArgumentError, "object must respond to method" unless object.respond_to?(method)
|
25
|
+
|
26
|
+
@state = -> { object.send(method, ...) }
|
26
27
|
end
|
27
28
|
|
28
29
|
# Specifies a minimum delta of the expected change.
|
@@ -37,7 +38,7 @@ module Matchi
|
|
37
38
|
#
|
38
39
|
# @param minimum_delta [#object_id] The minimum delta of the expected change.
|
39
40
|
#
|
40
|
-
# @return [#
|
41
|
+
# @return [#match?] A *change by at least* matcher.
|
41
42
|
def by_at_least(minimum_delta)
|
42
43
|
ByAtLeast.new(minimum_delta, &@state)
|
43
44
|
end
|
@@ -54,7 +55,7 @@ module Matchi
|
|
54
55
|
#
|
55
56
|
# @param maximum_delta [#object_id] The maximum delta of the expected change.
|
56
57
|
#
|
57
|
-
# @return [#
|
58
|
+
# @return [#match?] A *change by at most* matcher.
|
58
59
|
def by_at_most(maximum_delta)
|
59
60
|
ByAtMost.new(maximum_delta, &@state)
|
60
61
|
end
|
@@ -71,7 +72,7 @@ module Matchi
|
|
71
72
|
#
|
72
73
|
# @param delta [#object_id] The delta of the expected change.
|
73
74
|
#
|
74
|
-
# @return [#
|
75
|
+
# @return [#match?] A *change by* matcher.
|
75
76
|
def by(delta)
|
76
77
|
By.new(delta, &@state)
|
77
78
|
end
|
@@ -86,7 +87,7 @@ module Matchi
|
|
86
87
|
#
|
87
88
|
# @param old_value [#object_id] The original value.
|
88
89
|
#
|
89
|
-
# @return [#
|
90
|
+
# @return [#match?] A *change from* wrapper.
|
90
91
|
def from(old_value)
|
91
92
|
From.new(old_value, &@state)
|
92
93
|
end
|
@@ -101,7 +102,7 @@ module Matchi
|
|
101
102
|
#
|
102
103
|
# @param new_value [#object_id] The new value to expect.
|
103
104
|
#
|
104
|
-
# @return [#
|
105
|
+
# @return [#match?] A *change to* matcher.
|
105
106
|
def to(new_value)
|
106
107
|
To.new(new_value, &@state)
|
107
108
|
end
|
data/lib/matchi/eq.rb
CHANGED
@@ -3,9 +3,6 @@
|
|
3
3
|
module Matchi
|
4
4
|
# *Equivalence* matcher.
|
5
5
|
class Eq
|
6
|
-
# @return [#eql?] An expected equivalent object.
|
7
|
-
attr_reader :expected
|
8
|
-
|
9
6
|
# Initialize the matcher with an object.
|
10
7
|
#
|
11
8
|
# @example
|
@@ -24,26 +21,23 @@ module Matchi
|
|
24
21
|
# require "matchi/eq"
|
25
22
|
#
|
26
23
|
# matcher = Matchi::Eq.new("foo")
|
27
|
-
#
|
28
|
-
# matcher.expected # => "foo"
|
29
|
-
# matcher.matches? { "foo" } # => true
|
24
|
+
# matcher.match? { "foo" } # => true
|
30
25
|
#
|
31
26
|
# @yieldreturn [#object_id] The actual value to compare to the expected
|
32
27
|
# one.
|
33
28
|
#
|
34
29
|
# @return [Boolean] Comparison between actual and expected values.
|
35
|
-
def
|
36
|
-
|
37
|
-
end
|
30
|
+
def match?
|
31
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
38
32
|
|
39
|
-
|
40
|
-
def inspect
|
41
|
-
"#{self.class}(#{expected.inspect})"
|
33
|
+
@expected.eql?(yield)
|
42
34
|
end
|
43
35
|
|
44
36
|
# Returns a string representing the matcher.
|
37
|
+
#
|
38
|
+
# @return [String] a human-readable description of the matcher
|
45
39
|
def to_s
|
46
|
-
"eq #{expected.inspect}"
|
40
|
+
"eq #{@expected.inspect}"
|
47
41
|
end
|
48
42
|
end
|
49
43
|
end
|
data/lib/matchi/match.rb
CHANGED
@@ -3,9 +3,6 @@
|
|
3
3
|
module Matchi
|
4
4
|
# *Regular expressions* matcher.
|
5
5
|
class Match
|
6
|
-
# @return [#match] A regular expression.
|
7
|
-
attr_reader :expected
|
8
|
-
|
9
6
|
# Initialize the matcher with an instance of Regexp.
|
10
7
|
#
|
11
8
|
# @example
|
@@ -15,6 +12,8 @@ module Matchi
|
|
15
12
|
#
|
16
13
|
# @param expected [#match] A regular expression.
|
17
14
|
def initialize(expected)
|
15
|
+
raise ::ArgumentError, "expected must respond to match?" unless expected.respond_to?(:match?)
|
16
|
+
|
18
17
|
@expected = expected
|
19
18
|
end
|
20
19
|
|
@@ -24,26 +23,23 @@ module Matchi
|
|
24
23
|
# require "matchi/match"
|
25
24
|
#
|
26
25
|
# matcher = Matchi::Match.new(/^foo$/)
|
27
|
-
#
|
28
|
-
# matcher.expected # => /^foo$/
|
29
|
-
# matcher.matches? { "foo" } # => true
|
26
|
+
# matcher.match? { "foo" } # => true
|
30
27
|
#
|
31
28
|
# @yieldreturn [#object_id] The actual value to compare to the expected
|
32
29
|
# one.
|
33
30
|
#
|
34
31
|
# @return [Boolean] Comparison between actual and expected values.
|
35
|
-
def
|
36
|
-
|
37
|
-
end
|
32
|
+
def match?
|
33
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
38
34
|
|
39
|
-
|
40
|
-
def inspect
|
41
|
-
"#{self.class}(#{expected.inspect})"
|
35
|
+
@expected.match?(yield)
|
42
36
|
end
|
43
37
|
|
44
38
|
# Returns a string representing the matcher.
|
39
|
+
#
|
40
|
+
# @return [String] a human-readable description of the matcher
|
45
41
|
def to_s
|
46
|
-
"match #{expected.inspect}"
|
42
|
+
"match #{@expected.inspect}"
|
47
43
|
end
|
48
44
|
end
|
49
45
|
end
|
data/lib/matchi/predicate.rb
CHANGED
@@ -16,53 +16,42 @@ module Matchi
|
|
16
16
|
# @param block [Proc] A block of code.
|
17
17
|
def initialize(name, *args, **kwargs, &block)
|
18
18
|
@name = String(name)
|
19
|
-
|
20
|
-
raise ::ArgumentError unless valid_name?
|
19
|
+
raise ::ArgumentError, "invalid predicate name format" unless valid_name?
|
21
20
|
|
22
21
|
@args = args
|
23
22
|
@kwargs = kwargs
|
24
23
|
@block = block
|
25
24
|
end
|
26
25
|
|
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
26
|
# Boolean comparison between the actual value and the expected value.
|
33
27
|
#
|
34
28
|
# @example
|
35
29
|
# require "matchi/predicate"
|
36
30
|
#
|
37
31
|
# matcher = Matchi::Predicate.new(:be_empty)
|
38
|
-
#
|
39
|
-
# matcher.expected # => [:empty?, [], {}, nil]
|
40
|
-
# matcher.matches? { [] } # => true
|
32
|
+
# matcher.match? { [] } # => true
|
41
33
|
#
|
42
34
|
# @example
|
43
35
|
# require "matchi/predicate"
|
44
36
|
#
|
45
37
|
# matcher = Matchi::Predicate.new(:have_key, :foo)
|
46
|
-
#
|
47
|
-
# matcher.expected # => [:has_key?, [:foo], {}, nil]
|
48
|
-
# matcher.matches? { { foo: 42 } } # => true
|
38
|
+
# matcher.match? { { foo: 42 } } # => true
|
49
39
|
#
|
50
40
|
# @yieldreturn [#object_id] The actual value to receive the method request.
|
51
41
|
#
|
52
42
|
# @return [Boolean] A boolean returned by the actual value being tested.
|
53
|
-
def
|
43
|
+
def match?
|
44
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
45
|
+
|
54
46
|
value = yield.send(method_name, *@args, **@kwargs, &@block)
|
55
47
|
return value if [false, true].include?(value)
|
56
48
|
|
57
49
|
raise ::TypeError, "Boolean expected, but #{value.class} instance returned."
|
58
50
|
end
|
59
51
|
|
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
52
|
# Returns a string representing the matcher.
|
53
|
+
#
|
54
|
+
# @return [String] a human-readable description of the matcher
|
66
55
|
def to_s
|
67
56
|
(
|
68
57
|
"#{@name.tr("_", " ")} " + [
|
@@ -3,9 +3,6 @@
|
|
3
3
|
module Matchi
|
4
4
|
# *Expecting errors* matcher.
|
5
5
|
class RaiseException
|
6
|
-
# @return [String] The expected exception name.
|
7
|
-
attr_reader :expected
|
8
|
-
|
9
6
|
# Initialize the matcher with a descendant of class Exception.
|
10
7
|
#
|
11
8
|
# @example
|
@@ -16,6 +13,10 @@ module Matchi
|
|
16
13
|
# @param expected [Exception, #to_s] The expected exception name.
|
17
14
|
def initialize(expected)
|
18
15
|
@expected = String(expected)
|
16
|
+
return if /\A[A-Z]/.match?(@expected)
|
17
|
+
|
18
|
+
raise ::ArgumentError,
|
19
|
+
"expected must start with an uppercase letter (got: #{@expected})"
|
19
20
|
end
|
20
21
|
|
21
22
|
# Boolean comparison between the actual value and the expected value.
|
@@ -24,30 +25,42 @@ module Matchi
|
|
24
25
|
# require "matchi/raise_exception"
|
25
26
|
#
|
26
27
|
# matcher = Matchi::RaiseException.new(NameError)
|
27
|
-
#
|
28
|
-
# matcher.expected # => "NameError"
|
29
|
-
# matcher.matches? { Boom } # => true
|
28
|
+
# matcher.match? { Boom } # => true
|
30
29
|
#
|
31
30
|
# @yieldreturn [#object_id] The actual value to compare to the expected
|
32
31
|
# one.
|
33
32
|
#
|
34
33
|
# @return [Boolean] Comparison between actual and expected values.
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
false
|
41
|
-
end
|
34
|
+
def match?
|
35
|
+
raise ::ArgumentError, "a block must be provided" unless block_given?
|
36
|
+
|
37
|
+
klass = expected_class
|
38
|
+
raise ::ArgumentError, "expected exception class must inherit from Exception" unless klass <= ::Exception
|
42
39
|
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
begin
|
41
|
+
yield
|
42
|
+
false
|
43
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
44
|
+
e.class <= klass # Checks if the class of the thrown exception is klass or one of its subclasses
|
45
|
+
end
|
46
46
|
end
|
47
47
|
|
48
48
|
# Returns a string representing the matcher.
|
49
|
+
#
|
50
|
+
# @return [String] a human-readable description of the matcher
|
49
51
|
def to_s
|
50
|
-
"raise exception #{expected}"
|
52
|
+
"raise exception #{@expected}"
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# Resolves the expected class name to an actual Class object.
|
58
|
+
# This method handles both string and symbol class names through constant resolution.
|
59
|
+
#
|
60
|
+
# @return [Class] the resolved class
|
61
|
+
# @raise [NameError] if the class doesn't exist
|
62
|
+
def expected_class
|
63
|
+
::Object.const_get(@expected)
|
51
64
|
end
|
52
65
|
end
|
53
66
|
end
|