spectus 3.0.10 → 3.1.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 +66 -77
- data/lib/spectus.rb +2 -4
- data/lib/spectus/exam.rb +56 -0
- data/lib/spectus/expectation_target.rb +87 -70
- data/lib/spectus/requirement_level/base.rb +48 -73
- data/lib/spectus/requirement_level/may.rb +17 -0
- data/lib/spectus/requirement_level/must.rb +17 -0
- data/lib/spectus/requirement_level/should.rb +17 -0
- data/lib/spectus/result/common.rb +174 -0
- data/lib/spectus/result/fail.rb +40 -17
- data/lib/spectus/result/pass.rb +48 -21
- metadata +22 -24
- data/lib/spectus/matchers.rb +0 -33
- data/lib/spectus/report.rb +0 -92
- data/lib/spectus/requirement_level/high.rb +0 -27
- data/lib/spectus/requirement_level/low.rb +0 -27
- data/lib/spectus/requirement_level/medium.rb +0 -27
- data/lib/spectus/result/base.rb +0 -112
- data/lib/spectus/sandbox.rb +0 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61974cb7f8cc0f5e3feaab04f902099123a2f71fa815af3d5d5230b49a8dc573
|
4
|
+
data.tar.gz: bd85d771520589ee1a10ff672f610e04ad00bdb254343241f7aacc32a1af8f5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: baf4571bbc6b585b87b6d98752bf4ba1880c99fb05bfbb1d66d0587aadc8ec9fb3481cacb5bd8f193a53eca5269002a92d1a9900ee7e9ad8874e5950a7b5dd8a
|
7
|
+
data.tar.gz: b0819b033292607bc53ba1c690f09dad9c95566e70e102f02cde1a9b0c6e42d6b58db1dd16d5ece1423e8bef94841c3d9b37775d2f08e205e2a054df079ad97e
|
data/README.md
CHANGED
@@ -1,24 +1,12 @@
|
|
1
1
|
# Spectus
|
2
2
|
|
3
|
-
[][travis]
|
3
|
+
[][travis]
|
4
4
|
[][codeclimate]
|
5
5
|
[][gem]
|
6
|
-
[][inchpages]
|
7
|
+
[][rubydoc]
|
8
8
|
|
9
|
-
> Expectation library with [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt)'s requirement levels
|
10
|
-
|
11
|
-
## Contact
|
12
|
-
|
13
|
-
* Home page: https://github.com/fixrb/spectus
|
14
|
-
* Bugs/issues: https://github.com/fixrb/spectus/issues
|
15
|
-
* Support: https://stackoverflow.com/questions/tagged/spectus
|
16
|
-
|
17
|
-
## Rubies
|
18
|
-
|
19
|
-
* [MRI](https://www.ruby-lang.org/)
|
20
|
-
* [Rubinius](http://rubini.us/)
|
21
|
-
* [JRuby](http://jruby.org/)
|
9
|
+
> Expectation library with [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt)'s requirement levels 🚥
|
22
10
|
|
23
11
|
## Installation
|
24
12
|
|
@@ -40,6 +28,8 @@ Or install it yourself as:
|
|
40
28
|
|
41
29
|
An expectation is an assertion that is either `true` or `false`.
|
42
30
|
|
31
|
+
There are several scenarios:
|
32
|
+
|
43
33
|
| Requirement levels | **MUST** | **SHOULD** | **MAY** |
|
44
34
|
| ------------------------- | -------- | ---------- | ------- |
|
45
35
|
| Implemented & Matched | `true` | `true` | `true` |
|
@@ -47,39 +37,43 @@ An expectation is an assertion that is either `true` or `false`.
|
|
47
37
|
| Implemented & Exception | `false` | `false` | `false` |
|
48
38
|
| Not implemented | `false` | `false` | `true` |
|
49
39
|
|
50
|
-
|
40
|
+
Thus,
|
51
41
|
|
52
|
-
|
42
|
+
* when an expectation is `true`, a `Spectus::Result::Pass` instance is returned;
|
43
|
+
* when an expectation is `false`, a `Spectus::Result::Fail` exception is raised.
|
53
44
|
|
54
|
-
|
55
|
-
* when the requirement level of an expectation does not end with `!`, the test is performed without isolation.
|
45
|
+
Both results share a common interface, and can be classified respectively as:
|
56
46
|
|
57
|
-
|
47
|
+
* a ✅ _success_, a ⚠️ _warning_ or an 💡 _info_;
|
48
|
+
* a ❌ _failure_ or an 💥 _error_.
|
58
49
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
50
|
+
## Code Isolation
|
51
|
+
|
52
|
+
When executing expectations, side-effects may occur.
|
53
|
+
Because they may or may not be desired, each requirement level has 2 versions:
|
54
|
+
|
55
|
+
* if it does not end with `!`, its test is performed without isolation;
|
56
|
+
* if it ends with `!`, its test is performed in isolation.
|
65
57
|
|
66
58
|
Example of test without isolation:
|
67
59
|
|
68
60
|
```ruby
|
61
|
+
include Spectus
|
69
62
|
greeting = 'Hello, world!'
|
70
63
|
it { greeting.gsub!('world', 'Alice') }.MUST eql 'Hello, Alice!'
|
71
|
-
# =>
|
64
|
+
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
|
72
65
|
greeting # => "Hello, Alice!"
|
73
66
|
```
|
74
67
|
|
75
|
-
|
76
|
-
|
77
|
-
There are two cases:
|
78
|
-
|
79
|
-
* when an expectation is `true`, an instance of `Spectus::Result::Pass` is returned;
|
80
|
-
* when an expectation is `false`, an instance of `Spectus::Result::Fail` is raised.
|
68
|
+
Example of test in isolation:
|
81
69
|
|
82
|
-
|
70
|
+
```ruby
|
71
|
+
include Spectus
|
72
|
+
greeting = 'Hello, world!'
|
73
|
+
it { greeting.gsub!('world', 'Alice') }.MUST! eql 'Hello, Alice!'
|
74
|
+
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
|
75
|
+
greeting # => "Hello, world!"
|
76
|
+
```
|
83
77
|
|
84
78
|
## Usage
|
85
79
|
|
@@ -89,24 +83,24 @@ To begin with, let's include __Spectus__:
|
|
89
83
|
include Spectus
|
90
84
|
```
|
91
85
|
|
92
|
-
### Absolute
|
86
|
+
### Absolute Requirement
|
93
87
|
|
94
|
-
Given the
|
88
|
+
Given the "`ルビー`" object, when it receives `valid_encoding?` method, then it **MUST** be `true`:
|
95
89
|
|
96
90
|
```ruby
|
97
91
|
it { 'ルビー'.valid_encoding? }.MUST be_true
|
98
|
-
# =>
|
92
|
+
# => Spectus::Result::Pass(actual: true, error: nil, expected: nil, got: true, matcher: :be_true, negate: false, level: :MUST, valid: true)
|
99
93
|
```
|
100
94
|
|
101
95
|
The result of the test shows that the spec passed.
|
102
96
|
|
103
|
-
### Absolute
|
97
|
+
### Absolute Prohibition
|
104
98
|
|
105
|
-
Given the `
|
99
|
+
Given the "`foo`" object, when it receives `length` method, then it **MUST NOT** raise the `NoMethodError` exception:
|
106
100
|
|
107
101
|
```ruby
|
108
102
|
it { 'foo'.length }.MUST_NOT raise_exception NoMethodError
|
109
|
-
# =>
|
103
|
+
# => Spectus::Result::Pass(actual: 3, error: nil, expected: NoMethodError, got: true, matcher: :raise_exception, negate: true, level: :MUST, valid: true)
|
110
104
|
```
|
111
105
|
|
112
106
|
The result of the test shows that the spec passed.
|
@@ -117,74 +111,69 @@ Given the `BasicObject` object, when it receives `superclass` method, then it **
|
|
117
111
|
|
118
112
|
```ruby
|
119
113
|
it { BasicObject.superclass }.SHOULD equal NilClass
|
120
|
-
# =>
|
114
|
+
# => Spectus::Result::Pass(actual: nil, error: nil, expected: NilClass, got: false, matcher: :equal, negate: false, level: :SHOULD, valid: false)
|
121
115
|
```
|
122
116
|
|
123
117
|
Instead of the expected `NilClass` class, its sole instance (which is `nil`) was returned.
|
124
118
|
However, because there isn't any exception, the result of the test shows that the spec passed.
|
125
119
|
|
126
|
-
### Not
|
120
|
+
### Not Recommended
|
127
121
|
|
128
|
-
Given the `
|
122
|
+
Given the "`1`" object, when it receives `+(1)` method, then it **SHOULD NOT** return the "`11`" value:
|
129
123
|
|
130
124
|
```ruby
|
131
125
|
it { '1' + 1 }.SHOULD_NOT eql '11'
|
132
|
-
# Spectus::Result::Fail:
|
133
|
-
# from (irb):5
|
134
|
-
# from ./bin/console:7:in `<main>'
|
126
|
+
# raise Spectus::Result::Fail(actual: nil, error: #<TypeError: no implicit conversion of Integer into String>, expected: "11", got: nil, matcher: :eql, negate: true, level: :SHOULD, valid: false)
|
135
127
|
```
|
136
128
|
|
137
129
|
There was a `TypeError` exception, the result of the test shows that the spec failed.
|
138
130
|
|
139
131
|
### Optional
|
140
132
|
|
141
|
-
Given the `
|
133
|
+
Given the "`foo`" object, when it receives `blank?` method, then it **MAY** be `false`:
|
142
134
|
|
143
135
|
```ruby
|
144
136
|
it { 'foo'.blank? }.MAY be_false
|
145
|
-
# =>
|
137
|
+
# => Spectus::Result::Pass(actual: nil, error: #<NoMethodError: undefined method `blank?' for "foo":String>, expected: nil, got: nil, matcher: :be_false, negate: false, level: :MAY, valid: false)
|
146
138
|
```
|
147
139
|
|
148
|
-
The optional `blank?` method is not implemented (unlike in [Ruby on Rails](
|
140
|
+
The optional `blank?` method is not implemented (unlike in [Ruby on Rails](https://api.rubyonrails.org/classes/Object.html#method-i-blank-3F), for instance), so the result of the test shows that the spec passed.
|
149
141
|
|
150
|
-
|
142
|
+
### More Examples
|
151
143
|
|
152
|
-
|
153
|
-
|
154
|
-
Although these checksums do not prevent malicious users from tampering with a
|
155
|
-
built Gem they can be used for basic integrity verification purposes.
|
144
|
+
An exhaustive list of examples can also be viewed here:
|
145
|
+
[test.rb](https://github.com/fixrb/spectus/raw/master/test.rb)
|
156
146
|
|
157
|
-
|
158
|
-
example:
|
147
|
+
## Contact
|
159
148
|
|
160
|
-
|
161
|
-
|
149
|
+
* Home page: https://github.com/fixrb/spectus
|
150
|
+
* Bugs/issues: https://github.com/fixrb/spectus/issues
|
162
151
|
|
163
|
-
##
|
152
|
+
## Rubies
|
164
153
|
|
165
|
-
|
154
|
+
* [MRI](https://www.ruby-lang.org/)
|
155
|
+
* [Rubinius](https://rubinius.com/)
|
156
|
+
* [JRuby](https://www.jruby.org/)
|
166
157
|
|
167
|
-
##
|
158
|
+
## Versioning
|
168
159
|
|
169
|
-
|
170
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
171
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
172
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
173
|
-
5. Create a new Pull Request
|
160
|
+
__Spectus__ follows [Semantic Versioning 2.0](https://semver.org/).
|
174
161
|
|
175
162
|
## License
|
176
163
|
|
177
|
-
|
178
|
-
|
179
|
-
[gem]: https://rubygems.org/gems/spectus
|
180
|
-
[travis]: https://travis-ci.org/fixrb/spectus
|
181
|
-
[codeclimate]: https://codeclimate.com/github/fixrb/spectus
|
182
|
-
[gemnasium]: https://gemnasium.com/fixrb/spectus
|
183
|
-
[inchpages]: http://inch-ci.org/github/fixrb/spectus
|
184
|
-
[rubydoc]: http://rubydoc.info/gems/spectus/frames
|
164
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
185
165
|
|
186
166
|
***
|
187
167
|
|
188
|
-
|
168
|
+
<p>
|
169
|
+
This project is sponsored by:<br />
|
170
|
+
<a href="https://sashite.com/"><img
|
171
|
+
src="https://github.com/fixrb/spectus/raw/master/img/sashite.png"
|
172
|
+
alt="Sashite" /></a>
|
173
|
+
</p>
|
189
174
|
|
190
|
-
[
|
175
|
+
[gem]: https://rubygems.org/gems/spectus
|
176
|
+
[travis]: https://travis-ci.org/fixrb/spectus
|
177
|
+
[codeclimate]: https://codeclimate.com/github/fixrb/spectus
|
178
|
+
[inchpages]: https://inch-ci.org/github/fixrb/spectus
|
179
|
+
[rubydoc]: https://rubydoc.info/gems/spectus/frames
|
data/lib/spectus.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'matchi/helper'
|
4
4
|
|
5
5
|
# Namespace for the Spectus library.
|
6
6
|
#
|
7
|
-
# @api public
|
8
|
-
#
|
9
7
|
# @example It MUST equal 42.
|
10
8
|
# require 'spectus'
|
11
9
|
# it { 42 }.MUST equal 42 # => #<Spectus::Result::Pass...>
|
12
10
|
module Spectus
|
13
|
-
include
|
11
|
+
include ::Matchi::Helper
|
14
12
|
|
15
13
|
# Expectations are built with this method.
|
16
14
|
#
|
data/lib/spectus/exam.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'defi'
|
4
|
+
|
5
|
+
module Spectus
|
6
|
+
# This class evaluate the expectation with the passed block.
|
7
|
+
class Exam
|
8
|
+
# Execute the untested code from the passed block against the matcher.
|
9
|
+
#
|
10
|
+
# rubocop:disable Lint/RescueException
|
11
|
+
#
|
12
|
+
# @param callable [#call] The callable object to test.
|
13
|
+
# @param isolation [Boolean] Compute actual in isolation?
|
14
|
+
# @param negate [Boolean] Positive or negative assertion?
|
15
|
+
# @param matcher [#matches?] The matcher.
|
16
|
+
def initialize(callable:, isolation:, negate:, matcher:)
|
17
|
+
@got = negate ^ matcher.matches? do
|
18
|
+
value = if isolation
|
19
|
+
send_call.to!(callable)
|
20
|
+
else
|
21
|
+
send_call.to(callable)
|
22
|
+
end
|
23
|
+
|
24
|
+
@actual = value.object
|
25
|
+
|
26
|
+
value.call
|
27
|
+
end
|
28
|
+
rescue ::Exception => e
|
29
|
+
@actual = nil
|
30
|
+
@exception = e
|
31
|
+
end
|
32
|
+
# rubocop:enable Lint/RescueException
|
33
|
+
|
34
|
+
# @return [#object_id] The actual value.
|
35
|
+
attr_reader :actual
|
36
|
+
|
37
|
+
# @return [Exception, nil] An exception.
|
38
|
+
attr_reader :exception
|
39
|
+
|
40
|
+
# @return [Boolean, nil] Report to the spec requirement level if the
|
41
|
+
# expectation is true or false.
|
42
|
+
attr_reader :got
|
43
|
+
|
44
|
+
# @return [Defi::Challenge] The challenge for the callable object.
|
45
|
+
def send_call
|
46
|
+
::Defi.send(:call)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Report to the spec requirement level if the test pass or fail.
|
50
|
+
#
|
51
|
+
# @return [Boolean] Report if the test pass or fail?
|
52
|
+
def valid?
|
53
|
+
exception.nil? ? got : false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,49 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'defi'
|
4
|
-
|
5
3
|
module Spectus
|
6
4
|
# Wraps the target of an expectation.
|
7
5
|
#
|
8
|
-
# @api public
|
9
|
-
#
|
10
6
|
# @example
|
11
7
|
# it { actual value } # => ExpectationTarget wrapping the block
|
12
8
|
class ExpectationTarget
|
13
|
-
# Create a new
|
9
|
+
# Create a new expectation target
|
14
10
|
#
|
15
|
-
# @
|
16
|
-
|
17
|
-
|
18
|
-
def initialize(&subject)
|
19
|
-
@subject = subject
|
20
|
-
@challenges = [block_challenge]
|
11
|
+
# @param callable [Proc] The object to test.
|
12
|
+
def initialize(&callable)
|
13
|
+
@callable = callable
|
21
14
|
end
|
22
15
|
|
23
|
-
# rubocop:disable
|
24
|
-
# rubocop:disable Naming/UncommunicativeMethodParamName
|
16
|
+
# rubocop:disable Naming/MethodName
|
25
17
|
|
26
|
-
# @api public
|
27
|
-
#
|
28
18
|
# This word, or the terms "REQUIRED" or "SHALL", mean that the
|
29
19
|
# definition is an absolute requirement of the specification.
|
30
20
|
#
|
31
21
|
# @example _Absolute requirement_ definition
|
32
22
|
# it { 'foo'.upcase }.MUST eql 'FOO'
|
33
23
|
#
|
34
|
-
# @param
|
24
|
+
# @param matcher [#matches?] The matcher.
|
35
25
|
#
|
36
26
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
37
|
-
def MUST(
|
38
|
-
RequirementLevel::
|
27
|
+
def MUST(matcher)
|
28
|
+
RequirementLevel::Must.new(
|
29
|
+
callable: callable,
|
30
|
+
isolation: false,
|
31
|
+
negate: false,
|
32
|
+
matcher: matcher
|
33
|
+
).call
|
39
34
|
end
|
40
35
|
|
41
36
|
# @example _Absolute requirement_ definition with isolation
|
42
37
|
# it { 'foo'.upcase }.MUST! eql 'FOO'
|
43
38
|
#
|
44
39
|
# @see MUST
|
45
|
-
def MUST!(
|
46
|
-
RequirementLevel::
|
40
|
+
def MUST!(matcher)
|
41
|
+
RequirementLevel::Must.new(
|
42
|
+
callable: callable,
|
43
|
+
isolation: true,
|
44
|
+
negate: false,
|
45
|
+
matcher: matcher
|
46
|
+
).call
|
47
47
|
end
|
48
48
|
|
49
49
|
# This phrase, or the phrase "SHALL NOT", mean that the
|
@@ -52,19 +52,29 @@ module Spectus
|
|
52
52
|
# @example _Absolute prohibition_ definition
|
53
53
|
# it { 'foo'.size }.MUST_NOT equal 42
|
54
54
|
#
|
55
|
-
# @param
|
55
|
+
# @param matcher [#matches?] The matcher.
|
56
56
|
#
|
57
57
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
58
|
-
def MUST_NOT(
|
59
|
-
RequirementLevel::
|
58
|
+
def MUST_NOT(matcher)
|
59
|
+
RequirementLevel::Must.new(
|
60
|
+
callable: callable,
|
61
|
+
isolation: false,
|
62
|
+
negate: true,
|
63
|
+
matcher: matcher
|
64
|
+
).call
|
60
65
|
end
|
61
66
|
|
62
67
|
# @example _Absolute prohibition_ definition with isolation
|
63
68
|
# it { 'foo'.size }.MUST_NOT! equal 42
|
64
69
|
#
|
65
70
|
# @see MUST_NOT
|
66
|
-
def MUST_NOT!(
|
67
|
-
RequirementLevel::
|
71
|
+
def MUST_NOT!(matcher)
|
72
|
+
RequirementLevel::Must.new(
|
73
|
+
callable: callable,
|
74
|
+
isolation: true,
|
75
|
+
negate: true,
|
76
|
+
matcher: matcher
|
77
|
+
).call
|
68
78
|
end
|
69
79
|
|
70
80
|
# This word, or the adjective "RECOMMENDED", mean that there
|
@@ -75,19 +85,29 @@ module Spectus
|
|
75
85
|
# @example _Recommended_ definition
|
76
86
|
# it { 'foo'.valid_encoding? }.SHOULD equal true
|
77
87
|
#
|
78
|
-
# @param
|
88
|
+
# @param matcher [#matches?] The matcher.
|
79
89
|
#
|
80
90
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
81
|
-
def SHOULD(
|
82
|
-
RequirementLevel::
|
91
|
+
def SHOULD(matcher)
|
92
|
+
RequirementLevel::Should.new(
|
93
|
+
callable: callable,
|
94
|
+
isolation: false,
|
95
|
+
negate: false,
|
96
|
+
matcher: matcher
|
97
|
+
).call
|
83
98
|
end
|
84
99
|
|
85
100
|
# @example _Recommended_ definition with isolation
|
86
101
|
# it { 'foo'.valid_encoding? }.SHOULD! equal true
|
87
102
|
#
|
88
103
|
# @see SHOULD
|
89
|
-
def SHOULD!(
|
90
|
-
RequirementLevel::
|
104
|
+
def SHOULD!(matcher)
|
105
|
+
RequirementLevel::Should.new(
|
106
|
+
callable: callable,
|
107
|
+
isolation: true,
|
108
|
+
negate: false,
|
109
|
+
matcher: matcher
|
110
|
+
).call
|
91
111
|
end
|
92
112
|
|
93
113
|
# This phrase, or the phrase "NOT RECOMMENDED" mean that
|
@@ -99,19 +119,29 @@ module Spectus
|
|
99
119
|
# @example _Not recommended_ definition
|
100
120
|
# it { ''.blank? }.SHOULD_NOT raise_exception NoMethodError
|
101
121
|
#
|
102
|
-
# @param
|
122
|
+
# @param matcher [#matches?] The matcher.
|
103
123
|
#
|
104
124
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
105
|
-
def SHOULD_NOT(
|
106
|
-
RequirementLevel::
|
125
|
+
def SHOULD_NOT(matcher)
|
126
|
+
RequirementLevel::Should.new(
|
127
|
+
callable: callable,
|
128
|
+
isolation: false,
|
129
|
+
negate: true,
|
130
|
+
matcher: matcher
|
131
|
+
).call
|
107
132
|
end
|
108
133
|
|
109
134
|
# @example _Not recommended_ definition with isolation
|
110
135
|
# it { ''.blank? }.SHOULD_NOT! raise_exception NoMethodError
|
111
136
|
#
|
112
137
|
# @see SHOULD_NOT
|
113
|
-
def SHOULD_NOT!(
|
114
|
-
RequirementLevel::
|
138
|
+
def SHOULD_NOT!(matcher)
|
139
|
+
RequirementLevel::Should.new(
|
140
|
+
callable: callable,
|
141
|
+
isolation: true,
|
142
|
+
negate: true,
|
143
|
+
matcher: matcher
|
144
|
+
).call
|
115
145
|
end
|
116
146
|
|
117
147
|
# This word, or the adjective "OPTIONAL", mean that an item is
|
@@ -129,53 +159,40 @@ module Spectus
|
|
129
159
|
# @example _Optional_ definition
|
130
160
|
# it { 'foo'.bar }.MAY match /^foo$/
|
131
161
|
#
|
132
|
-
# @param
|
162
|
+
# @param matcher [#matches?] The matcher.
|
133
163
|
#
|
134
164
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
135
|
-
def MAY(
|
136
|
-
RequirementLevel::
|
165
|
+
def MAY(matcher)
|
166
|
+
RequirementLevel::May.new(
|
167
|
+
callable: callable,
|
168
|
+
isolation: false,
|
169
|
+
negate: false,
|
170
|
+
matcher: matcher
|
171
|
+
).call
|
137
172
|
end
|
138
173
|
|
139
174
|
# @example _Optional_ definition with isolation
|
140
175
|
# it { 'foo'.bar }.MAY! match /^foo$/
|
141
176
|
#
|
142
177
|
# @see MAY
|
143
|
-
def MAY!(
|
144
|
-
RequirementLevel::
|
178
|
+
def MAY!(matcher)
|
179
|
+
RequirementLevel::May.new(
|
180
|
+
callable: callable,
|
181
|
+
isolation: true,
|
182
|
+
negate: false,
|
183
|
+
matcher: matcher
|
184
|
+
).call
|
145
185
|
end
|
146
186
|
|
147
|
-
# rubocop:enable
|
148
|
-
# rubocop:enable Naming/UncommunicativeMethodParamName
|
187
|
+
# rubocop:enable Naming/MethodName
|
149
188
|
|
150
|
-
|
189
|
+
protected
|
151
190
|
|
152
|
-
#
|
153
|
-
|
154
|
-
# @return [BasicObject] The front object to be tested.
|
155
|
-
attr_reader :subject
|
156
|
-
private :subject
|
157
|
-
|
158
|
-
# @!attribute [r] challenges
|
159
|
-
#
|
160
|
-
# @return [Array] The challenges to call on the subject.
|
161
|
-
attr_reader :challenges
|
162
|
-
private :challenges
|
163
|
-
|
164
|
-
# rubocop:enable Style/AccessModifierDeclarations
|
165
|
-
|
166
|
-
private
|
167
|
-
|
168
|
-
# The first default challenge for blocks.
|
169
|
-
#
|
170
|
-
# @since 2.10.0
|
171
|
-
#
|
172
|
-
# @return [Defi] The challenge for blocks.
|
173
|
-
def block_challenge
|
174
|
-
::Defi.send(:call)
|
175
|
-
end
|
191
|
+
# @return [#call] The callable object to test.
|
192
|
+
attr_reader :callable
|
176
193
|
end
|
177
194
|
end
|
178
195
|
|
179
|
-
require_relative File.join('requirement_level', '
|
180
|
-
require_relative File.join('requirement_level', '
|
181
|
-
require_relative File.join('requirement_level', '
|
196
|
+
require_relative File.join('requirement_level', 'must')
|
197
|
+
require_relative File.join('requirement_level', 'should')
|
198
|
+
require_relative File.join('requirement_level', 'may')
|