r_spec 1.0.0.beta11 → 1.0.2

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.
data/lib/r_spec/dsl.rb DELETED
@@ -1,348 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "aw"
4
-
5
- require_relative "console"
6
- require_relative "error"
7
- require_relative "expectation_helper"
8
-
9
- module RSpec
10
- # Abstract class for handling the domain-specific language.
11
- class Dsl
12
- BEFORE_METHOD = :initialize
13
- AFTER_METHOD = :terminate
14
-
15
- private_constant :BEFORE_METHOD, :AFTER_METHOD
16
-
17
- # Executes the given block before each spec in the current context runs.
18
- #
19
- # @example
20
- # require "r_spec"
21
- #
22
- # RSpec.describe Integer do
23
- # before do
24
- # @value = 123
25
- # end
26
- #
27
- # it { expect(@value).to be 123 }
28
- #
29
- # describe "nested" do
30
- # before do
31
- # @value -= 81
32
- # end
33
- #
34
- # it { expect(@value).to be 42 }
35
- # end
36
- #
37
- # it { expect(@value).to be 123 }
38
- # end
39
- #
40
- # # Output to the console
41
- # # Success: expected to be 123.
42
- # # Success: expected to be 42.
43
- # # Success: expected to be 123.
44
- #
45
- # @param block [Proc] The content to execute at the class initialization.
46
- def self.before(&block)
47
- define_method(BEFORE_METHOD) do
48
- super()
49
- instance_eval(&block)
50
- end
51
-
52
- private BEFORE_METHOD
53
- end
54
-
55
- # Executes the given block after each spec in the current context runs.
56
- #
57
- # @example
58
- # require "r_spec"
59
- #
60
- # RSpec.describe Integer do
61
- # after do
62
- # puts "That is the answer to everything."
63
- # end
64
- #
65
- # it { expect(42).to be 42 }
66
- # end
67
- #
68
- # # Output to the console
69
- # # Success: expected to be 42.
70
- # # That is the answer to everything.
71
- #
72
- # @param block [Proc] The content to execute at the class initialization.
73
- def self.after(&block)
74
- define_method(AFTER_METHOD) do
75
- instance_exec(&block)
76
- super()
77
- end
78
-
79
- private AFTER_METHOD
80
- end
81
-
82
- # Sets a user-defined property.
83
- #
84
- # @example
85
- # require "r_spec"
86
- #
87
- # RSpec.describe "Name stories" do
88
- # let(:name) { "Bob" }
89
- #
90
- # it { expect(name).to eq "Bob" }
91
- #
92
- # context "with last name" do
93
- # let(:name) { "#{super()} Smith" }
94
- #
95
- # it { expect(name).to eq "Bob Smith" }
96
- # end
97
- # end
98
- #
99
- # # Output to the console
100
- # # Success: expected to eq "Bob".
101
- # # Success: expected to eq "Bob Smith".
102
- #
103
- # @param name [String, Symbol] The name of the property.
104
- # @param block [Proc] The content of the method to define.
105
- #
106
- # @return [Symbol] A private method that define the block content.
107
- def self.let(name, *args, **kwargs, &block)
108
- raise Error::ReservedMethod if [BEFORE_METHOD, AFTER_METHOD].include?(name.to_sym)
109
-
110
- private define_method(name, *args, **kwargs, &block)
111
- end
112
-
113
- # Sets a user-defined property named {#subject}.
114
- #
115
- # @example
116
- # require "r_spec"
117
- #
118
- # RSpec.describe Array do
119
- # subject { [1, 2, 3] }
120
- #
121
- # it "has the prescribed elements" do
122
- # expect(subject).to eq([1, 2, 3])
123
- # end
124
- # end
125
- #
126
- # # Output to the console
127
- # # Success: expected to eq [1, 2, 3].
128
- #
129
- # @param block [Proc] The subject to set.
130
- # @return [Symbol] A {#subject} method that define the block content.
131
- def self.subject(&block)
132
- let(__method__, &block)
133
- end
134
-
135
- # Defines an example group that describes a unit to be tested.
136
- #
137
- # @example
138
- # require "r_spec"
139
- #
140
- # RSpec.describe String do
141
- # describe "+" do
142
- # it("concats") { expect("foo" + "bar").to eq "foobar" }
143
- # end
144
- # end
145
- #
146
- # # Output to the console
147
- # # Success: expected to eq "foobar".
148
- #
149
- # @param const [Module, String] A module to include in block context.
150
- # @param block [Proc] The block to define the specs.
151
- def self.describe(const, &block)
152
- desc = ::Class.new(self)
153
- desc.let(:described_class) { const } if const.is_a?(::Module)
154
- desc.instance_eval(&block)
155
- end
156
-
157
- # Defines an example group that establishes a specific context, like _empty
158
- # array_ versus _array with elements_.
159
- #
160
- # Unlike {.describe}, the block is evaluated in isolation in order to scope
161
- # possible side effects inside its context.
162
- #
163
- # @example
164
- # require "r_spec"
165
- #
166
- # RSpec.describe "web resource" do
167
- # context "when resource is not found" do
168
- # pending "responds with 404"
169
- # end
170
- #
171
- # context "when resource is found" do
172
- # pending "responds with 200"
173
- # end
174
- # end
175
- #
176
- # # Output to the console
177
- # # Warning: responds with 404.
178
- # # Warning: responds with 200.
179
- #
180
- # @param _description [String] A description that usually begins with
181
- # "when", "with" or "without".
182
- # @param block [Proc] The block to define the specs.
183
- def self.context(_description = nil, &block)
184
- desc = ::Class.new(self)
185
- ::Aw.fork! { desc.instance_eval(&block) }
186
- end
187
-
188
- # Defines a concrete test case.
189
- #
190
- # The test is performed by the block supplied to `&block`.
191
- #
192
- # @example The integer after 41
193
- # require "r_spec"
194
- #
195
- # RSpec.describe Integer do
196
- # it { expect(41.next).to be 42 }
197
- # end
198
- #
199
- # # Output to the console
200
- # # Success: expected to be 42.
201
- #
202
- # @example A division by zero
203
- # require "r_spec"
204
- #
205
- # RSpec.describe Integer do
206
- # subject { 41 }
207
- #
208
- # it { is_expected.to be_an_instance_of described_class }
209
- #
210
- # it "raises an error" do
211
- # expect { subject / 0 }.to raise_exception ZeroDivisionError
212
- # end
213
- # end
214
- #
215
- # # Output to the console
216
- # # Success: expected 41 to be an instance of Integer.
217
- # # Success: divided by 0.
218
- #
219
- # It can be used inside a {.describe} or {.context} section.
220
- #
221
- # @param _name [String, nil] The name of the spec.
222
- # @param block [Proc] An expectation to evaluate.
223
- #
224
- # @raise (see ExpectationTarget::Base#result)
225
- # @return (see ExpectationTarget::Base#result)
226
- def self.it(_name = nil, &block)
227
- raise ::ArgumentError, "Missing example block" unless block
228
-
229
- example = ::Class.new(self) { include ExpectationHelper::It }.new
230
- example.instance_eval(&block)
231
- rescue ::SystemExit
232
- Console.source(*block.source_location)
233
-
234
- exit false
235
- ensure
236
- example&.send(AFTER_METHOD)
237
- end
238
-
239
- # Use the {.its} method to define a single spec that specifies the actual
240
- # value of an attribute of the subject using
241
- # {ExpectationHelper::Its#is_expected}.
242
- #
243
- # @example The integer after 41
244
- # require "r_spec"
245
- #
246
- # RSpec.describe Integer do
247
- # subject { 41 }
248
- #
249
- # its(:next) { is_expected.to be 42 }
250
- # end
251
- #
252
- # # Output to the console
253
- # # Success: expected to be 42.
254
- #
255
- # @example A division by zero
256
- # require "r_spec"
257
- #
258
- # RSpec.describe Integer do
259
- # subject { 41 }
260
- #
261
- # its(:/, 0) { is_expected.to raise_exception ZeroDivisionError }
262
- # end
263
- #
264
- # # Output to the console
265
- # # Success: divided by 0.
266
- #
267
- # @example A spec without subject
268
- # require "r_spec"
269
- #
270
- # RSpec.describe Integer do
271
- # its(:boom) { is_expected.to raise_exception RSpec::Error::UndefinedSubject }
272
- # end
273
- #
274
- # # Output to the console
275
- # # Success: subject not explicitly defined.
276
- #
277
- # @param attribute [String, Symbol] The property to call to subject.
278
- # @param args [Array] An optional list of arguments.
279
- # @param kwargs [Hash] An optional list of keyword arguments.
280
- # @param block [Proc] An expectation to evaluate.
281
- #
282
- # @raise (see ExpectationTarget::Base#result)
283
- # @return (see ExpectationTarget::Base#result)
284
- def self.its(attribute, *args, **kwargs, &block)
285
- raise ::ArgumentError, "Missing example block" unless block
286
-
287
- example = ::Class.new(self) do
288
- include ExpectationHelper::Its
289
-
290
- define_method(:actual) do
291
- subject.public_send(attribute, *args, **kwargs)
292
- end
293
- end.new
294
-
295
- example.instance_eval(&block)
296
- rescue ::SystemExit
297
- Console.source(*block.source_location)
298
-
299
- exit false
300
- ensure
301
- example&.send(AFTER_METHOD)
302
- end
303
-
304
- # Defines a pending test case.
305
- #
306
- # `&block` is never evaluated. It can be used to describe behaviour that is
307
- # not yet implemented.
308
- #
309
- # @example
310
- # require "r_spec"
311
- #
312
- # RSpec.describe "an example" do
313
- # pending "is implemented but waiting" do
314
- # expect something to be finished
315
- # end
316
- #
317
- # pending "is not yet implemented and waiting"
318
- # end
319
- #
320
- # # Output to the console
321
- # # Warning: is implemented but waiting.
322
- # # Warning: is not yet implemented and waiting.
323
- #
324
- # @param message [String] The reason why the example is pending.
325
- #
326
- # @return [nil] Write a message to STDOUT.
327
- #
328
- # @api public
329
- def self.pending(message)
330
- Console.passed_spec Error::PendingExpectation.result(message)
331
- end
332
-
333
- private
334
-
335
- def described_class
336
- raise Error::UndefinedDescribedClass,
337
- "the first argument to at least one example group must be a module"
338
- end
339
-
340
- def subject
341
- raise Error::UndefinedSubject, "subject not explicitly defined"
342
- end
343
-
344
- define_method(AFTER_METHOD) do
345
- # do nothing by default
346
- end
347
- end
348
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "expresenter"
4
-
5
- module RSpec
6
- module Error
7
- # Exception for pending expectations.
8
- #
9
- # @api private
10
- class PendingExpectation < ::RuntimeError
11
- # @param message [String] The not implemented expectation description.
12
- #
13
- # @return [nil] Write a pending expectation to STDOUT.
14
- def self.result(message)
15
- ::Expresenter.call(true).with(
16
- actual: new(message),
17
- error: nil,
18
- expected: self,
19
- got: false,
20
- matcher: :raise_exception,
21
- negate: true,
22
- level: :SHOULD
23
- )
24
- end
25
- end
26
- end
27
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpec
4
- module Error
5
- # Exception for reserved methods.
6
- #
7
- # @api private
8
- class ReservedMethod < ::RuntimeError
9
- end
10
- end
11
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpec
4
- module Error
5
- # Exception for undefined described classes.
6
- #
7
- # @api private
8
- class UndefinedDescribedClass < ::RuntimeError
9
- end
10
- end
11
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpec
4
- module Error
5
- # Exception for undefined subjects.
6
- #
7
- # @api private
8
- class UndefinedSubject < ::RuntimeError
9
- end
10
- end
11
- end
data/lib/r_spec/error.rb DELETED
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative File.join("error", "pending_expectation")
4
- require_relative File.join("error", "reserved_method")
5
- require_relative File.join("error", "undefined_described_class")
6
- require_relative File.join("error", "undefined_subject")
7
-
8
- module RSpec
9
- # Namespace for exceptions.
10
- #
11
- # @api private
12
- module Error
13
- end
14
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "shared"
4
- require_relative File.join("..", "expectation_target")
5
-
6
- module RSpec
7
- module ExpectationHelper
8
- # {RSpec::Dsl.it}'s expectation helper module.
9
- module It
10
- include Shared
11
-
12
- # Create an expectation for a spec.
13
- #
14
- # @param value [#object_id, nil] An actual value.
15
- # @param block [#call, nil] A code to evaluate.
16
- #
17
- # @return [Block, Value] The wrapped target of an expectation.
18
- #
19
- # @example
20
- # expect("foo") # => #<RSpec::ExpectationTarget::Value:0x00007fb6b82311a0 @actual="foo">
21
- # expect { Boom } # => #<RSpec::ExpectationTarget::Block:0x00007fb6b8263df8 @callable=#<Proc:0x00007fb6b8263e20>>
22
- #
23
- # @api public
24
- def expect(value = self.class.superclass, &block)
25
- ExpectationTarget.call(self.class.superclass, value, block)
26
- end
27
-
28
- # Wraps the target of an expectation with the subject as actual value.
29
- #
30
- # @return [Block] The wrapped target of an expectation.
31
- #
32
- # @example
33
- # is_expected # => #<RSpec::ExpectationTarget::Block:0x00007fb6b8263df8 @callable=#<Proc:0x00007fb6b8263e20>>
34
- #
35
- # @api public
36
- def is_expected
37
- expect { subject }
38
- end
39
- end
40
- end
41
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "shared"
4
- require_relative File.join("..", "expectation_target", "block")
5
-
6
- module RSpec
7
- module ExpectationHelper
8
- # {RSpec::Dsl.its}'s expectation helper module.
9
- module Its
10
- include Shared
11
-
12
- # Wraps the target of an expectation with the actual value.
13
- #
14
- # @return [Block] The wrapped target of an expectation.
15
- #
16
- # @example
17
- # is_expected # => #<RSpec::ExpectationTarget::Block:0x00007fb6b8263df8 @callable=#<Proc:0x00007fb6b8263e20>>
18
- #
19
- # @api public
20
- def is_expected
21
- ExpectationTarget::Block.new(method(:actual))
22
- end
23
- end
24
- end
25
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "matchi/rspec"
4
-
5
- require_relative File.join("..", "error", "pending_expectation")
6
-
7
- module RSpec
8
- module ExpectationHelper
9
- # Abstract expectation helper base module.
10
- #
11
- # This module defines a number of methods to create expectations, which are
12
- # automatically included into examples.
13
- #
14
- # It also includes a collection of expectation matchers 🤹
15
- #
16
- # @example Equivalence matcher
17
- # matcher = eql("foo") # => Matchi::Matcher::Eql.new("foo")
18
- # matcher.matches? { "foo" } # => true
19
- # matcher.matches? { "bar" } # => false
20
- #
21
- # matcher = eq("foo") # => Matchi::Matcher::Eq.new("foo")
22
- # matcher.matches? { "foo" } # => true
23
- # matcher.matches? { "bar" } # => false
24
- #
25
- # @example Identity matcher
26
- # object = "foo"
27
- #
28
- # matcher = equal(object) # => Matchi::Matcher::Equal.new(object)
29
- # matcher.matches? { object } # => true
30
- # matcher.matches? { "foo" } # => false
31
- #
32
- # matcher = be(object) # => Matchi::Matcher::Be.new(object)
33
- # matcher.matches? { object } # => true
34
- # matcher.matches? { "foo" } # => false
35
- #
36
- # @example Regular expressions matcher
37
- # matcher = match(/^foo$/) # => Matchi::Matcher::Match.new(/^foo$/)
38
- # matcher.matches? { "foo" } # => true
39
- # matcher.matches? { "bar" } # => false
40
- #
41
- # @example Expecting errors matcher
42
- # matcher = raise_exception(NameError) # => Matchi::Matcher::RaiseException.new(NameError)
43
- # matcher.matches? { Boom } # => true
44
- # matcher.matches? { true } # => false
45
- #
46
- # @example Truth matcher
47
- # matcher = be_true # => Matchi::Matcher::BeTrue.new
48
- # matcher.matches? { true } # => true
49
- # matcher.matches? { false } # => false
50
- # matcher.matches? { nil } # => false
51
- # matcher.matches? { 4 } # => false
52
- #
53
- # @example Untruth matcher
54
- # matcher = be_false # => Matchi::Matcher::BeFalse.new
55
- # matcher.matches? { false } # => true
56
- # matcher.matches? { true } # => false
57
- # matcher.matches? { nil } # => false
58
- # matcher.matches? { 4 } # => false
59
- #
60
- # @example Nil matcher
61
- # matcher = be_nil # => Matchi::Matcher::BeNil.new
62
- # matcher.matches? { nil } # => true
63
- # matcher.matches? { false } # => false
64
- # matcher.matches? { true } # => false
65
- # matcher.matches? { 4 } # => false
66
- #
67
- # @example Type/class matcher
68
- # matcher = be_instance_of(String) # => Matchi::Matcher::BeInstanceOf.new(String)
69
- # matcher.matches? { "foo" } # => true
70
- # matcher.matches? { 4 } # => false
71
- #
72
- # matcher = be_an_instance_of(String) # => Matchi::Matcher::BeAnInstanceOf.new(String)
73
- # matcher.matches? { "foo" } # => true
74
- # matcher.matches? { 4 } # => false
75
- #
76
- # @see https://github.com/fixrb/matchi
77
- # @see https://github.com/fixrb/matchi-rspec
78
- module Shared
79
- include ::Matchi::Helper
80
- end
81
- end
82
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative File.join("expectation_helper", "it")
4
- require_relative File.join("expectation_helper", "its")
5
-
6
- module RSpec
7
- # Namespace for {Dsl.it} and {Dsl.its}'s helper modules.
8
- module ExpectationHelper
9
- end
10
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "expresenter"
4
- require "test_tube"
5
-
6
- require_relative File.join("..", "console")
7
-
8
- module RSpec
9
- module ExpectationTarget
10
- # Abstract expectation target base class.
11
- #
12
- # @note `RSpec::ExpectationTarget::Base` is not intended to be instantiated
13
- # directly by users. Use `expect` instead.
14
- class Base
15
- # Instantiate a new expectation target.
16
- #
17
- # @param actual [#object_id] The actual value of the code to evaluate.
18
- def initialize(actual)
19
- @actual = actual
20
- end
21
-
22
- # Runs the given expectation, passing if `matcher` returns true.
23
- #
24
- # @example _Absolute requirement_ definition
25
- # expect { "foo".upcase }.to eq("foo")
26
- #
27
- # @param matcher [#matches?] The matcher.
28
- #
29
- # @raise (see #result)
30
- # @return (see #result)
31
- #
32
- # @api public
33
- def to(matcher)
34
- absolute_requirement(matcher: matcher, negate: false)
35
- end
36
-
37
- # Runs the given expectation, passing if `matcher` returns false.
38
- #
39
- # @example _Absolute prohibition_ definition
40
- # expect { "foo".size }.not_to be(4)
41
- #
42
- # @param (see #to)
43
- #
44
- # @raise (see #result)
45
- # @return (see #result)
46
- #
47
- # @api public
48
- def not_to(matcher)
49
- absolute_requirement(matcher: matcher, negate: true)
50
- end
51
-
52
- protected
53
-
54
- # @param passed [Boolean] The high expectation passed or failed.
55
- # @param actual [#object_id] The actual value.
56
- # @param error [Exception, nil] Any raised exception.
57
- # @param got [Boolean, nil] Any returned value.
58
- # @param matcher [#matches?] The matcher.
59
- # @param negate [Boolean] The assertion is positive or negative.
60
- #
61
- # @return [nil] Write a message to STDOUT.
62
- #
63
- # @raise [SystemExit] Terminate execution immediately by calling
64
- # `Kernel.exit(false)` with a failure message written to STDERR.
65
- #
66
- # @api private
67
- def result(passed, actual:, error:, got:, matcher:, negate:)
68
- Console.passed_spec ::Expresenter.call(passed).with(
69
- actual: actual,
70
- error: error,
71
- expected: matcher.expected,
72
- got: got,
73
- negate: negate,
74
- matcher: matcher.class.to_sym,
75
- level: :MUST
76
- )
77
- rescue ::Expresenter::Fail => e
78
- Console.failed_spec(e)
79
- end
80
- end
81
- end
82
- end