spectus 3.0.10 → 3.1.4

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: 73306cc997a51543203fcfbec28fedae74de8ca9f382040db66d1c6aebbfc4bd
4
+ data.tar.gz: c9d9365b33cc4cca9cb54630306f9320c254a42ad64161d8a609107eeb8f95e3
5
5
  SHA512:
6
- metadata.gz: 538622c03f5c9e52cda46b1c76b7c7d80ffad22e18abb6bc56a52ad371bdacb4ed292b9b6a44c29894ac1ca2ea319e22c053a448baa32aedf28ec143fa8cba11
7
- data.tar.gz: 638c15fc458db6ee8cc4381b16235df22ed8c6020f56b9d79f8330f28f32af34d9a50684b8b87e43ed83bac10c7c2822a8ef98cb03407ed2edae5d584312ebbd
6
+ metadata.gz: 5cdfb58c6e5e3b748f8c5071f354793618a6e6e00053e3139175c5afde4cbc2fd39a419fbe516970354a6eaaee585637077d6dcc65b1d3ba7ae5412f26dcce60
7
+ data.tar.gz: 8211f7d6955d70067071a691bfa80b1f640930c01db4cec6433534141c3f7c7a4e386ee82c80f00941b3c6a04426d2266be7cdb416960e04c5e8a36b0f35bc95
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014-2019 Cyril Kato
3
+ Copyright (c) 2014-2021 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,31 +1,19 @@
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=main)][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=main)][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
 
25
13
  Add this line to your application's Gemfile:
26
14
 
27
15
  ```ruby
28
- gem 'spectus'
16
+ gem "spectus"
29
17
  ```
30
18
 
31
19
  And then execute:
@@ -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,51 @@ 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 assertion is `true`, a `Spectus::Result::Pass` instance is returned;
43
+ * when an assertion 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.
56
46
 
57
- Example of test in isolation:
47
+ Passed expectations can be classified as:
58
48
 
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
- ```
49
+ * ✅ success
50
+ * ⚠️ warning
51
+ * 💡 info
52
+
53
+ Failed expectations can be classified as:
54
+
55
+ * ❌ failure
56
+ * 💥 error
57
+
58
+ ## Code Isolation
59
+
60
+ When executing expectations, side-effects may occur.
61
+ Because they may or may not be desired, each requirement level has 2 versions:
62
+
63
+ * if it does not end with `!`, its test is performed without isolation;
64
+ * if it ends with `!`, its test is performed in isolation.
65
65
 
66
66
  Example of test without isolation:
67
67
 
68
68
  ```ruby
69
- greeting = 'Hello, world!'
70
- 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>
69
+ include Spectus
70
+ greeting = "Hello, world!"
71
+ it { greeting.gsub!("world", "Alice") }.MUST eql "Hello, Alice!"
72
+ # => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
72
73
  greeting # => "Hello, Alice!"
73
74
  ```
74
75
 
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.
76
+ Example of test in isolation:
81
77
 
82
- Both instances share the same interface.
78
+ ```ruby
79
+ include Spectus
80
+ greeting = "Hello, world!"
81
+ it { greeting.gsub!("world", "Alice") }.MUST! eql "Hello, Alice!"
82
+ # => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
83
+ greeting # => "Hello, world!"
84
+ ```
83
85
 
84
86
  ## Usage
85
87
 
@@ -89,24 +91,24 @@ To begin with, let's include __Spectus__:
89
91
  include Spectus
90
92
  ```
91
93
 
92
- ### Absolute requirement
94
+ ### Absolute Requirement
93
95
 
94
- Given the `"ルビー"` object, when it receives `valid_encoding?` method, then it **MUST** be `true`:
96
+ Given the "`ルビー`" object, when it receives `valid_encoding?` method, then it **MUST** be `true`:
95
97
 
96
98
  ```ruby
97
- 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>
99
+ it { "ルビー".valid_encoding? }.MUST be_true
100
+ # => Spectus::Result::Pass(actual: true, error: nil, expected: nil, got: true, matcher: :be_true, negate: false, level: :MUST, valid: true)
99
101
  ```
100
102
 
101
103
  The result of the test shows that the spec passed.
102
104
 
103
- ### Absolute prohibition
105
+ ### Absolute Prohibition
104
106
 
105
- Given the `"foo"` object, when it receives `length` method, then it **MUST NOT** raise the `NoMethodError` exception:
107
+ Given the "`foo`" object, when it receives `length` method, then it **MUST NOT** raise the `NoMethodError` exception:
106
108
 
107
109
  ```ruby
108
- 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>
110
+ it { "foo".length }.MUST_NOT raise_exception NoMethodError
111
+ # => Spectus::Result::Pass(actual: 3, error: nil, expected: NoMethodError, got: true, matcher: :raise_exception, negate: true, level: :MUST, valid: true)
110
112
  ```
111
113
 
112
114
  The result of the test shows that the spec passed.
@@ -117,74 +119,63 @@ Given the `BasicObject` object, when it receives `superclass` method, then it **
117
119
 
118
120
  ```ruby
119
121
  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>
122
+ # => Spectus::Result::Pass(actual: nil, error: nil, expected: NilClass, got: false, matcher: :equal, negate: false, level: :SHOULD, valid: false)
121
123
  ```
122
124
 
123
125
  Instead of the expected `NilClass` class, its sole instance (which is `nil`) was returned.
124
126
  However, because there isn't any exception, the result of the test shows that the spec passed.
125
127
 
126
- ### Not recommended
128
+ ### Not Recommended
127
129
 
128
- Given the `"1"` object, when it receives `+(1)` method, then it **SHOULD NOT** return the `"11"` value:
130
+ Given the "`1`" object, when it receives `+(1)` method, then it **SHOULD NOT** return the "`11`" value:
129
131
 
130
132
  ```ruby
131
- 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>'
133
+ it { "1" + 1 }.SHOULD_NOT eql "11"
134
+ # 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
135
  ```
136
136
 
137
137
  There was a `TypeError` exception, the result of the test shows that the spec failed.
138
138
 
139
139
  ### Optional
140
140
 
141
- Given the `"foo"` object, when it receives `blank?` method, then it **MAY** be `false`:
141
+ Given the "`foo`" object, when it receives `blank?` method, then it **MAY** be `false`:
142
142
 
143
143
  ```ruby
144
- 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>
144
+ it { "foo".blank? }.MAY be_false
145
+ # => 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
146
  ```
147
147
 
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.
148
+ 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
149
 
150
- ## Security
150
+ ### More Examples
151
151
 
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.
152
+ A full list of unit tests can be viewed (and executed) here:
153
+ [./test.rb](https://github.com/fixrb/spectus/blob/main/test.rb)
156
154
 
157
- The checksum of a file can be checked using the `sha512sum` command. For
158
- example:
155
+ ## Contact
159
156
 
160
- $ sha512sum pkg/spectus-2.3.0.gem
161
- e9e35e1953104e2d428b0f217e418db3c1baecd9e011b2545f9fcba4ff7e3bba674c6b928b3d8db842a139cd7cc9806d77ebdc7f710ece4f2aecb343703e2451 pkg/spectus-2.3.0.gem
157
+ * Home page: https://github.com/fixrb/spectus
158
+ * Bugs/issues: https://github.com/fixrb/spectus/issues
162
159
 
163
160
  ## Versioning
164
161
 
165
- __Spectus__ follows [Semantic Versioning 2.0](http://semver.org/).
162
+ __Spectus__ follows [Semantic Versioning 2.0](https://semver.org/).
166
163
 
167
- ## Contributing
164
+ ## License
168
165
 
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
166
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
174
167
 
175
- ## License
168
+ ***
176
169
 
177
- See `LICENSE.md` file.
170
+ <p>
171
+ This project is sponsored by:<br />
172
+ <a href="https://sashite.com/"><img
173
+ src="https://github.com/fixrb/spectus/raw/main/img/sashite.png"
174
+ alt="Sashite" /></a>
175
+ </p>
178
176
 
179
177
  [gem]: https://rubygems.org/gems/spectus
180
178
  [travis]: https://travis-ci.org/fixrb/spectus
181
179
  [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
185
-
186
- ***
187
-
188
- This project is sponsored by:
189
-
190
- [![Sashite](https://pbs.twimg.com/profile_images/618485028322975744/PZ9qPuI__400x400.png)](https://sashite.com/)
180
+ [inchpages]: https://inch-ci.org/github/fixrb/spectus
181
+ [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
- 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
  #
@@ -25,4 +23,4 @@ module Spectus
25
23
  end
26
24
  end
27
25
 
28
- require_relative File.join('spectus', 'expectation_target')
26
+ require_relative File.join("spectus", "expectation_target")
@@ -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")