rspec-expectations 2.14.0 → 3.13.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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.document +1 -1
- data/.yardopts +1 -1
- data/Changelog.md +976 -25
- data/{License.txt → LICENSE.md} +5 -3
- data/README.md +162 -26
- data/lib/rspec/expectations/block_snippet_extractor.rb +253 -0
- data/lib/rspec/expectations/configuration.rb +230 -0
- data/lib/rspec/expectations/expectation_target.rb +127 -51
- data/lib/rspec/expectations/fail_with.rb +17 -57
- data/lib/rspec/expectations/failure_aggregator.rb +229 -0
- data/lib/rspec/expectations/handler.rb +146 -32
- data/lib/rspec/expectations/minitest_integration.rb +58 -0
- data/lib/rspec/expectations/syntax.rb +68 -100
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/expectations.rb +58 -23
- data/lib/rspec/matchers/aliased_matcher.rb +116 -0
- data/lib/rspec/matchers/built_in/all.rb +86 -0
- data/lib/rspec/matchers/built_in/base_matcher.rb +191 -20
- data/lib/rspec/matchers/built_in/be.rb +114 -114
- data/lib/rspec/matchers/built_in/be_between.rb +77 -0
- data/lib/rspec/matchers/built_in/be_instance_of.rb +15 -4
- data/lib/rspec/matchers/built_in/be_kind_of.rb +10 -1
- data/lib/rspec/matchers/built_in/be_within.rb +35 -18
- data/lib/rspec/matchers/built_in/change.rb +389 -80
- data/lib/rspec/matchers/built_in/compound.rb +290 -0
- data/lib/rspec/matchers/built_in/contain_exactly.rb +310 -0
- data/lib/rspec/matchers/built_in/count_expectation.rb +169 -0
- data/lib/rspec/matchers/built_in/cover.rb +3 -0
- data/lib/rspec/matchers/built_in/eq.rb +30 -8
- data/lib/rspec/matchers/built_in/eql.rb +23 -8
- data/lib/rspec/matchers/built_in/equal.rb +55 -22
- data/lib/rspec/matchers/built_in/exist.rb +74 -10
- data/lib/rspec/matchers/built_in/has.rb +141 -22
- data/lib/rspec/matchers/built_in/have_attributes.rb +114 -0
- data/lib/rspec/matchers/built_in/include.rb +184 -32
- data/lib/rspec/matchers/built_in/match.rb +95 -1
- data/lib/rspec/matchers/built_in/operators.rb +128 -0
- data/lib/rspec/matchers/built_in/output.rb +207 -0
- data/lib/rspec/matchers/built_in/raise_error.rb +192 -44
- data/lib/rspec/matchers/built_in/respond_to.rb +154 -28
- data/lib/rspec/matchers/built_in/satisfy.rb +39 -9
- data/lib/rspec/matchers/built_in/start_or_end_with.rb +94 -0
- data/lib/rspec/matchers/built_in/throw_symbol.rb +58 -14
- data/lib/rspec/matchers/built_in/yield.rb +240 -161
- data/lib/rspec/matchers/built_in.rb +47 -33
- data/lib/rspec/matchers/composable.rb +171 -0
- data/lib/rspec/matchers/dsl.rb +531 -10
- data/lib/rspec/matchers/english_phrasing.rb +58 -0
- data/lib/rspec/matchers/fail_matchers.rb +42 -0
- data/lib/rspec/matchers/generated_descriptions.rb +14 -8
- data/lib/rspec/matchers/matcher_delegator.rb +61 -0
- data/lib/rspec/matchers/matcher_protocol.rb +105 -0
- data/lib/rspec/matchers/multi_matcher_diff.rb +82 -0
- data/lib/rspec/matchers.rb +520 -173
- data.tar.gz.sig +0 -0
- metadata +141 -242
- metadata.gz.sig +2 -0
- data/features/README.md +0 -48
- data/features/Upgrade.md +0 -53
- data/features/built_in_matchers/README.md +0 -90
- data/features/built_in_matchers/be.feature +0 -175
- data/features/built_in_matchers/be_within.feature +0 -48
- data/features/built_in_matchers/cover.feature +0 -47
- data/features/built_in_matchers/end_with.feature +0 -48
- data/features/built_in_matchers/equality.feature +0 -139
- data/features/built_in_matchers/exist.feature +0 -45
- data/features/built_in_matchers/expect_change.feature +0 -59
- data/features/built_in_matchers/expect_error.feature +0 -144
- data/features/built_in_matchers/have.feature +0 -109
- data/features/built_in_matchers/include.feature +0 -174
- data/features/built_in_matchers/match.feature +0 -52
- data/features/built_in_matchers/operators.feature +0 -227
- data/features/built_in_matchers/predicates.feature +0 -137
- data/features/built_in_matchers/respond_to.feature +0 -84
- data/features/built_in_matchers/satisfy.feature +0 -33
- data/features/built_in_matchers/start_with.feature +0 -48
- data/features/built_in_matchers/throw_symbol.feature +0 -91
- data/features/built_in_matchers/types.feature +0 -116
- data/features/built_in_matchers/yield.feature +0 -161
- data/features/custom_matchers/access_running_example.feature +0 -53
- data/features/custom_matchers/define_diffable_matcher.feature +0 -27
- data/features/custom_matchers/define_matcher.feature +0 -368
- data/features/custom_matchers/define_matcher_outside_rspec.feature +0 -38
- data/features/custom_matchers/define_matcher_with_fluent_interface.feature +0 -24
- data/features/customized_message.feature +0 -22
- data/features/diffing.feature +0 -85
- data/features/implicit_docstrings.feature +0 -52
- data/features/step_definitions/additional_cli_steps.rb +0 -22
- data/features/support/env.rb +0 -14
- data/features/syntax_configuration.feature +0 -71
- data/features/test_frameworks/test_unit.feature +0 -44
- data/lib/rspec/expectations/deprecation.rb +0 -17
- data/lib/rspec/expectations/differ.rb +0 -133
- data/lib/rspec/expectations/errors.rb +0 -9
- data/lib/rspec/expectations/extensions/array.rb +0 -9
- data/lib/rspec/expectations/extensions/object.rb +0 -29
- data/lib/rspec/expectations/extensions.rb +0 -2
- data/lib/rspec/matchers/be_close.rb +0 -9
- data/lib/rspec/matchers/built_in/have.rb +0 -124
- data/lib/rspec/matchers/built_in/match_array.rb +0 -51
- data/lib/rspec/matchers/built_in/start_and_end_with.rb +0 -48
- data/lib/rspec/matchers/compatibility.rb +0 -14
- data/lib/rspec/matchers/configuration.rb +0 -108
- data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
- data/lib/rspec/matchers/matcher.rb +0 -300
- data/lib/rspec/matchers/method_missing.rb +0 -12
- data/lib/rspec/matchers/operator_matcher.rb +0 -109
- data/lib/rspec/matchers/pretty.rb +0 -70
- data/lib/rspec/matchers/test_unit_integration.rb +0 -11
- data/lib/rspec-expectations.rb +0 -1
- data/spec/rspec/expectations/differ_spec.rb +0 -192
- data/spec/rspec/expectations/expectation_target_spec.rb +0 -82
- data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
- data/spec/rspec/expectations/fail_with_spec.rb +0 -114
- data/spec/rspec/expectations/handler_spec.rb +0 -227
- data/spec/rspec/expectations/syntax_spec.rb +0 -139
- data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
- data/spec/rspec/matchers/be_close_spec.rb +0 -22
- data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
- data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
- data/spec/rspec/matchers/be_spec.rb +0 -516
- data/spec/rspec/matchers/be_within_spec.rb +0 -137
- data/spec/rspec/matchers/change_spec.rb +0 -553
- data/spec/rspec/matchers/configuration_spec.rb +0 -206
- data/spec/rspec/matchers/cover_spec.rb +0 -69
- data/spec/rspec/matchers/description_generation_spec.rb +0 -190
- data/spec/rspec/matchers/dsl_spec.rb +0 -57
- data/spec/rspec/matchers/eq_spec.rb +0 -60
- data/spec/rspec/matchers/eql_spec.rb +0 -41
- data/spec/rspec/matchers/equal_spec.rb +0 -78
- data/spec/rspec/matchers/exist_spec.rb +0 -124
- data/spec/rspec/matchers/has_spec.rb +0 -122
- data/spec/rspec/matchers/have_spec.rb +0 -455
- data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
- data/spec/rspec/matchers/include_spec.rb +0 -531
- data/spec/rspec/matchers/match_array_spec.rb +0 -194
- data/spec/rspec/matchers/match_spec.rb +0 -61
- data/spec/rspec/matchers/matcher_spec.rb +0 -471
- data/spec/rspec/matchers/matchers_spec.rb +0 -37
- data/spec/rspec/matchers/method_missing_spec.rb +0 -28
- data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
- data/spec/rspec/matchers/raise_error_spec.rb +0 -485
- data/spec/rspec/matchers/respond_to_spec.rb +0 -292
- data/spec/rspec/matchers/satisfy_spec.rb +0 -44
- data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
- data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
- data/spec/rspec/matchers/yield_spec.rb +0 -514
- data/spec/spec_helper.rb +0 -54
- data/spec/support/classes.rb +0 -56
- data/spec/support/in_sub_process.rb +0 -38
- data/spec/support/matchers.rb +0 -22
- data/spec/support/ruby_version.rb +0 -10
- data/spec/support/shared_examples.rb +0 -13
@@ -1,30 +1,36 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Matchers
|
3
3
|
class << self
|
4
|
-
|
4
|
+
# @private
|
5
|
+
attr_accessor :last_matcher, :last_expectation_handler
|
5
6
|
end
|
6
7
|
|
8
|
+
# @api private
|
9
|
+
# Used by rspec-core to clear the state used to generate
|
10
|
+
# descriptions after an example.
|
7
11
|
def self.clear_generated_description
|
8
12
|
self.last_matcher = nil
|
9
|
-
self.
|
13
|
+
self.last_expectation_handler = nil
|
10
14
|
end
|
11
15
|
|
16
|
+
# @api private
|
17
|
+
# Generates an an example description based on the last expectation.
|
18
|
+
# Used by rspec-core's one-liner syntax.
|
12
19
|
def self.generated_description
|
13
|
-
return nil if
|
14
|
-
"#{
|
20
|
+
return nil if last_expectation_handler.nil?
|
21
|
+
"#{last_expectation_handler.verb} #{last_description}"
|
15
22
|
end
|
16
23
|
|
17
|
-
|
18
|
-
|
24
|
+
# @private
|
19
25
|
def self.last_description
|
20
26
|
last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE
|
21
27
|
When you call a matcher in an example without a String, like this:
|
22
28
|
|
23
|
-
specify { object.
|
29
|
+
specify { expect(object).to matcher }
|
24
30
|
|
25
31
|
or this:
|
26
32
|
|
27
|
-
it {
|
33
|
+
it { is_expected.to matcher }
|
28
34
|
|
29
35
|
RSpec expects the matcher to have a #description method. You should either
|
30
36
|
add a String to the example this matcher is being used in, or give it a
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
# Provides a base class with as little methods as possible, so that
|
4
|
+
# most methods can be delegated via `method_missing`.
|
5
|
+
#
|
6
|
+
# On Ruby 2.0+ BasicObject could be used for this purpose, but it
|
7
|
+
# introduce some extra complexity with constant resolution, so the
|
8
|
+
# BlankSlate pattern was prefered.
|
9
|
+
# @private
|
10
|
+
class BaseDelegator
|
11
|
+
kept_methods = [
|
12
|
+
# Methods that raise warnings if removed.
|
13
|
+
:__id__, :__send__, :object_id,
|
14
|
+
|
15
|
+
# Methods that are explicitly undefined in some subclasses.
|
16
|
+
:==, :===,
|
17
|
+
|
18
|
+
# Methods we keep on purpose.
|
19
|
+
:class, :respond_to?, :__method__, :method, :dup,
|
20
|
+
:clone, :initialize_dup, :initialize_copy, :initialize_clone,
|
21
|
+
]
|
22
|
+
instance_methods.each do |method|
|
23
|
+
unless kept_methods.include?(method.to_sym)
|
24
|
+
undef_method(method)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Provides the necessary plumbing to wrap a matcher with a decorator.
|
30
|
+
# @private
|
31
|
+
class MatcherDelegator < BaseDelegator
|
32
|
+
include Composable
|
33
|
+
attr_reader :base_matcher
|
34
|
+
|
35
|
+
def initialize(base_matcher)
|
36
|
+
@base_matcher = base_matcher
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(*args, &block)
|
40
|
+
base_matcher.__send__(*args, &block)
|
41
|
+
end
|
42
|
+
|
43
|
+
if ::RUBY_VERSION.to_f > 1.8
|
44
|
+
def respond_to_missing?(name, include_all=false)
|
45
|
+
super || base_matcher.respond_to?(name, include_all)
|
46
|
+
end
|
47
|
+
else
|
48
|
+
# :nocov:
|
49
|
+
def respond_to?(name, include_all=false)
|
50
|
+
super || base_matcher.respond_to?(name, include_all)
|
51
|
+
end
|
52
|
+
# :nocov:
|
53
|
+
end
|
54
|
+
|
55
|
+
def initialize_copy(other)
|
56
|
+
@base_matcher = @base_matcher.clone
|
57
|
+
super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
# rspec-expectations can work with any matcher object that implements this protocol.
|
4
|
+
#
|
5
|
+
# @note This class is not loaded at runtime by rspec-expectations. It exists
|
6
|
+
# purely to provide documentation for the matcher protocol.
|
7
|
+
class MatcherProtocol
|
8
|
+
# @!group Required Methods
|
9
|
+
|
10
|
+
# @!method matches?(actual)
|
11
|
+
# @param actual [Object] The object being matched against.
|
12
|
+
# @yield For an expression like `expect(x).to matcher do...end`, the `do/end`
|
13
|
+
# block binds to `to`. It passes that block, if there is one, on to this method.
|
14
|
+
# @return [Boolean] true if this matcher matches the provided object.
|
15
|
+
|
16
|
+
# @!method failure_message
|
17
|
+
# This will only be called if {#matches?} returns false.
|
18
|
+
# @return [String] Explanation for the failure.
|
19
|
+
|
20
|
+
# @!endgroup
|
21
|
+
|
22
|
+
# @!group Optional Methods
|
23
|
+
|
24
|
+
# @!method does_not_match?(actual)
|
25
|
+
# In a negative expectation such as `expect(x).not_to foo`, RSpec will
|
26
|
+
# call `foo.does_not_match?(x)` if this method is defined. If it's not
|
27
|
+
# defined it will fall back to using `!foo.matches?(x)`. This allows you
|
28
|
+
# to provide custom logic for the negative case.
|
29
|
+
#
|
30
|
+
# @param actual [Object] The object being matched against.
|
31
|
+
# @yield For an expression like `expect(x).not_to matcher do...end`, the `do/end`
|
32
|
+
# block binds to `not_to`. It passes that block, if there is one, on to this method.
|
33
|
+
# @return [Boolean] true if this matcher does not match the provided object.
|
34
|
+
|
35
|
+
# @!method failure_message_when_negated
|
36
|
+
# This will only be called when a negative match fails.
|
37
|
+
# @return [String] Explanation for the failure.
|
38
|
+
# @note This method is listed as optional because matchers do not have to
|
39
|
+
# support negation. But if your matcher does support negation, this is a
|
40
|
+
# required method -- otherwise, you'll get a `NoMethodError`.
|
41
|
+
|
42
|
+
# @!method description
|
43
|
+
# The description is used for two things:
|
44
|
+
#
|
45
|
+
# * When using RSpec's one-liner syntax
|
46
|
+
# (e.g. `it { is_expected.to matcher }`), the description
|
47
|
+
# is used to generate the example's doc string since you
|
48
|
+
# have not provided one.
|
49
|
+
# * In a composed matcher expression, the description is used
|
50
|
+
# as part of the failure message (and description) of the outer
|
51
|
+
# matcher.
|
52
|
+
#
|
53
|
+
# @return [String] Description of the matcher.
|
54
|
+
|
55
|
+
# @!method supports_block_expectations?
|
56
|
+
# Indicates that this matcher can be used in a block expectation expression,
|
57
|
+
# such as `expect { foo }.to raise_error`. Generally speaking, this is
|
58
|
+
# only needed for matchers which operate on a side effect of a block, rather
|
59
|
+
# than on a particular object.
|
60
|
+
# @return [Boolean] true if this matcher can be used in block expressions.
|
61
|
+
# @note If not defined, RSpec assumes a value of `false` for this method.
|
62
|
+
|
63
|
+
# @!method supports_value_expectations?
|
64
|
+
# Indicates that this matcher can be used in a value expectation expression,
|
65
|
+
# such as `expect(foo).to eq(bar)`.
|
66
|
+
# @return [Boolean] true if this matcher can be used in value expressions.
|
67
|
+
# @note If not defined, RSpec assumes a value of `true` for this method.
|
68
|
+
|
69
|
+
# @!method expects_call_stack_jump?
|
70
|
+
# Indicates that when this matcher is used in a block expectation
|
71
|
+
# expression, it expects the block to use a ruby construct that causes
|
72
|
+
# a call stack jump (such as raising an error or throwing a symbol).
|
73
|
+
#
|
74
|
+
# This is used internally for compound block expressions, as matchers
|
75
|
+
# which expect call stack jumps must be treated with care to work properly.
|
76
|
+
#
|
77
|
+
# @return [Boolean] true if the matcher expects a call stack jump
|
78
|
+
#
|
79
|
+
# @note This method is very rarely used or needed.
|
80
|
+
# @note If not defined, RSpec assumes a value of `false` for this method.
|
81
|
+
|
82
|
+
# @!method diffable?
|
83
|
+
# @return [Boolean] true if `actual` and `expected` can be diffed.
|
84
|
+
# Indicates that this matcher provides `actual` and `expected` attributes,
|
85
|
+
# and that the values returned by these can be usefully diffed, which can
|
86
|
+
# be included in the output.
|
87
|
+
|
88
|
+
# @!method actual
|
89
|
+
# @return [String, Object] If an object (rather than a string) is provided,
|
90
|
+
# RSpec will use the `pp` library to convert it to multi-line output in
|
91
|
+
# order to diff.
|
92
|
+
# The actual value for the purposes of a diff.
|
93
|
+
# @note This method is required if `diffable?` returns true.
|
94
|
+
|
95
|
+
# @!method expected
|
96
|
+
# @return [String, Object] If an object (rather than a string) is provided,
|
97
|
+
# RSpec will use the `pp` library to convert it to multi-line output in
|
98
|
+
# order to diff.
|
99
|
+
# The expected value for the purposes of a diff.
|
100
|
+
# @note This method is required if `diffable?` returns true.
|
101
|
+
|
102
|
+
# @!endgroup
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
# @api private
|
4
|
+
# Handles list of expected and actual value pairs when there is a need
|
5
|
+
# to render multiple diffs. Also can handle one pair.
|
6
|
+
class MultiMatcherDiff
|
7
|
+
# @private
|
8
|
+
# Default diff label when there is only one matcher in diff
|
9
|
+
# output
|
10
|
+
DEFAULT_DIFF_LABEL = "Diff:".freeze
|
11
|
+
|
12
|
+
# @private
|
13
|
+
# Maximum readable matcher description length
|
14
|
+
DESCRIPTION_MAX_LENGTH = 65
|
15
|
+
|
16
|
+
def initialize(expected_list)
|
17
|
+
@expected_list = expected_list
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
# Wraps provided expected value in instance of
|
22
|
+
# MultiMatcherDiff. If provided value is already an
|
23
|
+
# MultiMatcherDiff then it just returns it.
|
24
|
+
# @param [Any] expected value to be wrapped
|
25
|
+
# @param [Any] actual value
|
26
|
+
# @return [RSpec::Matchers::MultiMatcherDiff]
|
27
|
+
def self.from(expected, actual)
|
28
|
+
return expected if self === expected
|
29
|
+
new([[expected, DEFAULT_DIFF_LABEL, actual]])
|
30
|
+
end
|
31
|
+
|
32
|
+
# @api private
|
33
|
+
# Wraps provided matcher list in instance of
|
34
|
+
# MultiMatcherDiff.
|
35
|
+
# @param [Array<Any>] matchers list of matchers to wrap
|
36
|
+
# @return [RSpec::Matchers::MultiMatcherDiff]
|
37
|
+
def self.for_many_matchers(matchers)
|
38
|
+
new(matchers.map { |m| [m.expected, diff_label_for(m), m.actual] })
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
# Returns message with diff(s) appended for provided differ
|
43
|
+
# factory and actual value if there are any
|
44
|
+
# @param [String] message original failure message
|
45
|
+
# @param [Proc] differ
|
46
|
+
# @return [String]
|
47
|
+
def message_with_diff(message, differ)
|
48
|
+
diff = diffs(differ)
|
49
|
+
message = "#{message}\n#{diff}" unless diff.empty?
|
50
|
+
message
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
class << self
|
56
|
+
private
|
57
|
+
|
58
|
+
def diff_label_for(matcher)
|
59
|
+
"Diff for (#{truncated(RSpec::Support::ObjectFormatter.format(matcher))}):"
|
60
|
+
end
|
61
|
+
|
62
|
+
def truncated(description)
|
63
|
+
return description if description.length <= DESCRIPTION_MAX_LENGTH
|
64
|
+
description[0...DESCRIPTION_MAX_LENGTH - 3] << "..."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def diffs(differ)
|
69
|
+
@expected_list.map do |(expected, diff_label, actual)|
|
70
|
+
diff = differ.diff(actual, expected)
|
71
|
+
next if diff.strip.empty?
|
72
|
+
if diff == "\e[0m\n\e[0m"
|
73
|
+
"#{diff_label}\n" \
|
74
|
+
" <The diff is empty, are your objects producing identical `#inspect` output?>"
|
75
|
+
else
|
76
|
+
"#{diff_label}#{diff}"
|
77
|
+
end
|
78
|
+
end.compact.join("\n")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|