matchi 5.0.0 → 6.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/README.md +9 -4
- data/lib/matchi/match.rb +2 -1
- data/lib/matchi/raise_exception.rb +20 -10
- metadata +4 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5f6e92545e779fe4ef4a899d77213b30b26480bb4ee4daef969b1e1ea60ee7e5
|
|
4
|
+
data.tar.gz: a407ea85374dd3242d28da5609fe37320200879edb46c877a13dba1f3e377d66
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b48397862d2c8d6c8582e23445cf8c73f03f714db6bd7a73cd950f6ccc8149f8488440a827c7e31c220927e2dd7c294cc8726cd2afa1c5fb99dad2f2d8bec930
|
|
7
|
+
data.tar.gz: 5160fa06299005d522a20e8f805bd16ae5bddec4341728b92f15bbfe64c8582d756328326c29c6868636c99a9f87af74d4ee81f93e9b61f2d20a6b692f0db0cb
|
data/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Framework-agnostic matchers for Ruby. Small, explicit, and written so that the object under test cannot forge a match.
|
|
8
8
|
|
|
9
|
-

|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
@@ -91,9 +91,9 @@ Matchi::Change.new(list, :length).from(1).to(2).match? { list << 1 } # => true
|
|
|
91
91
|
|
|
92
92
|
`BeWithin.new(delta)` and `Change#from(value)` are builders, not matchers: they do not respond to `match?` until `of` or `to` completes them.
|
|
93
93
|
|
|
94
|
-
Arguments are validated when the matcher is built (`ArgumentError`); a name is resolved when the matcher runs (`NameError`, or `TypeError` when the constant is not a module). A block is always required by `match?`. Whatever the actual value or an observed method raises propagates; `RaiseException`
|
|
94
|
+
Arguments are validated when the matcher is built (`ArgumentError`); a name is resolved when the matcher runs (`NameError`, or `TypeError` when the constant is not a module, or not an exception class for `RaiseException`). A block is always required by `match?`. Whatever the actual value or an observed method raises propagates; `RaiseException` rescues what its block raises, within the limits below, not what its message filter or the resolution of its name raises.
|
|
95
95
|
|
|
96
|
-
`RaiseException`
|
|
96
|
+
`RaiseException` rescues an exception of the expected class, and any `StandardError`, `ScriptError`, `SystemStackError` or `SystemExit` (the exceptions [Defi](https://fixrb.dev/gems/defi/) keeps too), which it then compares with the expected class. Anything else, an `Interrupt`, a signal, a `NoMemoryError`, the exception with which an enclosing `Timeout` ends its block, goes through as it would with any other matcher, unless that is the class expected: `RaiseException.new(Interrupt)` rescues an `Interrupt`. An unexpected `exit` inside the block is the wrong exception, so `false`, not the end of the process.
|
|
97
97
|
|
|
98
98
|
`Change` observes a value: when the observed method returns the same unfrozen object twice (an `attr_reader` on a mutated array, say), `match?` raises instead of reporting no change. Observe `items.length`, or use `to`.
|
|
99
99
|
|
|
@@ -130,11 +130,16 @@ If you come from RSpec or Minitest, these will surprise you:
|
|
|
130
130
|
|
|
131
131
|
- `Eq` is RSpec's `eql`, not its `eq`: it compares with `eql?`, so `1` is not `1.0`, and a value object that only defines `==` never matches. Define `eql?` and `hash` on it, or use `Satisfy`. `Integer#==` hands the comparison to the other operand, which is why Matchi does not use it.
|
|
132
132
|
- `Match` takes a `Regexp` only. For a literal substring, `Matchi::Match.new(Regexp.new(Regexp.escape("a.b")))`.
|
|
133
|
-
- `RaiseException` is `raise_error`; it needs an exception class, or its name, and takes an optional message.
|
|
133
|
+
- `RaiseException` is `raise_error`; it needs an exception class, or its name, and takes an optional message. It does not rescue an `Interrupt`, a signal, a `NoMemoryError` or the exception with which an enclosing `Timeout` ends its block, unless that is the class expected, where `raise_error` rescues every `Exception`.
|
|
134
134
|
- `Change#to` demands a change: a value already equal to the target does not pass. `Change` without a refinement needs the observed method to return a value, not the mutated object.
|
|
135
135
|
- `Predicate` only calls a method of the actual value: `be_nil` calls `nil?`, but `be_truthy`, `be_falsey` and `be_a` are not predicates and do not exist. Use `Be.new(nil)`, `Satisfy`, `BeAKindOf`.
|
|
136
136
|
- There is no `and`, `or`, `not_to` or `all`: compose in your framework, with plain booleans.
|
|
137
137
|
|
|
138
|
+
## Changes in 6.0
|
|
139
|
+
|
|
140
|
+
- `RaiseException` no longer rescues every `Exception`: it rescues the expected class, and any `StandardError`, `ScriptError`, `SystemStackError` or `SystemExit`, which it compares with the expected class. An `Interrupt`, a signal, a `NoMemoryError` or the exception with which an enclosing `Timeout` ends its block goes through unless that is the class expected, where 5.0 reported it as a failed match. `RaiseException.new(Exception)` still rescues everything, as asked.
|
|
141
|
+
- The message filter of `RaiseException` and `Match` compare a plain copy of the actual `String`: a subclass could answer `valid_encoding?` for it and turn the comparison into an error.
|
|
142
|
+
|
|
138
143
|
## Changes in 5.0
|
|
139
144
|
|
|
140
145
|
- `BeAKindOf`, `BeAnInstanceOf` and `RaiseException` accept a module directly, so anonymous classes work. A name is still accepted; it must be a constant path (`"Foo::bar"` is rejected at construction) and resolve to a module, or a class for `BeAnInstanceOf` and an exception class for `RaiseException`. `BeAnInstanceOf` rejects a module that is not a class.
|
data/lib/matchi/match.rb
CHANGED
|
@@ -31,7 +31,8 @@ module Matchi
|
|
|
31
31
|
actual = yield
|
|
32
32
|
return false unless ::String === actual || ::Symbol === actual
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
# A plain copy: a subclass of String has no say in the comparison.
|
|
35
|
+
string = ::String.new(::Symbol === actual ? actual.name : actual)
|
|
35
36
|
return false unless string.valid_encoding?
|
|
36
37
|
|
|
37
38
|
begin
|
|
@@ -9,11 +9,13 @@ module Matchi
|
|
|
9
9
|
# message: a String the message must be `eql?` to, or a Regexp it must
|
|
10
10
|
# match.
|
|
11
11
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
12
|
+
# The matcher rescues an exception of the expected class, and any
|
|
13
|
+
# `StandardError`, `ScriptError`, `SystemStackError` or `SystemExit`,
|
|
14
|
+
# which it then compares with the expected class. Anything else, an
|
|
15
|
+
# `Interrupt`, a signal, a `NoMemoryError`, the exception with which an
|
|
16
|
+
# enclosing `Timeout` ends its block, goes through as it would with any
|
|
17
|
+
# other matcher, unless that is the class expected. The expected class can
|
|
18
|
+
# be given directly, or by name; see {Matchi::Constant}.
|
|
17
19
|
#
|
|
18
20
|
# @example
|
|
19
21
|
# Matchi::RaiseException.new(ZeroDivisionError).match? { 1 / 0 } # => true
|
|
@@ -45,11 +47,15 @@ module Matchi
|
|
|
45
47
|
# mistaken for an exception raised by the block.
|
|
46
48
|
klass = expected_class
|
|
47
49
|
|
|
50
|
+
# The expected class first, whatever it is; then what a block raises
|
|
51
|
+
# on its own, the exceptions Defi keeps too.
|
|
48
52
|
begin
|
|
49
53
|
yield
|
|
50
54
|
false
|
|
51
|
-
rescue
|
|
52
|
-
|
|
55
|
+
rescue klass => e
|
|
56
|
+
message?(e)
|
|
57
|
+
rescue ::StandardError, ::ScriptError, ::SystemStackError, ::SystemExit
|
|
58
|
+
false
|
|
53
59
|
end
|
|
54
60
|
end
|
|
55
61
|
|
|
@@ -85,13 +91,17 @@ module Matchi
|
|
|
85
91
|
end
|
|
86
92
|
|
|
87
93
|
# The message is whatever the exception answers to `message`, which is
|
|
88
|
-
# its own data, as with any exception; it must be a
|
|
89
|
-
# expected String or Regexp
|
|
94
|
+
# its own data, as with any exception; it must be a String, copied so
|
|
95
|
+
# that a subclass has no say, and valid. The expected String or Regexp
|
|
96
|
+
# receives the comparison.
|
|
90
97
|
def message?(exception)
|
|
91
98
|
return true if @message.nil?
|
|
92
99
|
|
|
93
100
|
message = exception.message
|
|
94
|
-
return false unless ::String === message
|
|
101
|
+
return false unless ::String === message
|
|
102
|
+
|
|
103
|
+
message = ::String.new(message)
|
|
104
|
+
return false unless message.valid_encoding?
|
|
95
105
|
|
|
96
106
|
::String === @message ? @message.eql?(message) : @message.match?(message)
|
|
97
107
|
rescue ::Encoding::CompatibilityError
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: matchi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 6.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Cyril Kato
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies: []
|
|
13
12
|
description: 'Matchi provides small, explicit expectation matchers for any Ruby testing
|
|
14
13
|
framework. The expected value always controls the comparison, so the object under
|
|
@@ -45,10 +44,10 @@ licenses:
|
|
|
45
44
|
- MIT
|
|
46
45
|
metadata:
|
|
47
46
|
bug_tracker_uri: https://github.com/fixrb/matchi/issues
|
|
47
|
+
changelog_uri: https://github.com/fixrb/matchi#changes-in-60
|
|
48
48
|
documentation_uri: https://rubydoc.info/gems/matchi
|
|
49
49
|
rubygems_mfa_required: 'true'
|
|
50
50
|
source_code_uri: https://github.com/fixrb/matchi
|
|
51
|
-
post_install_message:
|
|
52
51
|
rdoc_options: []
|
|
53
52
|
require_paths:
|
|
54
53
|
- lib
|
|
@@ -63,8 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
63
62
|
- !ruby/object:Gem::Version
|
|
64
63
|
version: '0'
|
|
65
64
|
requirements: []
|
|
66
|
-
rubygems_version:
|
|
67
|
-
signing_key:
|
|
65
|
+
rubygems_version: 4.0.23
|
|
68
66
|
specification_version: 4
|
|
69
67
|
summary: Framework-agnostic matchers for secure Ruby testing
|
|
70
68
|
test_files: []
|