matchi 2.4.0 → 3.2.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.
@@ -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,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative File.join("change", "by_at_least")
4
+ require_relative File.join("change", "by_at_most")
5
+ require_relative File.join("change", "by")
6
+ require_relative File.join("change", "from")
7
+ require_relative File.join("change", "to")
8
+
9
+ module Matchi
10
+ # Wraps the target of a change matcher.
11
+ class Change
12
+ # Initialize a wrapper of the change matcher with an object and the name of
13
+ # one of its methods.
14
+ #
15
+ # @example
16
+ # require "matchi/change"
17
+ #
18
+ # Matchi::Change.new("foo", :to_s)
19
+ #
20
+ # @param object [#object_id] An object.
21
+ # @param method [Symbol] The name of a method.
22
+ # @param args [Array] A list of arguments.
23
+ # @param kwargs [Hash] A list of keyword arguments.
24
+ def initialize(object, method, *args, **kwargs, &block)
25
+ @state = -> { object.send(method, *args, **kwargs, &block) }
26
+ end
27
+
28
+ # Specifies a minimum delta of the expected change.
29
+ #
30
+ # @example
31
+ # require "matchi/change"
32
+ #
33
+ # object = []
34
+ #
35
+ # change_wrapper = Matchi::Change.new(object, :length)
36
+ # change_wrapper.by_at_least(1)
37
+ #
38
+ # @param minimum_delta [#object_id] The minimum delta of the expected change.
39
+ #
40
+ # @return [#matches?] A *change by at least* matcher.
41
+ def by_at_least(minimum_delta)
42
+ ByAtLeast.new(minimum_delta, &@state)
43
+ end
44
+
45
+ # Specifies a maximum delta of the expected change.
46
+ #
47
+ # @example
48
+ # require "matchi/change"
49
+ #
50
+ # object = []
51
+ #
52
+ # change_wrapper = Matchi::Change.new(object, :length)
53
+ # change_wrapper.by_at_most(1)
54
+ #
55
+ # @param maximum_delta [#object_id] The maximum delta of the expected change.
56
+ #
57
+ # @return [#matches?] A *change by at most* matcher.
58
+ def by_at_most(maximum_delta)
59
+ ByAtMost.new(maximum_delta, &@state)
60
+ end
61
+
62
+ # Specifies the delta of the expected change.
63
+ #
64
+ # @example
65
+ # require "matchi/change"
66
+ #
67
+ # object = []
68
+ #
69
+ # change_wrapper = Matchi::Change.new(object, :length)
70
+ # change_wrapper.by(1)
71
+ #
72
+ # @param delta [#object_id] The delta of the expected change.
73
+ #
74
+ # @return [#matches?] A *change by* matcher.
75
+ def by(delta)
76
+ By.new(delta, &@state)
77
+ end
78
+
79
+ # Specifies the original value.
80
+ #
81
+ # @example
82
+ # require "matchi/change"
83
+ #
84
+ # change_wrapper = Matchi::Change.new("foo", :to_s)
85
+ # change_wrapper.from("foo")
86
+ #
87
+ # @param old_value [#object_id] The original value.
88
+ #
89
+ # @return [#matches?] A *change from* wrapper.
90
+ def from(old_value)
91
+ From.new(old_value, &@state)
92
+ end
93
+
94
+ # Specifies the new value to expect.
95
+ #
96
+ # @example
97
+ # require "matchi/change"
98
+ #
99
+ # change_wrapper = Matchi::Change.new("foo", :to_s)
100
+ # change_wrapper.to("FOO")
101
+ #
102
+ # @param new_value [#object_id] The new value to expect.
103
+ #
104
+ # @return [#matches?] A *change to* matcher.
105
+ def to(new_value)
106
+ To.new(new_value, &@state)
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Matchi
4
+ class Change
5
+ # *Change by* matcher.
6
+ class By
7
+ # @return [#object_id] An expected delta.
8
+ attr_reader :expected
9
+
10
+ # Initialize the matcher with an object and a block.
11
+ #
12
+ # @example
13
+ # require "matchi/change/by"
14
+ #
15
+ # object = []
16
+ #
17
+ # Matchi::Change::By.new(1) { object.length }
18
+ #
19
+ # @param expected [#object_id] An expected delta.
20
+ # @param state [Proc] A block of code to execute to get the
21
+ # state of the object.
22
+ def initialize(expected, &state)
23
+ @expected = expected
24
+ @state = state
25
+ end
26
+
27
+ # Boolean comparison on the expected change by comparing the value
28
+ # before and after the code execution.
29
+ #
30
+ # @example
31
+ # require "matchi/change/by"
32
+ #
33
+ # object = []
34
+ #
35
+ # matcher = Matchi::Change::By.new(1) { object.length }
36
+ #
37
+ # matcher.expected # => 1
38
+ # matcher.matches? { object << "foo" } # => true
39
+ #
40
+ # @yieldreturn [#object_id] The block of code to execute.
41
+ #
42
+ # @return [Boolean] Comparison between the value before and after the
43
+ # code execution.
44
+ def matches?
45
+ value_before = @state.call
46
+ yield
47
+ value_after = @state.call
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})"
55
+ end
56
+
57
+ # Returns a string representing the matcher.
58
+ def to_s
59
+ "change by #{expected.inspect}"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Matchi
4
+ class Change
5
+ # *Change by at least* matcher.
6
+ class ByAtLeast
7
+ # @return [#object_id] An expected delta.
8
+ attr_reader :expected
9
+
10
+ # Initialize the matcher with an object and a block.
11
+ #
12
+ # @example
13
+ # require "matchi/change/by_at_least"
14
+ #
15
+ # object = []
16
+ #
17
+ # Matchi::Change::ByAtLeast.new(1) { object.length }
18
+ #
19
+ # @param expected [#object_id] An expected delta.
20
+ # @param state [Proc] A block of code to execute to get the
21
+ # state of the object.
22
+ def initialize(expected, &state)
23
+ @expected = expected
24
+ @state = state
25
+ end
26
+
27
+ # Boolean comparison on the expected change by comparing the value
28
+ # before and after the code execution.
29
+ #
30
+ # @example
31
+ # require "matchi/change/by_at_least"
32
+ #
33
+ # object = []
34
+ #
35
+ # matcher = Matchi::Change::ByAtLeast.new(1) { object.length }
36
+ #
37
+ # matcher.expected # => 1
38
+ # matcher.matches? { object << "foo" } # => true
39
+ #
40
+ # @yieldreturn [#object_id] The block of code to execute.
41
+ #
42
+ # @return [Boolean] Comparison between the value before and after the
43
+ # code execution.
44
+ def matches?
45
+ value_before = @state.call
46
+ yield
47
+ value_after = @state.call
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})"
55
+ end
56
+
57
+ # Returns a string representing the matcher.
58
+ def to_s
59
+ "change by at least #{expected.inspect}"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Matchi
4
+ class Change
5
+ # *Change by at most* matcher.
6
+ class ByAtMost
7
+ # @return [#object_id] An expected delta.
8
+ attr_reader :expected
9
+
10
+ # Initialize the matcher with an object and a block.
11
+ #
12
+ # @example
13
+ # require "matchi/change/by_at_most"
14
+ #
15
+ # object = []
16
+ #
17
+ # Matchi::Change::ByAtMost.new(1) { object.length }
18
+ #
19
+ # @param expected [#object_id] An expected delta.
20
+ # @param state [Proc] A block of code to execute to get the
21
+ # state of the object.
22
+ def initialize(expected, &state)
23
+ @expected = expected
24
+ @state = state
25
+ end
26
+
27
+ # Boolean comparison on the expected change by comparing the value
28
+ # before and after the code execution.
29
+ #
30
+ # @example
31
+ # require "matchi/change/by_at_most"
32
+ #
33
+ # object = []
34
+ #
35
+ # matcher = Matchi::Change::ByAtMost.new(1) { object.length }
36
+ #
37
+ # matcher.expected # => 1
38
+ # matcher.matches? { object << "foo" } # => true
39
+ #
40
+ # @yieldreturn [#object_id] The block of code to execute.
41
+ #
42
+ # @return [Boolean] Comparison between the value before and after the
43
+ # code execution.
44
+ def matches?
45
+ value_before = @state.call
46
+ yield
47
+ value_after = @state.call
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})"
55
+ end
56
+
57
+ # Returns a string representing the matcher.
58
+ def to_s
59
+ "change by at most #{expected.inspect}"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative File.join("from", "to")
4
+
5
+ module Matchi
6
+ class Change
7
+ # *Change from to* wrapper.
8
+ class From
9
+ # Initialize the wrapper with an object and a block.
10
+ #
11
+ # @example
12
+ # require "matchi/change/from"
13
+ #
14
+ # object = "foo"
15
+ #
16
+ # Matchi::Change::From.new("foo") { object.to_s }
17
+ #
18
+ # @param expected [#object_id] An expected initial value.
19
+ # @param state [Proc] A block of code to execute to get the
20
+ # state of the object.
21
+ def initialize(expected, &state)
22
+ @expected = expected
23
+ @state = state
24
+ end
25
+
26
+ # Specifies the new value to expect.
27
+ #
28
+ # @example
29
+ # require "matchi/change/from"
30
+ #
31
+ # object = "foo"
32
+ #
33
+ # change_from_wrapper = Matchi::Change::From.new("foo") { object.to_s }
34
+ # change_from_wrapper.to("FOO")
35
+ #
36
+ # @param expected_new_value [#object_id] The new value to expect.
37
+ #
38
+ # @return [#matches?] A *change from to* matcher.
39
+ def to(expected_new_value)
40
+ To.new(@expected, expected_new_value, &@state)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Matchi
4
+ class Change
5
+ class From
6
+ # *Change from to* matcher.
7
+ class To
8
+ # @return [#object_id] An expected new value.
9
+ attr_reader :expected
10
+
11
+ # Initialize the matcher with two objects and a block.
12
+ #
13
+ # @example
14
+ # require "matchi/change/from/to"
15
+ #
16
+ # object = "foo"
17
+ #
18
+ # Matchi::Change::From::To.new("foo", "FOO") { object.to_s }
19
+ #
20
+ # @param expected_init [#object_id] An expected initial value.
21
+ # @param expected_new_value [#object_id] An expected new value.
22
+ # @param state [Proc] A block of code to execute to
23
+ # get the state of the object.
24
+ def initialize(expected_init, expected_new_value, &state)
25
+ @expected_init = expected_init
26
+ @expected = expected_new_value
27
+ @state = state
28
+ end
29
+
30
+ # Boolean comparison on the expected change by comparing the value
31
+ # before and after the code execution.
32
+ #
33
+ # @example
34
+ # require "matchi/change/from/to"
35
+ #
36
+ # object = "foo"
37
+ #
38
+ # matcher = Matchi::Change::From::To.new("foo", "FOO") { object.to_s }
39
+ #
40
+ # matcher.expected # => "FOO"
41
+ # matcher.matches? { object.upcase! } # => true
42
+ #
43
+ # @yieldreturn [#object_id] The block of code to execute.
44
+ #
45
+ # @return [Boolean] Comparison between the value before and after the
46
+ # code execution.
47
+ def matches?
48
+ value_before = @state.call
49
+ return false unless @expected_init == value_before
50
+
51
+ yield
52
+ value_after = @state.call
53
+
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})"
60
+ end
61
+
62
+ # Returns a string representing the matcher.
63
+ def to_s
64
+ "change from #{@expected_init.inspect} to #{expected.inspect}"
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end