matchi-fix 3.0.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 +24 -61
- data/lib/matchi/fix.rb +26 -111
- metadata +12 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a85b8e9ec0a7e2d5f8658db7bceb58a3618d229e5aa46e28330d8a2aff937e6d
|
|
4
|
+
data.tar.gz: e82e40a660b9941eae1a8fb303af87cce4dc79543281e706571719b60a8f117a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c1c9899e751e1e0c9c3d0aadd830d7dbbb752e6c0c1fd160963f2d386f51db0ab1e676d0e69f4af5504fe80a25b84d4f1b8dac470924931a98946e23fab0fb0
|
|
7
|
+
data.tar.gz: c8aa800f53639230c536aa3773fe97102bd02e3a4dcf19ade549b05af826e1eb4d2c63495e6d424c6cf61c355fc79605cfa1beab27bd7ef94e7920e704f0a9c1
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
|
@@ -1,97 +1,60 @@
|
|
|
1
1
|
# Matchi::Fix
|
|
2
2
|
|
|
3
|
-
[](https://github.com/fixrb/matchi-fix/
|
|
3
|
+
[](https://github.com/fixrb/matchi-fix/tags)
|
|
4
4
|
[](https://rubydoc.info/github/fixrb/matchi-fix/main)
|
|
5
5
|
[](https://github.com/fixrb/matchi-fix/raw/main/LICENSE.md)
|
|
6
6
|
|
|
7
|
-
[Matchi](https://github.com/fixrb/matchi)
|
|
7
|
+
Matchi::Fix is a matcher of [Matchi](https://github.com/fixrb/matchi) that tests a value against a specification of [Fix](https://github.com/fixrb/fix): `match?` is true when the value meets every expectation of the specification, registered under a name or written in a block. It brings the specifications of Fix wherever a matcher of Matchi goes: to [Spectus](https://github.com/fixrb/spectus), and to any test framework that takes one.
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
11
|
-
Add this line to your application's Gemfile:
|
|
12
|
-
|
|
13
11
|
```ruby
|
|
12
|
+
# Gemfile
|
|
14
13
|
gem "matchi-fix"
|
|
15
14
|
```
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```shell
|
|
20
|
-
bundle install
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Or install it yourself:
|
|
24
|
-
|
|
25
|
-
```shell
|
|
26
|
-
gem install matchi-fix
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Description
|
|
30
|
-
|
|
31
|
-
A Matchi-compatible matcher that allows testing objects against Fix specifications.
|
|
32
|
-
Enables verification of implementation conformance to Fix test specifications
|
|
33
|
-
across different testing frameworks like Minitest and RSpec. Integrates seamlessly
|
|
34
|
-
with the Fix testing framework's powerful specification system while maintaining
|
|
35
|
-
Matchi's clean matcher interface.
|
|
16
|
+
Matchi::Fix requires Ruby 3.3 or later on a system with `fork`, and depends on [Fix](https://github.com/fixrb/fix).
|
|
36
17
|
|
|
37
18
|
## Usage
|
|
38
19
|
|
|
39
|
-
To make __Matchi::Fix__ available:
|
|
40
|
-
|
|
41
20
|
```ruby
|
|
42
21
|
require "matchi/fix"
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
The Fix matcher allows testing values against Fix specifications. After requiring `matchi-fix`, you can use the `Fix` matcher in your tests through anonymous specification:
|
|
46
22
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
or through registered specification by name:
|
|
52
|
-
|
|
53
|
-
```ruby
|
|
54
|
-
# First, define a Fix specification
|
|
55
|
-
Fix :Calculator do
|
|
56
|
-
on(:add, 2, 3) do
|
|
57
|
-
it MUST eq 5
|
|
23
|
+
Fix :Duck do
|
|
24
|
+
on :walk do
|
|
25
|
+
it MUST eq "Klop klop!"
|
|
58
26
|
end
|
|
59
27
|
|
|
60
|
-
on
|
|
61
|
-
it MUST eq
|
|
28
|
+
on :swim do
|
|
29
|
+
it MUST eq "Swoosh..."
|
|
62
30
|
end
|
|
63
31
|
end
|
|
64
32
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Matchi::Fix.new(:Calculator).matches?(calculator) #=> true/false
|
|
70
|
-
```
|
|
33
|
+
class Duck
|
|
34
|
+
def walk = "Klop klop!"
|
|
35
|
+
def swim = "Swoosh..."
|
|
36
|
+
end
|
|
71
37
|
|
|
72
|
-
|
|
38
|
+
matcher = Matchi::Fix.new(:Duck)
|
|
39
|
+
matcher.match? { Duck.new } # => true
|
|
40
|
+
matcher.match? { "a decoy" } # => false
|
|
41
|
+
matcher.to_s # => "fix Duck"
|
|
73
42
|
|
|
74
|
-
|
|
43
|
+
Matchi::Fix.new { it MUST be_a_kind_of Numeric }.match? { 42 } # => true
|
|
44
|
+
Matchi::Fix.new { it MUST be_a_kind_of Numeric }.to_s # => "fix an anonymous specification"
|
|
75
45
|
|
|
76
|
-
|
|
77
|
-
Matchi::Fix.new(:NonExistent)
|
|
78
|
-
# => KeyError
|
|
46
|
+
Spectus.must(matcher).call { "a decoy" }.to_s # => "Failure: expected \"a decoy\" to fix Duck"
|
|
79
47
|
```
|
|
80
48
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
```ruby
|
|
84
|
-
Matchi::Fix.new(:SpecName) { "Spec block" }
|
|
85
|
-
# => ArgumentError
|
|
86
|
-
```
|
|
49
|
+
`Matchi::Fix.new(:Name)` finds the specification registered by `Fix :Name do … end`, and raises `KeyError` when there is none; `Matchi::Fix.new { … }` builds one from the block, as `Fix do … end` does. Given both a name and a block, or neither, it raises `ArgumentError`. The specification is found or built once, when the matcher is.
|
|
87
50
|
|
|
88
|
-
|
|
51
|
+
`match?` calls its block once, where it is called, and the value is the subject of every expectation, each context of the specification running in a child process, as Fix does it. It answers `true` when every expectation passes, a warning or an info included, and `false` when one fails or errors, without saying which: `Fix[:Name].test { … }` says which. What is not an outcome of an expectation is raised: an `Interrupt`, a child that died, a Ruby without `fork`. Since the value is given once, the contexts cannot build it anew with their lets: a specification meant for a matcher is written without `with`.
|
|
89
52
|
|
|
90
|
-
|
|
53
|
+
A `Fix::Spec` is a matcher already: `Matchi::Fix.new(:Duck)` and `Fix[:Duck]` answer the same `match?` and `to_s`, and inside a specification of Fix the word `fix(:Duck)` is that matcher. The class is the word of Matchi for it, for the other frameworks, taking the name or the block as the other matchers of Matchi take their expected value.
|
|
91
54
|
|
|
92
55
|
## Versioning
|
|
93
56
|
|
|
94
|
-
|
|
57
|
+
Matchi::Fix follows [Semantic Versioning 2.0](https://semver.org/).
|
|
95
58
|
|
|
96
59
|
## License
|
|
97
60
|
|
data/lib/matchi/fix.rb
CHANGED
|
@@ -2,127 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
require "fix"
|
|
4
4
|
|
|
5
|
+
# The matchers of Matchi: this gem adds {Matchi::Fix} to them.
|
|
5
6
|
module Matchi
|
|
6
|
-
#
|
|
7
|
+
# A matcher of Matchi that tests a value against a specification of Fix,
|
|
8
|
+
# registered under a name or written in the block: `match?` is true when
|
|
9
|
+
# the value meets every expectation of the specification.
|
|
7
10
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
# The matcher provides a bridge between Matchi's matcher interface and Fix's powerful
|
|
12
|
-
# specification system.
|
|
13
|
-
#
|
|
14
|
-
# @example Basic usage with anonymous specification
|
|
15
|
-
# matcher = Matchi::Fix.new { it MUST be 42 }
|
|
16
|
-
# matcher.match? { 42 } # => true
|
|
17
|
-
# matcher.match? { 41 } # => false
|
|
18
|
-
#
|
|
19
|
-
# @example Using named specifications
|
|
20
|
-
# # Define a Fix specification
|
|
21
|
-
# Fix :Calculator do
|
|
22
|
-
# on(:add, 2, 3) do
|
|
23
|
-
# it MUST eq 5
|
|
24
|
-
# end
|
|
25
|
-
#
|
|
26
|
-
# on(:multiply, 2, 3) do
|
|
27
|
-
# it MUST eq 6
|
|
28
|
-
# end
|
|
29
|
-
# end
|
|
30
|
-
#
|
|
31
|
-
# # Test implementations
|
|
32
|
-
# calculator = Calculator.new
|
|
33
|
-
# matcher = Matchi::Fix.new(:Calculator)
|
|
34
|
-
# matcher.match? { calculator } # => true if calculator meets spec
|
|
35
|
-
#
|
|
36
|
-
# @example Complex specifications
|
|
37
|
-
# Fix :UserValidator do
|
|
38
|
-
# on(:validate, name: "Alice", age: 30) do
|
|
39
|
-
# it MUST be true
|
|
40
|
-
# end
|
|
41
|
-
#
|
|
42
|
-
# on(:validate, name: "", age: -1) do
|
|
43
|
-
# it MUST be false
|
|
44
|
-
# end
|
|
45
|
-
# end
|
|
46
|
-
#
|
|
47
|
-
# validator = UserValidator.new
|
|
48
|
-
# matcher = Matchi::Fix.new(:UserValidator)
|
|
49
|
-
# matcher.match? { validator } # => true if validation logic is correct
|
|
50
|
-
#
|
|
51
|
-
# @see https://github.com/fixrb/fix
|
|
52
|
-
# @see https://github.com/fixrb/matchi
|
|
11
|
+
# @example
|
|
12
|
+
# Matchi::Fix.new(:Duck).match? { Duck.new } # => true
|
|
13
|
+
# Matchi::Fix.new { it MUST eq 42 }.to_s # => "fix an anonymous specification"
|
|
53
14
|
class Fix
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
# @
|
|
57
|
-
#
|
|
58
|
-
# @param name [Symbol, nil] The name of a registered Fix specification
|
|
59
|
-
# @param block [Proc, nil] A block containing the specification
|
|
60
|
-
#
|
|
61
|
-
# @raise [ArgumentError] if neither name nor block is provided
|
|
62
|
-
# @raise [ArgumentError] if both name and block are provided
|
|
63
|
-
# @raise [KeyError] if the named specification doesn't exist
|
|
64
|
-
#
|
|
65
|
-
# @return [Fix] a new instance of the matcher
|
|
66
|
-
#
|
|
67
|
-
# @example With anonymous specification
|
|
68
|
-
# Fix.new { it MUST be_positive }
|
|
69
|
-
#
|
|
70
|
-
# @example With named specification
|
|
71
|
-
# Fix.new(:Calculator)
|
|
15
|
+
# @param name [Symbol, nil] the name of a registered specification
|
|
16
|
+
# @yield the document of an anonymous specification, instead of a name
|
|
17
|
+
# @raise [ArgumentError] with both a name and a block, or neither
|
|
18
|
+
# @raise [KeyError] when no specification has that name
|
|
72
19
|
def initialize(name = nil, &block)
|
|
73
|
-
raise ::ArgumentError, "a name or a block must be
|
|
74
|
-
raise ::ArgumentError, "a name or a block must be provided" if !name.nil? && !block.nil?
|
|
20
|
+
raise ::ArgumentError, "a name or a block must be given, not both" if name.nil? == block.nil?
|
|
75
21
|
|
|
76
|
-
@
|
|
22
|
+
@spec = name.nil? ? ::Fix.spec(&block) : ::Fix[name]
|
|
77
23
|
end
|
|
78
24
|
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
# @
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# @return [Boolean] true if the object satisfies the specification
|
|
91
|
-
#
|
|
92
|
-
# @raise [ArgumentError] if no block is provided
|
|
93
|
-
#
|
|
94
|
-
# @example With anonymous specification
|
|
95
|
-
# matcher = Fix.new { it MUST be_zero }
|
|
96
|
-
# matcher.match? { 0 } # => true
|
|
97
|
-
# matcher.match? { 1 } # => false
|
|
98
|
-
#
|
|
99
|
-
# @example With named specification
|
|
100
|
-
# Fix :Sortable do
|
|
101
|
-
# on(:sort) do
|
|
102
|
-
# it MUST be_kind_of(Array)
|
|
103
|
-
# it MUST be_sorted
|
|
104
|
-
# end
|
|
105
|
-
# end
|
|
106
|
-
#
|
|
107
|
-
# matcher = Fix.new(:Sortable)
|
|
108
|
-
# matcher.match? { [1, 2, 3] } # => true if array meets spec
|
|
109
|
-
def match?
|
|
110
|
-
raise ::ArgumentError, "a block must be provided" unless block_given?
|
|
111
|
-
|
|
112
|
-
@expected.match?(yield)
|
|
25
|
+
# Tests a value: the block is called once, and its value is the subject
|
|
26
|
+
# of every expectation, each context in a child process.
|
|
27
|
+
#
|
|
28
|
+
# @yieldreturn [Object] the value
|
|
29
|
+
# @return [Boolean] whether the specification is met
|
|
30
|
+
# @raise [ArgumentError] without a block
|
|
31
|
+
# @raise [NotImplementedError] when this Ruby cannot fork
|
|
32
|
+
# @raise [Aw::ChildError] when a child died or delivered no result; what a
|
|
33
|
+
# child raised outside an expectation is raised here again
|
|
34
|
+
def match?(&)
|
|
35
|
+
@spec.match?(&)
|
|
113
36
|
end
|
|
114
37
|
|
|
115
|
-
#
|
|
116
|
-
#
|
|
117
|
-
# @api public
|
|
118
|
-
#
|
|
119
|
-
# @return [String] A string describing what this matcher verifies
|
|
120
|
-
#
|
|
121
|
-
# @example
|
|
122
|
-
# Fix.new(:Calculator).to_s # => "fix Calculator"
|
|
123
|
-
# Fix.new { it MUST be 42 }.to_s # => "fix #<Fix::Spec:...>"
|
|
38
|
+
# @return [String] `fix NAME`, or `fix an anonymous specification`
|
|
124
39
|
def to_s
|
|
125
|
-
|
|
40
|
+
@spec.to_s
|
|
126
41
|
end
|
|
127
42
|
end
|
|
128
43
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: matchi-fix
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 4.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
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: fix
|
|
@@ -16,21 +15,17 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0
|
|
18
|
+
version: '1.0'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - "~>"
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0
|
|
27
|
-
description: '
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
with the Fix testing framework''s powerful specification system while maintaining
|
|
31
|
-
Matchi''s clean matcher interface.
|
|
32
|
-
|
|
33
|
-
'
|
|
25
|
+
version: '1.0'
|
|
26
|
+
description: 'Matchi::Fix tests a value against a specification of Fix, registered
|
|
27
|
+
under a name or written in a block: match? is true when the value meets every expectation.
|
|
28
|
+
It brings the specifications of Fix wherever a matcher of Matchi goes.'
|
|
34
29
|
email: contact@cyril.email
|
|
35
30
|
executables: []
|
|
36
31
|
extensions: []
|
|
@@ -39,15 +34,14 @@ files:
|
|
|
39
34
|
- LICENSE.md
|
|
40
35
|
- README.md
|
|
41
36
|
- lib/matchi/fix.rb
|
|
42
|
-
homepage: https://
|
|
37
|
+
homepage: https://fixrb.dev/gems/matchi-fix/
|
|
43
38
|
licenses:
|
|
44
39
|
- MIT
|
|
45
40
|
metadata:
|
|
46
41
|
bug_tracker_uri: https://github.com/fixrb/matchi-fix/issues
|
|
47
42
|
documentation_uri: https://rubydoc.info/gems/matchi-fix
|
|
48
|
-
source_code_uri: https://github.com/fixrb/matchi-fix
|
|
49
43
|
rubygems_mfa_required: 'true'
|
|
50
|
-
|
|
44
|
+
source_code_uri: https://github.com/fixrb/matchi-fix
|
|
51
45
|
rdoc_options: []
|
|
52
46
|
require_paths:
|
|
53
47
|
- lib
|
|
@@ -55,15 +49,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
55
49
|
requirements:
|
|
56
50
|
- - ">="
|
|
57
51
|
- !ruby/object:Gem::Version
|
|
58
|
-
version: 3.
|
|
52
|
+
version: 3.3.0
|
|
59
53
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
54
|
requirements:
|
|
61
55
|
- - ">="
|
|
62
56
|
- !ruby/object:Gem::Version
|
|
63
57
|
version: '0'
|
|
64
58
|
requirements: []
|
|
65
|
-
rubygems_version:
|
|
66
|
-
signing_key:
|
|
59
|
+
rubygems_version: 4.0.23
|
|
67
60
|
specification_version: 4
|
|
68
|
-
summary:
|
|
61
|
+
summary: A matcher of Matchi that tests a value against a specification of Fix
|
|
69
62
|
test_files: []
|