rspec-expectations 2.14.0 → 3.0.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 +15 -0
- checksums.yaml.gz.sig +0 -0
- data/Changelog.md +369 -25
- data/License.txt +1 -0
- data/README.md +88 -15
- data/lib/rspec/{matchers → expectations}/configuration.rb +44 -14
- data/lib/rspec/expectations/expectation_target.rb +67 -33
- data/lib/rspec/expectations/fail_with.rb +11 -53
- data/lib/rspec/expectations/handler.rb +126 -31
- data/lib/rspec/expectations/minitest_integration.rb +16 -0
- data/lib/rspec/expectations/syntax.rb +60 -94
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/expectations.rb +45 -23
- data/lib/rspec/matchers/aliased_matcher.rb +41 -0
- data/lib/rspec/matchers/built_in/all.rb +78 -0
- data/lib/rspec/matchers/built_in/base_matcher.rb +63 -15
- data/lib/rspec/matchers/built_in/be.rb +170 -81
- data/lib/rspec/matchers/built_in/be_between.rb +77 -0
- data/lib/rspec/matchers/built_in/be_instance_of.rb +11 -3
- data/lib/rspec/matchers/built_in/be_kind_of.rb +5 -0
- data/lib/rspec/matchers/built_in/be_within.rb +39 -15
- data/lib/rspec/matchers/built_in/change.rb +273 -80
- data/lib/rspec/matchers/built_in/compound.rb +122 -0
- data/lib/rspec/matchers/built_in/contain_exactly.rb +256 -0
- data/lib/rspec/matchers/built_in/cover.rb +3 -0
- data/lib/rspec/matchers/built_in/eq.rb +60 -6
- data/lib/rspec/matchers/built_in/eql.rb +17 -5
- data/lib/rspec/matchers/built_in/equal.rb +55 -21
- data/lib/rspec/matchers/built_in/exist.rb +74 -10
- data/lib/rspec/matchers/built_in/has.rb +71 -15
- data/lib/rspec/matchers/built_in/include.rb +64 -27
- data/lib/rspec/matchers/built_in/match.rb +19 -1
- data/lib/rspec/matchers/built_in/operators.rb +119 -0
- data/lib/rspec/matchers/built_in/output.rb +150 -0
- data/lib/rspec/matchers/built_in/raise_error.rb +84 -42
- data/lib/rspec/matchers/built_in/respond_to.rb +42 -20
- data/lib/rspec/matchers/built_in/satisfy.rb +19 -3
- data/lib/rspec/matchers/built_in/start_and_end_with.rb +54 -18
- data/lib/rspec/matchers/built_in/throw_symbol.rb +38 -8
- data/lib/rspec/matchers/built_in/yield.rb +175 -68
- data/lib/rspec/matchers/built_in.rb +45 -33
- data/lib/rspec/matchers/composable.rb +179 -0
- data/lib/rspec/matchers/dsl.rb +362 -5
- data/lib/rspec/matchers/generated_descriptions.rb +13 -6
- data/lib/rspec/matchers/matcher_delegator.rb +37 -0
- data/lib/rspec/matchers/pretty.rb +27 -20
- data/lib/rspec/matchers.rb +361 -136
- data.tar.gz.sig +1 -0
- metadata +99 -215
- metadata.gz.sig +0 -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/compatibility.rb +0 -14
- 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/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
|
@@ -4,7 +4,7 @@ module RSpec
|
|
|
4
4
|
# @api private
|
|
5
5
|
#
|
|
6
6
|
# Used _internally_ as a base class for matchers that ship with
|
|
7
|
-
# rspec-expectations.
|
|
7
|
+
# rspec-expectations and rspec-rails.
|
|
8
8
|
#
|
|
9
9
|
# ### Warning:
|
|
10
10
|
#
|
|
@@ -13,18 +13,35 @@ module RSpec
|
|
|
13
13
|
# class. If/when this changes, we will announce it and remove this warning.
|
|
14
14
|
class BaseMatcher
|
|
15
15
|
include RSpec::Matchers::Pretty
|
|
16
|
+
include RSpec::Matchers::Composable
|
|
16
17
|
|
|
18
|
+
# @api private
|
|
19
|
+
# Used to detect when no arg is passed to `initialize`.
|
|
20
|
+
# `nil` cannot be used because it's a valid value to pass.
|
|
21
|
+
UNDEFINED = Object.new.freeze
|
|
22
|
+
|
|
23
|
+
# @private
|
|
17
24
|
attr_reader :actual, :expected, :rescued_exception
|
|
18
25
|
|
|
19
|
-
def initialize(expected =
|
|
20
|
-
@expected = expected
|
|
26
|
+
def initialize(expected = UNDEFINED)
|
|
27
|
+
@expected = expected unless UNDEFINED.equal?(expected)
|
|
21
28
|
end
|
|
22
29
|
|
|
30
|
+
# @api private
|
|
31
|
+
# Indicates if the match is successful. Delegates to `match`, which
|
|
32
|
+
# should be defined on a subclass. Takes care of consistently
|
|
33
|
+
# initializing the `actual` attribute.
|
|
23
34
|
def matches?(actual)
|
|
24
35
|
@actual = actual
|
|
25
36
|
match(expected, actual)
|
|
26
37
|
end
|
|
27
38
|
|
|
39
|
+
# @api private
|
|
40
|
+
# Used to wrap a block of code that will indicate failure by
|
|
41
|
+
# raising one of the named exceptions.
|
|
42
|
+
#
|
|
43
|
+
# This is used by rspec-rails for some of its matchers that
|
|
44
|
+
# wrap rails' assertions.
|
|
28
45
|
def match_unless_raises(*exceptions)
|
|
29
46
|
exceptions.unshift Exception if exceptions.empty?
|
|
30
47
|
begin
|
|
@@ -35,32 +52,63 @@ module RSpec
|
|
|
35
52
|
end
|
|
36
53
|
end
|
|
37
54
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
55
|
+
# @api private
|
|
56
|
+
# Provides a good generic failure message. Based on `description`.
|
|
57
|
+
# When subclassing, if you are not satisfied with this failure message
|
|
58
|
+
# you often only need to override `description`.
|
|
59
|
+
# @return [String]
|
|
60
|
+
def failure_message
|
|
61
|
+
assert_ivars :@actual
|
|
62
|
+
"expected #{@actual.inspect} to #{description}"
|
|
41
63
|
end
|
|
42
64
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
65
|
+
# @api private
|
|
66
|
+
# Provides a good generic negative failure message. Based on `description`.
|
|
67
|
+
# When subclassing, if you are not satisfied with this failure message
|
|
68
|
+
# you often only need to override `description`.
|
|
69
|
+
# @return [String]
|
|
70
|
+
def failure_message_when_negated
|
|
71
|
+
assert_ivars :@actual
|
|
72
|
+
"expected #{@actual.inspect} not to #{description}"
|
|
46
73
|
end
|
|
47
74
|
|
|
75
|
+
# @api private
|
|
76
|
+
# Generates a "pretty" description using the logic in {Pretty}.
|
|
77
|
+
# @return [String]
|
|
48
78
|
def description
|
|
49
|
-
|
|
79
|
+
return name_to_sentence unless defined?(@expected)
|
|
80
|
+
"#{name_to_sentence}#{to_sentence @expected}"
|
|
50
81
|
end
|
|
51
82
|
|
|
83
|
+
# @api private
|
|
84
|
+
# Matchers are not diffable by default. Override this to make your
|
|
85
|
+
# subclass diffable.
|
|
52
86
|
def diffable?
|
|
53
87
|
false
|
|
54
88
|
end
|
|
55
89
|
|
|
56
|
-
|
|
57
|
-
|
|
90
|
+
# @api private
|
|
91
|
+
# Most matchers are value matchers (i.e. meant to work with `expect(value)`)
|
|
92
|
+
# rather than block matchers (i.e. meant to work with `expect { }`), so
|
|
93
|
+
# this defaults to false. Block matchers must override this to return true.
|
|
94
|
+
def supports_block_expectations?
|
|
95
|
+
false
|
|
58
96
|
end
|
|
59
97
|
|
|
60
|
-
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def assert_ivars(*expected_ivars)
|
|
101
|
+
if (expected_ivars - present_ivars).any?
|
|
102
|
+
raise "#{self.class.name} needs to supply#{to_sentence expected_ivars}"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
61
105
|
|
|
62
|
-
|
|
63
|
-
|
|
106
|
+
if RUBY_VERSION.to_f < 1.9
|
|
107
|
+
def present_ivars
|
|
108
|
+
instance_variables.map { |v| v.to_sym }
|
|
109
|
+
end
|
|
110
|
+
else
|
|
111
|
+
alias present_ivars instance_variables
|
|
64
112
|
end
|
|
65
113
|
end
|
|
66
114
|
end
|
|
@@ -1,73 +1,80 @@
|
|
|
1
|
-
require 'rspec/matchers/dsl'
|
|
2
|
-
|
|
3
1
|
module RSpec
|
|
4
2
|
module Matchers
|
|
5
3
|
module BuiltIn
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
# @api private
|
|
5
|
+
# Provides the implementation for `be_truthy`.
|
|
6
|
+
# Not intended to be instantiated directly.
|
|
7
|
+
class BeTruthy < BaseMatcher
|
|
8
|
+
|
|
9
|
+
# @api private
|
|
10
|
+
# @return [String]
|
|
11
|
+
def failure_message
|
|
12
|
+
"expected: truthy value\n got: #{actual.inspect}"
|
|
9
13
|
end
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
# @api private
|
|
16
|
+
# @return [String]
|
|
17
|
+
def failure_message_when_negated
|
|
18
|
+
"expected: falsey value\n got: #{actual.inspect}"
|
|
13
19
|
end
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def match(_, actual)
|
|
24
|
+
!!actual
|
|
17
25
|
end
|
|
18
26
|
end
|
|
19
27
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
28
|
+
# @api private
|
|
29
|
+
# Provides the implementation for `be_falsey`.
|
|
30
|
+
# Not intended to be instantiated directly.
|
|
31
|
+
class BeFalsey < BaseMatcher
|
|
32
|
+
|
|
33
|
+
# @api private
|
|
34
|
+
# @return [String]
|
|
35
|
+
def failure_message
|
|
36
|
+
"expected: falsey value\n got: #{actual.inspect}"
|
|
23
37
|
end
|
|
24
38
|
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
# @api private
|
|
40
|
+
# @return [String]
|
|
41
|
+
def failure_message_when_negated
|
|
42
|
+
"expected: truthy value\n got: #{actual.inspect}"
|
|
27
43
|
end
|
|
28
44
|
|
|
29
|
-
|
|
30
|
-
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def match(_, actual)
|
|
48
|
+
!actual
|
|
31
49
|
end
|
|
32
50
|
end
|
|
33
51
|
|
|
52
|
+
# @api private
|
|
53
|
+
# Provides the implementation for `be_nil`.
|
|
54
|
+
# Not intended to be instantiated directly.
|
|
34
55
|
class BeNil < BaseMatcher
|
|
35
|
-
def match(_, actual)
|
|
36
|
-
actual.nil?
|
|
37
|
-
end
|
|
38
56
|
|
|
39
|
-
|
|
57
|
+
# @api private
|
|
58
|
+
# @return [String]
|
|
59
|
+
def failure_message
|
|
40
60
|
"expected: nil\n got: #{actual.inspect}"
|
|
41
61
|
end
|
|
42
62
|
|
|
43
|
-
|
|
63
|
+
# @api private
|
|
64
|
+
# @return [String]
|
|
65
|
+
def failure_message_when_negated
|
|
44
66
|
"expected: not nil\n got: nil"
|
|
45
67
|
end
|
|
46
|
-
end
|
|
47
68
|
|
|
48
|
-
|
|
49
|
-
def initialize(*args, &block)
|
|
50
|
-
@args = args
|
|
51
|
-
end
|
|
69
|
+
private
|
|
52
70
|
|
|
53
71
|
def match(_, actual)
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def failure_message_for_should
|
|
58
|
-
"expected #{@actual.inspect} to evaluate to true"
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def failure_message_for_should_not
|
|
62
|
-
"expected #{@actual.inspect} to evaluate to false"
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
[:==, :<, :<=, :>=, :>, :===, :=~].each do |operator|
|
|
66
|
-
define_method operator do |operand|
|
|
67
|
-
BeComparedTo.new(operand, operator)
|
|
68
|
-
end
|
|
72
|
+
actual.nil?
|
|
69
73
|
end
|
|
74
|
+
end
|
|
70
75
|
|
|
76
|
+
# @private
|
|
77
|
+
module BeHelpers
|
|
71
78
|
private
|
|
72
79
|
|
|
73
80
|
def args_to_s
|
|
@@ -91,10 +98,50 @@ module RSpec
|
|
|
91
98
|
end
|
|
92
99
|
end
|
|
93
100
|
|
|
94
|
-
|
|
101
|
+
# @api private
|
|
102
|
+
# Provides the implementation for `be`.
|
|
103
|
+
# Not intended to be instantiated directly.
|
|
104
|
+
class Be < BaseMatcher
|
|
105
|
+
include BeHelpers
|
|
106
|
+
|
|
107
|
+
def initialize(*args, &block)
|
|
108
|
+
@args = args
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @api private
|
|
112
|
+
# @return [String]
|
|
113
|
+
def failure_message
|
|
114
|
+
"expected #{@actual.inspect} to evaluate to true"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @api private
|
|
118
|
+
# @return [String]
|
|
119
|
+
def failure_message_when_negated
|
|
120
|
+
"expected #{@actual.inspect} to evaluate to false"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
[:==, :<, :<=, :>=, :>, :===, :=~].each do |operator|
|
|
124
|
+
define_method operator do |operand|
|
|
125
|
+
BeComparedTo.new(operand, operator)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private
|
|
130
|
+
|
|
131
|
+
def match(_, actual)
|
|
132
|
+
!!actual
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# @api private
|
|
137
|
+
# Provides the implementation of `be <operator> value`.
|
|
138
|
+
# Not intended to be instantiated directly.
|
|
139
|
+
class BeComparedTo < BaseMatcher
|
|
140
|
+
include BeHelpers
|
|
141
|
+
|
|
95
142
|
def initialize(operand, operator)
|
|
96
143
|
@expected, @operator = operand, operator
|
|
97
|
-
|
|
144
|
+
@args = []
|
|
98
145
|
end
|
|
99
146
|
|
|
100
147
|
def matches?(actual)
|
|
@@ -102,74 +149,104 @@ module RSpec
|
|
|
102
149
|
@actual.__send__ @operator, @expected
|
|
103
150
|
end
|
|
104
151
|
|
|
105
|
-
|
|
152
|
+
# @api private
|
|
153
|
+
# @return [String]
|
|
154
|
+
def failure_message
|
|
106
155
|
"expected: #{@operator} #{@expected.inspect}\n got: #{@operator.to_s.gsub(/./, ' ')} #{@actual.inspect}"
|
|
107
156
|
end
|
|
108
157
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
158
|
+
# @api private
|
|
159
|
+
# @return [String]
|
|
160
|
+
def failure_message_when_negated
|
|
161
|
+
message = "`expect(#{@actual.inspect}).not_to be #{@operator} #{@expected.inspect}`"
|
|
162
|
+
if [:<, :>, :<=, :>=].include?(@operator)
|
|
163
|
+
message + " not only FAILED, it is a bit confusing."
|
|
164
|
+
else
|
|
165
|
+
message
|
|
166
|
+
end
|
|
118
167
|
end
|
|
119
168
|
|
|
169
|
+
# @api private
|
|
170
|
+
# @return [String]
|
|
120
171
|
def description
|
|
121
172
|
"be #{@operator} #{expected_to_sentence}#{args_to_sentence}"
|
|
122
173
|
end
|
|
123
|
-
|
|
124
|
-
def negative_expectation_expression
|
|
125
|
-
Expectations::Syntax.negative_expression("actual", "be #{@operator} #{@expected}")
|
|
126
|
-
end
|
|
127
174
|
end
|
|
128
175
|
|
|
129
|
-
|
|
176
|
+
# @api private
|
|
177
|
+
# Provides the implementation of `be_<predicate>`.
|
|
178
|
+
# Not intended to be instantiated directly.
|
|
179
|
+
class BePredicate < BaseMatcher
|
|
180
|
+
include BeHelpers
|
|
181
|
+
|
|
130
182
|
def initialize(*args, &block)
|
|
131
183
|
@expected = parse_expected(args.shift)
|
|
132
184
|
@args = args
|
|
133
185
|
@block = block
|
|
134
186
|
end
|
|
135
187
|
|
|
136
|
-
def matches?(actual)
|
|
137
|
-
@actual
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
rescue NameError => predicate_missing_error
|
|
141
|
-
"this needs to be here or rcov will not count this branch even though it's executed in a code example"
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
begin
|
|
145
|
-
return @result = actual.__send__(present_tense_predicate, *@args, &@block)
|
|
146
|
-
rescue NameError
|
|
147
|
-
raise predicate_missing_error
|
|
148
|
-
end
|
|
188
|
+
def matches?(actual, &block)
|
|
189
|
+
@actual = actual
|
|
190
|
+
@block ||= block
|
|
191
|
+
predicate_accessible? && predicate_matches?
|
|
149
192
|
end
|
|
150
193
|
|
|
151
|
-
|
|
194
|
+
def does_not_match?(actual, &block)
|
|
195
|
+
@actual = actual
|
|
196
|
+
@block ||= block
|
|
197
|
+
predicate_accessible? && !predicate_matches?
|
|
198
|
+
end
|
|
152
199
|
|
|
153
|
-
|
|
154
|
-
|
|
200
|
+
# @api private
|
|
201
|
+
# @return [String]
|
|
202
|
+
def failure_message
|
|
203
|
+
failure_message_expecting(true)
|
|
155
204
|
end
|
|
156
205
|
|
|
157
|
-
|
|
158
|
-
|
|
206
|
+
# @api private
|
|
207
|
+
# @return [String]
|
|
208
|
+
def failure_message_when_negated
|
|
209
|
+
failure_message_expecting(false)
|
|
159
210
|
end
|
|
160
211
|
|
|
212
|
+
# @api private
|
|
213
|
+
# @return [String]
|
|
161
214
|
def description
|
|
162
215
|
"#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}"
|
|
163
216
|
end
|
|
164
217
|
|
|
165
|
-
|
|
218
|
+
private
|
|
219
|
+
|
|
220
|
+
def predicate_accessible?
|
|
221
|
+
!private_predicate? && predicate_exists?
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# support 1.8.7, evaluate once at load time for performance
|
|
225
|
+
if String === methods.first
|
|
226
|
+
def private_predicate?
|
|
227
|
+
@actual.private_methods.include? predicate.to_s
|
|
228
|
+
end
|
|
229
|
+
else
|
|
230
|
+
def private_predicate?
|
|
231
|
+
@actual.private_methods.include? predicate
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def predicate_exists?
|
|
236
|
+
actual.respond_to?(predicate) || actual.respond_to?(present_tense_predicate)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def predicate_matches?
|
|
240
|
+
method_name = actual.respond_to?(predicate) ? predicate : present_tense_predicate
|
|
241
|
+
@predicate_matches = actual.__send__(method_name, *@args, &@block)
|
|
242
|
+
end
|
|
166
243
|
|
|
167
244
|
def predicate
|
|
168
|
-
"#{@expected}?"
|
|
245
|
+
:"#{@expected}?"
|
|
169
246
|
end
|
|
170
247
|
|
|
171
248
|
def present_tense_predicate
|
|
172
|
-
"#{@expected}s?"
|
|
249
|
+
:"#{@expected}s?"
|
|
173
250
|
end
|
|
174
251
|
|
|
175
252
|
def parse_expected(expected)
|
|
@@ -178,13 +255,25 @@ it is a bit confusing.
|
|
|
178
255
|
end
|
|
179
256
|
|
|
180
257
|
def prefix_and_expected(symbol)
|
|
181
|
-
symbol.to_s
|
|
182
|
-
return $1, $3
|
|
258
|
+
Matchers::BE_PREDICATE_REGEX.match(symbol.to_s).captures.compact
|
|
183
259
|
end
|
|
184
260
|
|
|
185
261
|
def prefix_to_sentence
|
|
186
262
|
split_words(@prefix)
|
|
187
263
|
end
|
|
264
|
+
|
|
265
|
+
def failure_message_expecting(value)
|
|
266
|
+
validity_message ||
|
|
267
|
+
"expected `#{@actual.inspect}.#{predicate}#{args_to_s}` to return #{value}, got #{@predicate_matches.inspect}"
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def validity_message
|
|
271
|
+
if private_predicate?
|
|
272
|
+
"expected #{@actual} to respond to `#{predicate}` but `#{predicate}` is a private method"
|
|
273
|
+
elsif !predicate_exists?
|
|
274
|
+
"expected #{@actual} to respond to `#{predicate}`"
|
|
275
|
+
end
|
|
276
|
+
end
|
|
188
277
|
end
|
|
189
278
|
end
|
|
190
279
|
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Matchers
|
|
3
|
+
module BuiltIn
|
|
4
|
+
# @api private
|
|
5
|
+
# Provides the implementation for `be_between`.
|
|
6
|
+
# Not intended to be instantiated directly.
|
|
7
|
+
class BeBetween < BaseMatcher
|
|
8
|
+
def initialize(min, max)
|
|
9
|
+
@min, @max = min, max
|
|
10
|
+
inclusive
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @api public
|
|
14
|
+
# Makes the between comparison inclusive.
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
# expect(3).to be_between(2, 3).inclusive
|
|
18
|
+
#
|
|
19
|
+
# @note The matcher is inclusive by default; this simply provides
|
|
20
|
+
# a way to be more explicit about it.
|
|
21
|
+
def inclusive
|
|
22
|
+
@less_than_operator = :<=
|
|
23
|
+
@greater_than_operator = :>=
|
|
24
|
+
@mode = :inclusive
|
|
25
|
+
self
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @api public
|
|
29
|
+
# Makes the between comparison exclusive.
|
|
30
|
+
#
|
|
31
|
+
# @example
|
|
32
|
+
# expect(3).to be_between(2, 4).exclusive
|
|
33
|
+
def exclusive
|
|
34
|
+
@less_than_operator = :<
|
|
35
|
+
@greater_than_operator = :>
|
|
36
|
+
@mode = :exclusive
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @api private
|
|
41
|
+
# @return [Boolean]
|
|
42
|
+
def matches?(actual)
|
|
43
|
+
@actual = actual
|
|
44
|
+
comparable? && compare
|
|
45
|
+
rescue ArgumentError
|
|
46
|
+
false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @api private
|
|
50
|
+
# @return [String]
|
|
51
|
+
def failure_message
|
|
52
|
+
"#{super}#{not_comparable_clause}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @api private
|
|
56
|
+
# @return [String]
|
|
57
|
+
def description
|
|
58
|
+
"be between #{@min.inspect} and #{@max.inspect} (#{@mode})"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def comparable?
|
|
64
|
+
@actual.respond_to?(@less_than_operator) && @actual.respond_to?(@greater_than_operator)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def not_comparable_clause
|
|
68
|
+
", but it does not respond to `#{@less_than_operator}` and `#{@greater_than_operator}`" unless comparable?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def compare
|
|
72
|
+
@actual.__send__(@greater_than_operator, @min) && @actual.__send__(@less_than_operator, @max)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
module RSpec
|
|
2
2
|
module Matchers
|
|
3
3
|
module BuiltIn
|
|
4
|
+
# @api private
|
|
5
|
+
# Provides the implementation for `be_an_instance_of`.
|
|
6
|
+
# Not intended to be instantiated directly.
|
|
4
7
|
class BeAnInstanceOf < BaseMatcher
|
|
5
|
-
def match(expected, actual)
|
|
6
|
-
actual.instance_of? expected
|
|
7
|
-
end
|
|
8
8
|
|
|
9
|
+
# @api private
|
|
10
|
+
# @return [String]
|
|
9
11
|
def description
|
|
10
12
|
"be an instance of #{expected}"
|
|
11
13
|
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def match(expected, actual)
|
|
18
|
+
actual.instance_of? expected
|
|
19
|
+
end
|
|
12
20
|
end
|
|
13
21
|
end
|
|
14
22
|
end
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
module RSpec
|
|
2
2
|
module Matchers
|
|
3
3
|
module BuiltIn
|
|
4
|
+
# @api private
|
|
5
|
+
# Provides the implementation for `be_a_kind_of`.
|
|
6
|
+
# Not intended to be instantiated directly.
|
|
4
7
|
class BeAKindOf < BaseMatcher
|
|
8
|
+
|
|
9
|
+
private
|
|
5
10
|
def match(expected, actual)
|
|
6
11
|
actual.kind_of? expected
|
|
7
12
|
end
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
module RSpec
|
|
2
2
|
module Matchers
|
|
3
3
|
module BuiltIn
|
|
4
|
+
# @api private
|
|
5
|
+
# Provides the implementation for `be_within`.
|
|
6
|
+
# Not intended to be instantiated directly.
|
|
4
7
|
class BeWithin
|
|
8
|
+
include Composable
|
|
9
|
+
|
|
5
10
|
def initialize(delta)
|
|
6
11
|
@delta = delta
|
|
7
12
|
end
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
raise needs_expected unless defined? @expected
|
|
12
|
-
raise needs_subtractable unless @actual.respond_to? :-
|
|
13
|
-
(@actual - @expected).abs <= @tolerance
|
|
14
|
-
end
|
|
15
|
-
alias == matches?
|
|
16
|
-
|
|
14
|
+
# @api public
|
|
15
|
+
# Sets the expected value.
|
|
17
16
|
def of(expected)
|
|
18
17
|
@expected = expected
|
|
19
18
|
@tolerance = @delta
|
|
@@ -21,6 +20,9 @@ module RSpec
|
|
|
21
20
|
self
|
|
22
21
|
end
|
|
23
22
|
|
|
23
|
+
# @api public
|
|
24
|
+
# Sets the expected value, and makes the matcher do
|
|
25
|
+
# a percent comparison.
|
|
24
26
|
def percent_of(expected)
|
|
25
27
|
@expected = expected
|
|
26
28
|
@tolerance = @delta * @expected.abs / 100.0
|
|
@@ -28,27 +30,49 @@ module RSpec
|
|
|
28
30
|
self
|
|
29
31
|
end
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
# @private
|
|
34
|
+
def matches?(actual)
|
|
35
|
+
@actual = actual
|
|
36
|
+
raise needs_expected unless defined? @expected
|
|
37
|
+
numeric? && (@actual - @expected).abs <= @tolerance
|
|
33
38
|
end
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
# @api private
|
|
41
|
+
# @return [String]
|
|
42
|
+
def failure_message
|
|
43
|
+
"expected #{@actual.inspect} to #{description}#{not_numeric_clause}"
|
|
37
44
|
end
|
|
38
45
|
|
|
46
|
+
# @api private
|
|
47
|
+
# @return [String]
|
|
48
|
+
def failure_message_when_negated
|
|
49
|
+
"expected #{@actual.inspect} not to #{description}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @api private
|
|
53
|
+
# @return [String]
|
|
39
54
|
def description
|
|
40
55
|
"be within #{@delta}#{@unit} of #{@expected}"
|
|
41
56
|
end
|
|
42
57
|
|
|
43
|
-
private
|
|
58
|
+
# @private
|
|
59
|
+
def supports_block_expectations?
|
|
60
|
+
false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
44
64
|
|
|
45
|
-
def
|
|
46
|
-
|
|
65
|
+
def numeric?
|
|
66
|
+
@actual.respond_to?(:-)
|
|
47
67
|
end
|
|
48
68
|
|
|
49
69
|
def needs_expected
|
|
50
70
|
ArgumentError.new "You must set an expected value using #of: be_within(#{@delta}).of(expected_value)"
|
|
51
71
|
end
|
|
72
|
+
|
|
73
|
+
def not_numeric_clause
|
|
74
|
+
", but it could not be treated as a numeric value" unless numeric?
|
|
75
|
+
end
|
|
52
76
|
end
|
|
53
77
|
end
|
|
54
78
|
end
|