matchi 4.1.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 730c0baf16a64842af123077150d70aee64e664ef6d5626dadf4730c1ee3425d
4
- data.tar.gz: a934654b282119e28d4fb5c4079298770f86a834d58621240737f2473f067500
3
+ metadata.gz: eed23fa6963893d67a2cc6042f1f977f4fb0012013d53775e142bf92e1333a6d
4
+ data.tar.gz: 97c4f82fa65c4d46af8babc966005d8a2db81b85b26987cf5fe3444f14ef6a25
5
5
  SHA512:
6
- metadata.gz: 75884ba2533b155d3f1e4490f9b8f6071a95aad0fca637dcdb0eee2bf60e1a3dc6bd7cab35ab93a3a7c18b680b9d789ee71bfbd7d524e6ca5ea8573520a3deec
7
- data.tar.gz: d421e42619fc45d1f1aab95ccde2a24d6a1226f4163a4afbde02fc8e693343997fa5a9a0081d72734955b2b6a25b3f9f735766702860d2184c44f403e169f442
6
+ metadata.gz: 271a0262764b04a77af4d149485395a1cf4d617c62e65dc6fab2388ad5873f3092ce08a9c273e836780623122599603a2a365c199f51ba20a2cda0f6a94f4867
7
+ data.tar.gz: baa9876cb229024e218d1ee07d4913805f9b64eaa49fab23e76b01d2fdab1f05ba4b952920cb127a3e3fe8c71990a7653d7513828e68faa056632ce0619854de
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2024 Cyril Kato
3
+ Copyright (c) 2015-2025 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
@@ -2,312 +2,235 @@
2
2
 
