spectus 3.0.10 → 3.1.4

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: 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")