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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/README.md +24 -61
  4. data/lib/matchi/fix.rb +26 -111
  5. metadata +12 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7fb48f06e3e6e908cd3bd62f18a1813b33cfee44c10f42c7b6dc217b8be2127
4
- data.tar.gz: f7e74dab912262624625e5edec68939aa2218604df28bf7688a19d60b4c18fef
3
+ metadata.gz: a85b8e9ec0a7e2d5f8658db7bceb58a3618d229e5aa46e28330d8a2aff937e6d
4
+ data.tar.gz: e82e40a660b9941eae1a8fb303af87cce4dc79543281e706571719b60a8f117a
5
5
  SHA512:
6
- metadata.gz: f873e0eacdfe88f0607f215f45c1267d865017facd15ded5b890b72b543487b041a742d8b43128d7688207036ec9d40e3dc5c2a0e06418fc27e5f96903dbd026
7
- data.tar.gz: 6fba06dbd66e390080c9687f8ec77816f8ad5d070d13a989676eea1aca595edd3aeb48abf2ad30fbe00ce4c611bf7d45f35005452cad305d1c173d8559b71eb8
6
+ metadata.gz: 6c1c9899e751e1e0c9c3d0aadd830d7dbbb752e6c0c1fd160963f2d386f51db0ab1e676d0e69f4af5504fe80a25b84d4f1b8dac470924931a98946e23fab0fb0
7
+ data.tar.gz: c8aa800f53639230c536aa3773fe97102bd02e3a4dcf19ade549b05af826e1eb4d2c63495e6d424c6cf61c355fc79605cfa1beab27bd7ef94e7920e704f0a9c1
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2025 Cyril Kato
3
+ Copyright (c) 2015-2026 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
@@ -1,97 +1,60 @@
1
1
  # Matchi::Fix
2
2
 
3
- [![Version](https://img.shields.io/github/v/tag/fixrb/matchi-fix?label=Version&logo=github)](https://github.com/fixrb/matchi-fix/releases)
3
+ [![Version](https://img.shields.io/github/v/tag/fixrb/matchi-fix?label=Version&logo=github)](https://github.com/fixrb/matchi-fix/tags)
4
4
  [![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/fixrb/matchi-fix/main)
5
5
  [![License](https://img.shields.io/github/license/fixrb/matchi-fix?label=License&logo=github)](https://github.com/fixrb/matchi-fix/raw/main/LICENSE.md)
6
6
 
7
- [Matchi](https://github.com/fixrb/matchi)-compatible matcher for testing implementations against [Fix](https://github.com/fixrb/fix) specifications.
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
- And then execute:
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
- ```ruby
48
- Matchi::Fix.new { it MUST be 42 }.match? { 42 } # => true
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(:multiply, 2, 3) do
61
- it MUST eq 6
28
+ on :swim do
29
+ it MUST eq "Swoosh..."
62
30
  end
63
31
  end
64
32
 
65
- # Then use the matcher to test implementations
66
- calculator = MyCalculator.new
67
-
68
- # Using direct matcher syntax
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
- ### Error Handling
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
- On missing specifications:
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
- ```ruby
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
- On passing both specification name and specification code:
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
- ## Contact
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
- * Source code: https://github.com/fixrb/matchi-fix
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
- __Matchi::Fix__ follows [Semantic Versioning 2.0](https://semver.org/).
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
- # Specification conformance matcher that verifies objects against Fix test specifications.
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
- # This matcher allows testing objects against Fix specifications, enabling verification
9
- # of implementation conformance across different testing frameworks. It supports both
10
- # anonymous specifications defined inline and named specifications registered with Fix.
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
- # Initialize the matcher with either a name or a specification block.
55
- #
56
- # @api public
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 provided" if name.nil? && block.nil?
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
- @expected = name.nil? ? ::Fix.spec(&block) : ::Fix[name]
22
+ @spec = name.nil? ? ::Fix.spec(&block) : ::Fix[name]
77
23
  end
78
24
 
79
- # Checks if the yielded object satisfies the Fix specification.
80
- #
81
- # This method executes the Fix specification against the provided object,
82
- # verifying that all specified behaviors and conditions are met. It works
83
- # with both anonymous and named specifications.
84
- #
85
- # @api public
86
- #
87
- # @yield [] Block that returns the object to verify
88
- # @yieldreturn [Object] The object to check against the specification
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
- # Returns a human-readable description of the matcher.
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
- "fix #{@expected.inspect}"
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: 3.0.1
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: 2025-01-05 00:00:00.000000000 Z
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.21'
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.21'
27
- description: 'A Matchi-compatible matcher that allows testing objects against Fix
28
- specifications. Enables verification of implementation conformance to Fix test specifications
29
- across different testing frameworks like Minitest and RSpec. Integrates seamlessly
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://github.com/fixrb/matchi-fix
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
- post_install_message:
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.1.0
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: 3.3.27
66
- signing_key:
59
+ rubygems_version: 4.0.23
67
60
  specification_version: 4
68
- summary: Matcher for testing implementations against Fix specifications.
61
+ summary: A matcher of Matchi that tests a value against a specification of Fix
69
62
  test_files: []