r_spec 0.3.3 → 1.0.0.beta5

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.
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ # Namespace for exceptions.
5
+ #
6
+ # @api private
7
+ module Error
8
+ end
9
+ end
10
+
11
+ require_relative File.join("error", "pending_expectation")
12
+ require_relative File.join("error", "undefined_described_class")
13
+ require_relative File.join("error", "undefined_subject")
@@ -0,0 +1,28 @@
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
+ warn " " + ::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
+ valid: false
24
+ ).colored_string
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
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
@@ -0,0 +1,11 @@
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
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ # Namespace for `it` and `its` helper modules.
5
+ module ExpectationHelper
6
+ end
7
+ end
8
+
9
+ require_relative File.join("expectation_helper", "it")
10
+ require_relative File.join("expectation_helper", "its")
@@ -0,0 +1,99 @@
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 example namespaces.
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 Base
79
+ include ::Matchi::Helper
80
+
81
+ # Mark a spec as pending, expectation results will be ignored.
82
+ #
83
+ # @param description [String] The reason why the example is pending.
84
+ #
85
+ # @return [nil] Write a message to STDOUT.
86
+ #
87
+ # @example Output a message to the console and return nil
88
+ # pending("something else getting finished") # => nil
89
+ #
90
+ # # Output to the console
91
+ # # Warning: something else getting finished.
92
+ #
93
+ # @api public
94
+ def pending(description)
95
+ Error::PendingExpectation.result(description)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative File.join("..", "expectation_target")
5
+
6
+ module RSpec
7
+ module ExpectationHelper
8
+ # `it` expectation helper module.
9
+ module It
10
+ include Base
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
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative File.join("..", "expectation_target", "block")
5
+
6
+ module RSpec
7
+ module ExpectationHelper
8
+ # `its` expectation helper module.
9
+ module Its
10
+ include Base
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
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ # Wraps the target of an expectation.
5
+ #
6
+ # @api private
7
+ module ExpectationTarget
8
+ # @param undefined_value A sentinel value to be able to tell when the user
9
+ # did not pass an argument. We can't use `nil` for that because `nil` is a
10
+ # valid value to pass.
11
+ # @param value [#object_id, nil] An actual value.
12
+ # @param block [#call, nil] A code to evaluate.
13
+ #
14
+ # @return [Block, Value] The wrapped target of an expectation.
15
+ def self.call(undefined_value, value, block)
16
+ if undefined_value.equal?(value)
17
+ raise ::ArgumentError, "Pass either an argument or a block" unless block
18
+
19
+ Block.new(block)
20
+ else
21
+ raise ::ArgumentError, "Can't pass both an argument and a block" if block
22
+
23
+ Value.new(value)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ require_relative File.join("expectation_target", "block")
30
+ require_relative File.join("expectation_target", "value")
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "expresenter"
4
+
5
+ module RSpec
6
+ module ExpectationTarget
7
+ # Abstract expectation target base class.
8
+ #
9
+ # @note `RSpec::ExpectationTarget::Base` is not intended to be instantiated
10
+ # directly by users. Use `expect` instead.
11
+ class Base
12
+ # Runs the given expectation, passing if `matcher` returns true.
13
+ #
14
+ # @example _Absolute requirement_ definition
15
+ # expect { "foo".upcase }.to eq("foo")
16
+ #
17
+ # @param matcher [#matches?] The matcher.
18
+ #
19
+ # @raise (see #result)
20
+ # @return (see #result)
21
+ #
22
+ # @api public
23
+ def to(matcher)
24
+ absolute_requirement(matcher: matcher, negate: false)
25
+ end
26
+
27
+ # Runs the given expectation, passing if `matcher` returns false.
28
+ #
29
+ # @example _Absolute prohibition_ definition
30
+ # expect { "foo".size }.not_to be(4)
31
+ #
32
+ # @param (see #to)
33
+ #
34
+ # @raise (see #result)
35
+ # @return (see #result)
36
+ #
37
+ # @api public
38
+ def not_to(matcher)
39
+ absolute_requirement(matcher: matcher, negate: true)
40
+ end
41
+
42
+ protected
43
+
44
+ # @param actual [#object_id] The actual value.
45
+ # @param error [Exception, nil] Any raised exception.
46
+ # @param got [Boolean, nil] Any returned value.
47
+ # @param matcher [#matches?] The matcher.
48
+ # @param negate [Boolean] The assertion is positive or negative.
49
+ # @param valid [Boolean] The result of an expectation.
50
+ #
51
+ # @return [nil] Write a message to STDOUT.
52
+ #
53
+ # @raise [SystemExit] Terminate execution immediately by calling
54
+ # `Kernel.exit(false)` with a failure message written to STDERR.
55
+ #
56
+ # @api private
57
+ def result(actual:, error:, got:, matcher:, negate:, valid:)
58
+ puts " " + ::Expresenter.call(valid).with(
59
+ actual: actual,
60
+ error: error,
61
+ expected: matcher.expected,
62
+ got: got,
63
+ negate: negate,
64
+ valid: valid,
65
+ matcher: matcher.class.to_sym,
66
+ level: :MUST
67
+ ).colored_string
68
+ rescue ::Expresenter::Fail => e
69
+ abort " #{e.colored_string}"
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spectus/exam"
4
+
5
+ require_relative "base"
6
+
7
+ module RSpec
8
+ module ExpectationTarget
9
+ # Wraps the target of an expectation with a block.
10
+ #
11
+ # @example
12
+ # expect { something } # => ExpectationTarget::Block wrapping something
13
+ #
14
+ # # used with `to`
15
+ # expect { actual }.to be(42)
16
+ #
17
+ # # with `not_to`
18
+ # expect { actual }.not_to be(4)
19
+ #
20
+ # @note `RSpec::ExpectationTarget::Block` is not intended to be instantiated
21
+ # directly by users. Use `expect` instead.
22
+ class Block < Base
23
+ # Instantiate a new expectation target.
24
+ #
25
+ # @param block [#call] The code to evaluate.
26
+ def initialize(block)
27
+ super()
28
+
29
+ @callable = block
30
+ end
31
+
32
+ protected
33
+
34
+ # @param matcher [#matches?] The matcher.
35
+ # @param negate [Boolean] The assertion is positive or negative.
36
+ #
37
+ # @return [nil] Write a message to STDOUT.
38
+ #
39
+ # @raise [SystemExit] Terminate execution immediately by calling
40
+ # `Kernel.exit(false)` with a failure message written to STDERR.
41
+ def absolute_requirement(matcher:, negate:)
42
+ exam = ::Spectus::Exam.new(
43
+ callable: @callable,
44
+ isolation: false,
45
+ negate: negate,
46
+ matcher: matcher
47
+ )
48
+
49
+ result(
50
+ actual: exam.actual,
51
+ error: exam.exception,
52
+ got: exam.got,
53
+ matcher: matcher,
54
+ negate: negate,
55
+ valid: exam.valid?
56
+ )
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module RSpec
6
+ module ExpectationTarget
7
+ # Wraps the target of an expectation with a value.
8
+ #
9
+ # @example
10
+ # expect(something) # => ExpectationTarget::Value wrapping something
11
+ #
12
+ # # used with `to`
13
+ # expect(actual).to be(42)
14
+ #
15
+ # # with `not_to`
16
+ # expect(actual).not_to be(4)
17
+ #
18
+ # @note `RSpec::ExpectationTarget::Value` is not intended to be instantiated
19
+ # directly by users. Use `expect` instead.
20
+ class Value < Base
21
+ # Instantiate a new expectation target.
22
+ #
23
+ # @param actual [#object_id] The actual value.
24
+ def initialize(actual)
25
+ super()
26
+
27
+ @actual = actual
28
+ end
29
+
30
+ protected
31
+
32
+ # @param matcher [#matches?] The matcher.
33
+ # @param negate [Boolean] The assertion is positive or negative.
34
+ #
35
+ # @return [nil] Write a message to STDOUT.
36
+ #
37
+ # @raise [SystemExit] Terminate execution immediately by calling
38
+ # `Kernel.exit(false)` with a failure message written to STDERR.
39
+ def absolute_requirement(matcher:, negate:)
40
+ valid = negate ^ matcher.matches? { @actual }
41
+
42
+ result(
43
+ actual: @actual,
44
+ error: nil,
45
+ got: valid,
46
+ matcher: matcher,
47
+ negate: negate,
48
+ valid: valid
49
+ )
50
+ end
51
+ end
52
+ end
53
+ end