3
3
  [![Version](https://img.shields.io/github/v/tag/fixrb/matchi?label=Version&logo=github)](https://github.com/fixrb/matchi/tags)
4
4
  [![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/fixrb/matchi/main)
5
- [![Ruby](https://github.com/fixrb/matchi/workflows/Ruby/badge.svg?branch=main)](https://github.com/fixrb/matchi/actions?query=workflow%3Aruby+branch%3Amain)
6
- [![RuboCop](https://github.com/fixrb/matchi/workflows/RuboCop/badge.svg?branch=main)](https://github.com/fixrb/matchi/actions?query=workflow%3Arubocop+branch%3Amain)
7
5
  [![License](https://img.shields.io/github/license/fixrb/matchi?label=License&logo=github)](https://github.com/fixrb/matchi/raw/main/LICENSE.md)
8
6
 
9
- This library provides a comprehensive set of matchers for testing different aspects of your code.
10
- Each matcher is designed to handle specific verification needs while maintaining a clear and expressive syntax.
7
+ Matchi is a lightweight, framework-agnostic Ruby library that provides a comprehensive set of expectation matchers for elegant and secure testing. Its design focuses on simplicity, security, and extensibility.
11
8
 
12
9
  ![A Rubyist juggling between Matchi letters](https://github.com/fixrb/matchi/raw/main/img/matchi.png)
13
10
 
14
- ## Project goals
11
+ ## Key Features
15
12
 
16
- * Adding matchers should be as simple as possible.
17
- * Being framework agnostic and easy to integrate.
18
- * Avoid false positives/negatives due to malicious actual values.
13
+ - **Framework Agnostic**: Easily integrate with any Ruby testing framework
14
+ - **Security-Focused Design**: Built with robust type checking for most matchers
15
+ - **Simple Integration**: Minimal setup required to get started
16
+ - **Extensible**: Create custom matchers with just a few lines of code
17
+ - **Comprehensive**: Rich set of built-in matchers for common testing scenarios
18
+ - **Well Documented**: Extensive documentation with clear examples and implementation details
19
+ - **Thread Safe**: Immutable matchers design ensures thread safety in concurrent environments
19
20
 
20
- ## Installation
21
+ ### Security Considerations for Predicate Matchers
21
22
 
22
- Add this line to your application's Gemfile:
23
+ While most Matchi matchers are designed to resist type spoofing, predicate matchers (`Matchi::Predicate`) rely on Ruby's dynamic method dispatch system and can be vulnerable to method overriding:
23
24
 
24
25
  ```ruby
25
- gem "matchi"
26
- ```
27
-
28
- And then execute:
29
-
30
- ```sh
31
- bundle install
32
- ```
33
-
34
- Or install it yourself as:
35
-
36
- ```sh
37
- gem install matchi
38
- ```
39
-
40
- ## Overview
41
-
42
- __Matchi__ provides a collection of damn simple expectation matchers.
43
-
44
- ## Usage
26
+ # Example of predicate matcher vulnerability:
27
+ matcher = Matchi::Predicate.new(:be_empty)
28
+ array = []
45
29
 
46
- To make __Matchi__ available:
30
+ # Method overriding can defeat the matcher
31
+ def array.empty?
32
+ false
33
+ end
47
34
 
48
- ```ruby
49
- require "matchi"
35
+ matcher.match? { array } # => false (Even though array is empty!)
50
36
  ```
51
37
 
52
- All examples here assume that this has been done.
38
+ This limitation is inherent to Ruby's dynamic nature when working with predicate methods. If your tests require strict security guarantees, consider using direct state verification matchers instead of predicate matchers.
53
39
 
54
- ### Anatomy of a matcher
40
+ ## What is a Matchi Matcher?
55
41
 
56
- A **Matchi** matcher is a simple Ruby object that follows these requirements:
42
+ A Matchi matcher is a simple Ruby object that follows a specific contract:
57
43
 
58
- 1. It must implement a `match?` method that:
44
+ 1. **Core Interface**: Every matcher must implement a `match?` method that:
59
45
  - Accepts a block as its only parameter
60
46
  - Executes that block to get the actual value
61
47
  - Returns a boolean indicating if the actual value matches the expected criteria
62
48
 
63
- 2. Optionally, it may implement:
64
- - `to_s`: Returns a human-readable description of the match criteria
65
-
66
- ### Using Matchers
49
+ 2. **Optional Description**: Matchers can implement a `to_s` method that returns a human-readable description of the match criteria
67
50
 
68
- There are two main ways to use Matchi matchers:
69
-
70
- #### 1. Direct Class Instantiation
71
-
72
- You can create matchers directly from their classes:
51
+ Here's the simplest possible matcher:
73
52
 
74
53
  ```ruby
75
- matcher = Matchi::Eq.new("foo")
76
- matcher.match? { "foo" } # => true
77
-
78
- matcher = Matchi::BeWithin.new(0.5).of(3.0)
79
- matcher.match? { 3.2 } # => true
80
- ```
81
-
82
- #### 2. Helper Methods via Module Inclusion
83
-
84
- For a more expressive and readable syntax, you can include or extend the `Matchi` module to get access to helper methods:
54
+ module Matchi
55
+ class SimpleEqual
56
+ def initialize(expected)
57
+ @expected = expected
58
+ end
85
59
 
86
- ```ruby
87
- # Including in a class for instance methods
88
- class MyTestFramework
89
- include Matchi
60
+ def match?
61
+ raise ArgumentError, "a block must be provided" unless block_given?
90
62
 
91
- def test_equality
92
- # Helper methods available as instance methods
93
- matcher = eq("foo")
94
- assert(matcher.match? { "foo" })
63
+ @expected == yield
64
+ end
95
65
 
96
- # Method chaining works too
97
- assert(change(@array, :length).by(1).match? { @array << 1 })
66
+ def to_s
67
+ "equal #{@expected.inspect}"
68
+ end
98
69
  end
99
70
  end
100
71
 
101
- # Extending a class for class methods
102
- class MyAssertions
103
- extend Matchi
104
-
105
- def self.assert_equals(expected, actual)
106
- eq(expected).match? { actual }
107
- end
108
-
109
- def self.assert_within_range(expected, delta, actual)
110
- be_within(delta).of(expected).match? { actual }
111
- end
112
- end
72
+ # Usage:
73
+ matcher = Matchi::SimpleEqual.new(42)
74
+ matcher.match? { 42 } # => true
75
+ matcher.match? { "42" } # => false
76
+ matcher.to_s # => "equal 42"
113
77
  ```
114
78
 
115
- Available helper methods correspond to the built-in matchers:
116
- - `eq` / `eql` - For equivalence matching
117
- - `be` / `equal` - For identity matching
118
- - `be_within` - For delta comparisons
119
- - `match` - For regular expression matching
120
- - `change` - For state changes
121
- - `be_true`, `be_false`, `be_nil` - For state verification
122
- - `be_an_instance_of` - For exact type matching
123
- - `be_a_kind_of` - For type hierarchy matching
124
- - `satisfy` - For custom block-based matching
125
- - Dynamic predicate matchers (`be_*` and `have_*`)
79
+ This design provides several benefits:
80
+ - **Lazy Evaluation**: The actual value is only computed when needed via the block
81
+ - **Encapsulation**: Each matcher is a self-contained object with clear responsibilities
82
+ - **Composability**: Matchers can be easily combined and reused
83
+ - **Testability**: The contract is simple and easy to verify
126
84
 
127
- ### Built-in matchers
128
-
129
- Here is the collection of generic matchers.
130
-
131
- #### Basic Comparison Matchers
85
+ ## Installation
132
86
 
133
- ##### `Be`
134
- Checks for object identity using Ruby's `equal?` method.
135
- ```ruby
136
- Matchi::Be.new(:foo).match? { :foo } # => true (same object)
137
- Matchi::Be.new("test").match? { "test" } # => false (different objects)
138
- ```
87
+ Add to your Gemfile:
139
88
 
140
- ##### `Eq`
141
- Verifies object equivalence using Ruby's `eql?` method.
142
89
  ```ruby
143
- Matchi::Eq.new("foo").match? { "foo" } # => true (equivalent content)
144
- Matchi::Eq.new([1, 2]).match? { [1, 2] } # => true (equivalent arrays)
90
+ gem "matchi"
145
91
  ```
146
92
 
147
- #### Type and Class Matchers
93
+ Or install directly:
148
94
 
149
- ##### `BeAnInstanceOf`
150
- Verifies exact class matching (no inheritance).
151
95
  ```ruby
152
- Matchi::BeAnInstanceOf.new(String).match? { "test" } # => true
153
- Matchi::BeAnInstanceOf.new(Integer).match? { 42 } # => true
154
- Matchi::BeAnInstanceOf.new(Numeric).match? { 42 } # => false (Integer, not Numeric)
155
- ```
156
-
157
- ##### `BeAKindOf`
158
- Verifies class inheritance and module inclusion.
159
- ```ruby
160
- Matchi::BeAKindOf.new(Numeric).match? { 42 } # => true (Integer inherits from Numeric)
161
- Matchi::BeAKindOf.new(Numeric).match? { 42.0 } # => true (Float inherits from Numeric)
96
+ gem install matchi
162
97
  ```
163
98
 
164
- #### Pattern Matchers
99
+ ## Quick Start
165
100
 
166
- ##### `Match`
167
- Tests string patterns against regular expressions.
168
101
  ```ruby
169
- Matchi::Match.new(/^foo/).match? { "foobar" } # => true
170
- Matchi::Match.new(/\d+/).match? { "abc123" } # => true
171
- Matchi::Match.new(/^foo/).match? { "barfoo" } # => false
172
- ```
173
-
174
- ##### `Satisfy`
175
- Provides custom matching through a block.
176
- ```ruby
177
- Matchi::Satisfy.new { |x| x.positive? && x < 10 }.match? { 5 } # => true
178
- Matchi::Satisfy.new { |x| x.start_with?("test") }.match? { "test_file" } # => true
179
- ```
102
+ require "matchi"
180
103
 
181
- #### State Change Matchers
104
+ # Basic equality matching
105
+ Matchi::Eq.new("hello").match? { "hello" } # => true
182
106
 
183
- ##### `Change`
184
- Verifies state changes in objects with multiple variation methods:
107
+ # Type checking
108
+ Matchi::BeAKindOf.new(Numeric).match? { 42 } # => true
109
+ Matchi::BeAKindOf.new(String).match? { 42 } # => false
185
110
 
186
- ###### Basic Change
187
- ```ruby
111
+ # State change verification
188
112
  array = []
189
113
  Matchi::Change.new(array, :length).by(2).match? { array.push(1, 2) } # => true
190
114
  ```
191
115
 
192
- ###### Minimum Change
193
- ```ruby
194
- counter = 0
195
- Matchi::Change.new(counter, :to_i).by_at_least(2).match? { counter += 3 } # => true
196
- ```
116
+ ## Core Matchers
197
117
 
198
- ###### Maximum Change
199
- ```ruby
200
- value = 10
201
- Matchi::Change.new(value, :to_i).by_at_most(5).match? { value += 3 } # => true
202
- ```
118
+ ### Value Comparison
203
119
 
204
- ###### From-To Change
205
120
  ```ruby
206
- string = "hello"
207
- Matchi::Change.new(string, :upcase).from("hello").to("HELLO").match? { string.upcase! } # => true
121
+ # Exact equality (eql?)
122
+ Matchi::Eq.new("test").match? { "test" } # => true
123
+ Matchi::Eq.new([1, 2, 3]).match? { [1, 2, 3] } # => true
124
+
125
+ # Object identity (equal?)
126
+ symbol = :test
127
+ Matchi::Be.new(symbol).match? { symbol } # => true
128
+ string = "test"
129
+ Matchi::Be.new(string).match? { string.dup } # => false
208
130
  ```
209
131
 
210
- ###### To-Only Change
132
+ ### Type Checking
133
+
211
134
  ```ruby
212
- number = 1
213
- Matchi::Change.new(number, :to_i).to(5).match? { number = 5 } # => true
214
- ```
135
+ # Inheritance-aware type checking
136
+ Matchi::BeAKindOf.new(Numeric).match? { 42.0 } # => true
137
+ Matchi::BeAKindOf.new(Integer).match? { 42.0 } # => false
215
138
 
216
- #### Numeric Matchers
139
+ # Exact type matching
140
+ Matchi::BeAnInstanceOf.new(Float).match? { 42.0 } # => true
141
+ Matchi::BeAnInstanceOf.new(Numeric).match? { 42.0 } # => false
217
142
 
218
- ##### `BeWithin`
219
- Checks if a number is within a specified range of an expected value.
220
- ```ruby
221
- Matchi::BeWithin.new(0.5).of(3.0).match? { 3.2 } # => true
222
- Matchi::BeWithin.new(5).of(100).match? { 98 } # => true
143
+ # Using class names as strings
144
+ Matchi::BeAKindOf.new("Numeric").match? { 42.0 } # => true
145
+ Matchi::BeAnInstanceOf.new("Float").match? { 42.0 } # => true
223
146
  ```
224
147
 
225
- #### Behavior Matchers
148
+ ### State Changes
226
149
 
227
- ##### `RaiseException`
228
- Verifies that code raises specific exceptions.
229
150
  ```ruby
230
- Matchi::RaiseException.new(ArgumentError).match? { raise ArgumentError } # => true
231
- Matchi::RaiseException.new(NameError).match? { undefined_variable } # => true
232
- ```
151
+ # Verify exact changes
152
+ counter = 0
153
+ Matchi::Change.new(counter, :to_i).by(5).match? { counter += 5 } # => true
233
154
 
234
- ##### `Predicate`
235
- Creates matchers for methods ending in `?`.
155
+ # Verify minimum changes
156
+ Matchi::Change.new(counter, :to_i).by_at_least(2).match? { counter += 3 } # => true
236
157
 
237
- ###### Using `be_` prefix
238
- ```ruby
239
- Matchi::Predicate.new(:be_empty).match? { [] } # => true (calls empty?)
240
- Matchi::Predicate.new(:be_nil).match? { nil } # => true (calls nil?)
241
- ```
158
+ # Verify maximum changes
159
+ Matchi::Change.new(counter, :to_i).by_at_most(5).match? { counter += 3 } # => true
242
160
 
243
- ###### Using `have_` prefix
244
- ```ruby
245
- Matchi::Predicate.new(:have_key, :foo).match? { { foo: 42 } } # => true (calls has_key?)
246
- ```
161
+ # Track value transitions
162
+ string = "hello"
163
+ Matchi::Change.new(string, :to_s).from("hello").to("HELLO").match? { string.upcase! } # => true
247
164
 
248
- ### Custom matchers
165
+ # Simple change detection
166
+ array = []
167
+ Matchi::Change.new(array, :length).match? { array << 1 } # => true
249
168
 
250
- Custom matchers could easily be added to `Matchi` module to express more specific expectations.
169
+ # Check final state only
170
+ counter = 0
171
+ Matchi::Change.new(counter, :to_i).to(5).match? { counter = 5 } # => true
172
+ ```
251
173
 
252
- A **Be the answer** matcher:
174
+ ### Pattern Matching
253
175
 
254
176
  ```ruby
255
- module Matchi
256
- class BeTheAnswer
257
- def match?
258
- expected.equal?(yield)
259
- end
177
+ # Regular expressions
178
+ Matchi::Match.new(/^test/).match? { "test_string" } # => true
179
+ Matchi::Match.new(/^\d{3}-\d{2}$/).match? { "123-45" } # => true
260
180
 
261
- private
262
-
263
- def expected
264
- 42
265
- end
266
- end
267
- end
181
+ # Custom predicates with Satisfy
182
+ Matchi::Satisfy.new { |x| x.positive? && x < 10 }.match? { 5 } # => true
183
+ Matchi::Satisfy.new { |arr| arr.all?(&:even?) }.match? { [2, 4, 6] } # => true
268
184
 
269
- matcher = Matchi::BeTheAnswer.new
270
- matcher.match? { 42 } # => true
185
+ # Built-in predicates
186
+ Matchi::Predicate.new(:be_empty).match? { [] } # => true
187
+ Matchi::Predicate.new(:have_key, :name).match? { { name: "Alice" } } # => true
271
188
  ```
272
189
 
273
- A **Be prime** matcher:
190
+ ### Exception Handling
274
191
 
275
192
  ```ruby
276
- require "prime"
193
+ # Verify raised exceptions
194
+ Matchi::RaiseException.new(ArgumentError).match? { raise ArgumentError } # => true
277
195
 
278
- module Matchi
279
- class BePrime
280
- def match?
281
- Prime.prime?(yield)
282
- end
283
- end
284
- end
196
+ # Works with inheritance
197
+ Matchi::RaiseException.new(StandardError).match? { raise ArgumentError } # => true
198
+
199
+ # Using exception class names
200
+ Matchi::RaiseException.new("ArgumentError").match? { raise ArgumentError } # => true
201
+ ```
285
202
 
286
- matcher = Matchi::BePrime.new
203
+ ### Numeric Comparisons
287
204
 
288
- matcher.match? { 42 } # => false
205
+ ```ruby
206
+ # Delta comparisons
207
+ Matchi::BeWithin.new(0.5).of(3.0).match? { 3.2 } # => true
208
+ Matchi::BeWithin.new(2).of(10).match? { 9 } # => true
289
209
  ```
290
210
 
291
- A **Start with** matcher:
211
+ ## Creating Custom Matchers
212
+
213
+ Creating custom matchers is straightforward:
292
214
 
293
215
  ```ruby
294
216
  module Matchi
295
- class StartWith
296
- def initialize(expected)
297
- @expected = expected
217
+ class BePositive
218
+ def match?
219
+ yield.positive?
298
220
  end
299
221
 
300
- def match?
301
- /\A#{@expected}/.match?(yield)
222
+ def to_s
223
+ "be positive"
302
224
  end
303
225
  end
304
226
  end
305
227
 
306
- matcher = Matchi::StartWith.new("foo")
307
- matcher.match? { "foobar" } # => true
228
+ matcher = Matchi::BePositive.new
229
+ matcher.match? { 42 } # => true
230
+ matcher.match? { -1 } # => false
308
231
  ```
309
232
 
310
- ## Best Practices
233
+ ## Security Best Practices
311
234
 
312
235
  ### Proper Value Comparison Order
313
236
 
@@ -316,7 +239,6 @@ One of the most critical aspects when implementing matchers is the order of comp
316
239
  ```ruby
317
240
  # GOOD: Expected value controls the comparison
318
241
  expected_value.eql?(actual_value)
319
-
320
242
  # BAD: Actual value controls the comparison
321
243
  actual_value.eql?(expected_value)
322
244
  ```
@@ -339,7 +261,6 @@ end
339
261
 
340
262
  actual = MaliciousString.new
341
263
  expected = "expected string"
342
-
343
264
  actual.eql?(expected) # => true (incorrect result!)
344
265
  expected.eql?(actual) # => false (correct result)
345
266
  ```
@@ -353,14 +274,22 @@ def match?
353
274
  end
354
275
  ```
355
276
 
356
- ## Contact
277
+ ## Extensions
278
+
279
+ ### matchi-fix
280
+
281
+ The [matchi-fix gem](https://rubygems.org/gems/matchi-fix) extends Matchi with support for testing against [Fix](https://github.com/fixrb/fix) specifications. It provides a seamless integration between Matchi's matcher interface and Fix's powerful specification system.
282
+
283
+ ```ruby
284
+ # Add to your Gemfile
285
+ gem "matchi-fix"
286
+ ```
357
287
 
358
- * Home page: https://github.com/fixrb/matchi
359
- * Bugs/issues: https://github.com/fixrb/matchi/issues
288
+ This extension adds a `Fix` matcher that allows you to verify implementation conformance to Fix test specifications across different testing frameworks like Minitest and RSpec.
360
289
 
361
290
  ## Versioning
362
291
 
363
- __Matchi__ follows [Semantic Versioning 2.0](https://semver.org/).
292
+ Matchi follows [Semantic Versioning 2.0](https://semver.org/).
364
293
 
365
294
  ## License
366
295
 
data/lib/matchi/be.rb CHANGED
@@ -1,41 +1,83 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Matchi
4
- # *Identity* matcher.
4
+ # Identity matcher that checks if two objects are the exact same instance.
5
+ #
6
+ # This matcher verifies object identity using Ruby's Object#equal? method, which
7
+ # compares object IDs to determine if two references point to the exact same object
8
+ # in memory. This is different from equality comparison (==) which compares values.
9
+ #
10
+ # @example Basic usage with symbols
11
+ # matcher = Matchi::Be.new(:foo)
12
+ # matcher.match? { :foo } # => true
13
+ # matcher.match? { :bar } # => false
14
+ #
15
+ # @example Identity comparison with strings
16
+ # string = "test"
17
+ # matcher = Matchi::Be.new(string)
18
+ # matcher.match? { string } # => true
19
+ # matcher.match? { string.dup } # => false
20
+ # matcher.match? { "test" } # => false
21
+ #
22
+ # @example With mutable objects
23
+ # array = [1, 2, 3]
24
+ # matcher = Matchi::Be.new(array)
25
+ # matcher.match? { array } # => true
26
+ # matcher.match? { array.dup } # => false
27
+ # matcher.match? { [1, 2, 3] } # => false
28
+ #
29
+ # @see https://ruby-doc.org/core/Object.html#method-i-equal-3F
30
+ # @see Matchi::Eq
5
31
  class Be
6
- # Initialize the matcher with an object.
32
+ # Initialize the matcher with a reference object.
7
33
  #
8
- # @example
9
- # require "matchi/be"
34
+ # @api public
35
+ #
36
+ # @param expected [#equal?] The expected identical object
10
37
  #
11
- # Matchi::Be.new(:foo)
38
+ # @return [Be] a new instance of the matcher
12
39
  #
13
- # @param expected [#equal?] The expected identical object.
40
+ # @example
41
+ # string = "test"
42
+ # Be.new(string) # Match only the same string instance
14
43
  def initialize(expected)
15
44
  @expected = expected
16
45
  end
17
46
 
18
- # Boolean comparison between the actual value and the expected value.
47
+ # Checks if the yielded object is the same instance as the expected object.
19
48
  #
20
- # @example
21
- # require "matchi/be"
49
+ # This method uses Ruby's Object#equal? method, which performs identity comparison
50
+ # by comparing object IDs. Two objects are considered identical only if they are
51
+ # the exact same instance in memory.
52
+ #
53
+ # @api public
22
54
  #
23
- # matcher = Matchi::Be.new(:foo)
24
- # matcher.match? { :foo } # => true
55
+ # @yield [] Block that returns the object to check
56
+ # @yieldreturn [Object] The object to verify identity with
25
57
  #
26
- # @yieldreturn [#object_id] The actual value to compare to the expected
27
- # one.
58
+ # @return [Boolean] true if both objects are the same instance
28
59
  #
29
- # @return [Boolean] Comparison between actual and expected values.
60
+ # @raise [ArgumentError] if no block is provided
61
+ #
62
+ # @example
63
+ # obj = "test"
64
+ # matcher = Be.new(obj)
65
+ # matcher.match? { obj } # => true
66
+ # matcher.match? { obj.dup } # => false
30
67
  def match?
31
68
  raise ::ArgumentError, "a block must be provided" unless block_given?
32
69
 
33
70
  @expected.equal?(yield)
34
71
  end
35
72
 
36
- # Returns a string representing the matcher.
73
+ # Returns a human-readable description of the matcher.
74
+ #
75
+ # @api public
37
76
  #
38
- # @return [String] a human-readable description of the matcher
77
+ # @return [String] A string describing what this matcher verifies
78
+ #
79
+ # @example
80
+ # Be.new("test").to_s # => 'be "test"'
39
81
  def to_s
40
82
  "be #{@expected.inspect}"
41
83
  end