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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13481b61d71af90cd7460d98c76eb3e13914e2720f7364433a746571d78e63d6
4
- data.tar.gz: 71843f9b4ad356df5a992494978a2275dcccafb207eebcc5067e21d04a1438c4
3
+ metadata.gz: 61974cb7f8cc0f5e3feaab04f902099123a2f71fa815af3d5d5230b49a8dc573
4
+ data.tar.gz: bd85d771520589ee1a10ff672f610e04ad00bdb254343241f7aacc32a1af8f5a
5
5
  SHA512:
6
- metadata.gz: 538622c03f5c9e52cda46b1c76b7c7d80ffad22e18abb6bc56a52ad371bdacb4ed292b9b6a44c29894ac1ca2ea319e22c053a448baa32aedf28ec143fa8cba11
7
- data.tar.gz: 638c15fc458db6ee8cc4381b16235df22ed8c6020f56b9d79f8330f28f32af34d9a50684b8b87e43ed83bac10c7c2822a8ef98cb03407ed2edae5d584312ebbd
6
+ metadata.gz: baf4571bbc6b585b87b6d98752bf4ba1880c99fb05bfbb1d66d0587aadc8ec9fb3481cacb5bd8f193a53eca5269002a92d1a9900ee7e9ad8874e5950a7b5dd8a
7
+ data.tar.gz: b0819b033292607bc53ba1c690f09dad9c95566e70e102f02cde1a9b0c6e42d6b58db1dd16d5ece1423e8bef94841c3d9b37775d2f08e205e2a054df079ad97e
data/README.md CHANGED
@@ -1,24 +1,12 @@
1
1
  # Spectus
2
2
 
3
- [![Build Status](https://travis-ci.org/fixrb/spectus.svg?branch=master)][travis]
3
+ [![Build Status](https://api.travis-ci.org/fixrb/spectus.svg?branch=master)][travis]
4
4
  [![Code Climate](https://codeclimate.com/github/fixrb/spectus/badges/gpa.svg)][codeclimate]
5
5
  [![Gem Version](https://badge.fury.io/rb/spectus.svg)][gem]
6
- [![Inline docs](http://inch-ci.org/github/fixrb/spectus.svg?branch=master)][inchpages]
7
- [![Documentation](http://img.shields.io/:yard-docs-38c800.svg)][rubydoc]
6
+ [![Inline docs](https://inch-ci.org/github/fixrb/spectus.svg?branch=master)][inchpages]
7
+ [![Documentation](https://img.shields.io/:yard-docs-38c800.svg)][rubydoc]
8
8
 
9
- > Expectation library with [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt)'s requirement levels, and some matchers for Ruby.
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
- ## Isolation
40
+ Thus,
51
41
 
52
- There are two cases:
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
- * when the requirement level of an expectation ends with `!`, the test is performed in isolation;
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
- Example of test in isolation:
47
+ * a _success_, a ⚠️ _warning_ or an 💡 _info_;
48
+ * a ❌ _failure_ or an 💥 _error_.
58
49
 
59
- ```ruby
60
- greeting = 'Hello, world!'
61
- it { greeting.gsub!('world', 'Alice') }.MUST! eql 'Hello, Alice!'
62
- # => #<Spectus::Result::Pass:0x007fa5022d8760 @message="Pass: Expected \"Hello, Alice!\" to eql \"Hello, Alice!\".", @subject=#<Proc:0x007fa5022d8e18@(irb):3>, @challenge=#<Defi::Challenge:0x007fa5022d8a08 @method=:call, @args=[]>, @actual="Hello, Alice!", @expected=#<Matchi::Eql:0x007fa5022d8cb0 @expected="Hello, Alice!">, @got=true, @error=nil, @level=:High, @negate=false, @valid=true>
63
- greeting # => "Hello, world!"
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
- # => #<Spectus::Result::Pass:0x007f982304d310 @message="Pass: Expected \"Hello, Alice!\" to eql \"Hello, Alice!\".", @subject=#<Proc:0x007f982304fbb0@(irb):3>, @challenge=#<Defi::Challenge:0x007f982304f890 @method=:call, @args=[]>, @actual="Hello, Alice!", @expected=#<Matchi::Eql:0x007f982304f200 @expected="Hello, Alice!">, @got=true, @error=nil, @level=:High, @negate=false, @valid=true>
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
- ## Results
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
- Both instances share the same interface.
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 requirement
86
+ ### Absolute Requirement
93
87
 
94
- Given the `"ルビー"` object, when it receives `valid_encoding?` method, then it **MUST** be `true`:
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
- # => #<Spectus::Result::Pass:0x007ffd7d00af50 @message="Pass: Expected true to be_true.", @subject=#<Proc:0x007ffd7d010130@(irb):2>, @challenge=#<Defi::Challenge:0x007ffd7d0116e8 @method=:call, @args=[]>, @actual=true, @expected=#<Matchi::BeTrue:0x007ffd7d012188>, @got=true, @error=nil, @level=:High, @negate=false, @valid=true>
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 prohibition
97
+ ### Absolute Prohibition
104
98
 
105
- Given the `"foo"` object, when it receives `length` method, then it **MUST NOT** raise the `NoMethodError` exception:
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
- # => #<Spectus::Result::Pass:0x007ffd7b890af0 @message="Pass: Expected 3 not to raise_exception NoMethodError.", @subject=#<Proc:0x007ffd7b8913b0@(irb):3>, @challenge=#<Defi::Challenge:0x007ffd7b891248 @method=:call, @args=[]>, @actual=3, @expected=#<Matchi::RaiseException:0x007ffd7b891130 @expected=NoMethodError>, @got=true, @error=nil, @level=:High, @negate=true, @valid=true>
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
- # => #<Spectus::Result::Pass:0x007ffd7b871a38 @message="Info: Expected nil to equal NilClass.", @subject=#<Proc:0x007ffd7b872460@(irb):4>, @challenge=#<Defi::Challenge:0x007ffd7b872370 @method=:call, @args=[]>, @actual=nil, @expected=#<Matchi::Equal:0x007ffd7b872140 @expected=NilClass>, @got=false, @error=nil, @level=:Medium, @negate=false, @valid=false>
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 recommended
120
+ ### Not Recommended
127
121
 
128
- Given the `"1"` object, when it receives `+(1)` method, then it **SHOULD NOT** return the `"11"` value:
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: Error: no implicit conversion of Fixnum into String (TypeError).
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 `"foo"` object, when it receives `blank?` method, then it **MAY** be `false`:
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
- # => #<Spectus::Result::Pass:0x007ffd7bbc3cb8 @message="Info: undefined method `blank?' for \"foo\":String (NoMethodError).", @subject=#<Proc:0x007ffd7b8285b8@(irb):6>, @challenge=#<Defi::Challenge:0x007ffd7b8284f0 @method=:call, @args=[]>, @actual=nil, @expected=#<Matchi::BeFalse:0x007ffd7b828310>, @got=nil, @error=#<NoMethodError: undefined method `blank?' for "foo":String>, @level=:Low, @negate=false, @valid=false>
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](http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F), for instance), so the result of the test shows that the spec passed.
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
- ## Security
142
+ ### More Examples
151
143
 
152
- As a basic form of security __Spectus__ provides a set of SHA512 checksums for
153
- every Gem release. These checksums can be found in the `checksum/` directory.
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
- The checksum of a file can be checked using the `sha512sum` command. For
158
- example:
147
+ ## Contact
159
148
 
160
- $ sha512sum pkg/spectus-2.3.0.gem
161
- e9e35e1953104e2d428b0f217e418db3c1baecd9e011b2545f9fcba4ff7e3bba674c6b928b3d8db842a139cd7cc9806d77ebdc7f710ece4f2aecb343703e2451 pkg/spectus-2.3.0.gem
149
+ * Home page: https://github.com/fixrb/spectus
150
+ * Bugs/issues: https://github.com/fixrb/spectus/issues
162
151
 
163
- ## Versioning
152
+ ## Rubies
164
153
 
165
- __Spectus__ follows [Semantic Versioning 2.0](http://semver.org/).
154
+ * [MRI](https://www.ruby-lang.org/)
155
+ * [Rubinius](https://rubinius.com/)
156
+ * [JRuby](https://www.jruby.org/)
166
157
 
167
- ## Contributing
158
+ ## Versioning
168
159
 
169
- 1. [Fork it](https://github.com/fixrb/spectus/fork)
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
- See `LICENSE.md` file.
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
- This project is sponsored by:
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
- [![Sashite](https://pbs.twimg.com/profile_images/618485028322975744/PZ9qPuI__400x400.png)](https://sashite.com/)
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
@@ -1,16 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative File.join('spectus', 'matchers')
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 Matchers
11
+ include ::Matchi::Helper
14
12
 
15
13
  # Expectations are built with this method.
16
14
  #
@@ -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 expection target
9
+ # Create a new expectation target
14
10
  #
15
- # @api private
16
- #
17
- # @param subject [Proc] The value which is compared with the expected value.
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 Style/MethodName
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 m [#matches?] The matcher.
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(m)
38
- RequirementLevel::High.new(m, false, subject, *challenges).result
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!(m)
46
- RequirementLevel::High.new(m, false, subject, *challenges).result(true)
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 m [#matches?] The matcher.
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(m)
59
- RequirementLevel::High.new(m, true, subject, *challenges).result
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!(m)
67
- RequirementLevel::High.new(m, true, subject, *challenges).result(true)
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 m [#matches?] The matcher.
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(m)
82
- RequirementLevel::Medium.new(m, false, subject, *challenges).result
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!(m)
90
- RequirementLevel::Medium.new(m, false, subject, *challenges).result(true)
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 m [#matches?] The matcher.
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(m)
106
- RequirementLevel::Medium.new(m, true, subject, *challenges).result
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!(m)
114
- RequirementLevel::Medium.new(m, true, subject, *challenges).result(true)
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 m [#matches?] The matcher.
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(m)
136
- RequirementLevel::Low.new(m, false, subject, *challenges).result
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!(m)
144
- RequirementLevel::Low.new(m, false, subject, *challenges).result(true)
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 Style/MethodName
148
- # rubocop:enable Naming/UncommunicativeMethodParamName
187
+ # rubocop:enable Naming/MethodName
149
188
 
150
- # rubocop:disable Style/AccessModifierDeclarations
189
+ protected
151
190
 
152
- # @!attribute [r] subject
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', 'high')
180
- require_relative File.join('requirement_level', 'medium')
181
- require_relative File.join('requirement_level', 'low')
196
+ require_relative File.join('requirement_level', 'must')
197
+ require_relative File.join('requirement_level', 'should')
198
+ require_relative File.join('requirement_level', 'may')