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
data/lib/rspec/matchers.rb
CHANGED
@@ -1,29 +1,24 @@
|
|
1
|
-
require 'rspec/
|
2
|
-
|
1
|
+
require 'rspec/support'
|
2
|
+
RSpec::Support.require_rspec_support 'matcher_definition'
|
3
|
+
RSpec::Support.define_optimized_require_for_rspec(:matchers) { |f| require_relative(f) }
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
%w[
|
6
|
+
english_phrasing
|
7
|
+
composable
|
8
|
+
built_in
|
9
|
+
generated_descriptions
|
10
|
+
dsl
|
11
|
+
matcher_delegator
|
12
|
+
aliased_matcher
|
13
|
+
multi_matcher_diff
|
14
|
+
].each { |file| RSpec::Support.require_rspec_matchers(file) }
|
14
15
|
|
16
|
+
# RSpec's top level namespace. All of rspec-expectations is contained
|
17
|
+
# in the `RSpec::Expectations` and `RSpec::Matchers` namespaces.
|
15
18
|
module RSpec
|
16
19
|
# RSpec::Matchers provides a number of useful matchers we use to define
|
17
|
-
# expectations.
|
18
|
-
#
|
19
|
-
# matches?(actual)
|
20
|
-
# failure_message_for_should
|
21
|
-
#
|
22
|
-
# These methods are also part of the matcher protocol, but are optional:
|
23
|
-
#
|
24
|
-
# does_not_match?(actual)
|
25
|
-
# failure_message_for_should_not
|
26
|
-
# description
|
20
|
+
# expectations. Any object that implements the [matcher protocol](Matchers/MatcherProtocol)
|
21
|
+
# can be used as a matcher.
|
27
22
|
#
|
28
23
|
# ## Predicates
|
29
24
|
#
|
@@ -41,14 +36,14 @@ module RSpec
|
|
41
36
|
# expect([]).to be_empty # => [].empty?() | passes
|
42
37
|
# expect([]).not_to be_empty # => [].empty?() | fails
|
43
38
|
#
|
44
|
-
# In
|
39
|
+
# In addition to prefixing the predicate matchers with "be_", you can also use "be_a_"
|
45
40
|
# and "be_an_", making your specs read much more naturally:
|
46
41
|
#
|
47
42
|
# expect("a string").to be_an_instance_of(String) # =>"a string".instance_of?(String) # passes
|
48
43
|
#
|
49
|
-
# expect(3).to be_a_kind_of(
|
50
|
-
# expect(3).to be_a_kind_of(Numeric)
|
51
|
-
# expect(3).to be_an_instance_of(
|
44
|
+
# expect(3).to be_a_kind_of(Integer) # => 3.kind_of?(Numeric) | passes
|
45
|
+
# expect(3).to be_a_kind_of(Numeric) # => 3.kind_of?(Numeric) | passes
|
46
|
+
# expect(3).to be_an_instance_of(Integer) # => 3.instance_of?(Integer) | passes
|
52
47
|
# expect(3).not_to be_an_instance_of(Numeric) # => 3.instance_of?(Numeric) | fails
|
53
48
|
#
|
54
49
|
# RSpec will also create custom matchers for predicates like `has_key?`. To
|
@@ -61,6 +56,32 @@ module RSpec
|
|
61
56
|
# You can use this feature to invoke any predicate that begins with "has_", whether it is
|
62
57
|
# part of the Ruby libraries (like `Hash#has_key?`) or a method you wrote on your own class.
|
63
58
|
#
|
59
|
+
# Note that RSpec does not provide composable aliases for these dynamic predicate
|
60
|
+
# matchers. You can easily define your own aliases, though:
|
61
|
+
#
|
62
|
+
# RSpec::Matchers.alias_matcher :a_user_who_is_an_admin, :be_an_admin
|
63
|
+
# expect(user_list).to include(a_user_who_is_an_admin)
|
64
|
+
#
|
65
|
+
# ## Alias Matchers
|
66
|
+
#
|
67
|
+
# With {RSpec::Matchers.alias_matcher}, you can easily create an
|
68
|
+
# alternate name for a given matcher.
|
69
|
+
#
|
70
|
+
# The description will also change according to the new name:
|
71
|
+
#
|
72
|
+
# RSpec::Matchers.alias_matcher :a_list_that_sums_to, :sum_to
|
73
|
+
# sum_to(3).description # => "sum to 3"
|
74
|
+
# a_list_that_sums_to(3).description # => "a list that sums to 3"
|
75
|
+
#
|
76
|
+
# or you can specify a custom description like this:
|
77
|
+
#
|
78
|
+
# RSpec::Matchers.alias_matcher :a_list_sorted_by, :be_sorted_by do |description|
|
79
|
+
# description.sub("be sorted by", "a list sorted by")
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# be_sorted_by(:age).description # => "be sorted by age"
|
83
|
+
# a_list_sorted_by(:age).description # => "a list sorted by age"
|
84
|
+
#
|
64
85
|
# ## Custom Matchers
|
65
86
|
#
|
66
87
|
# When you find that none of the stock matchers provide a natural feeling
|
@@ -100,11 +121,11 @@ module RSpec
|
|
100
121
|
# player.in_zone?(zone)
|
101
122
|
# end
|
102
123
|
#
|
103
|
-
#
|
124
|
+
# failure_message do |player|
|
104
125
|
# # generate and return the appropriate string.
|
105
126
|
# end
|
106
127
|
#
|
107
|
-
#
|
128
|
+
# failure_message_when_negated do |player|
|
108
129
|
# # generate and return the appropriate string.
|
109
130
|
# end
|
110
131
|
#
|
@@ -115,8 +136,8 @@ module RSpec
|
|
115
136
|
#
|
116
137
|
# Each of the message-generation methods has access to the block arguments
|
117
138
|
# passed to the <tt>create</tt> method (in this case, <tt>zone</tt>). The
|
118
|
-
# failure message methods (<tt>
|
119
|
-
# <tt>
|
139
|
+
# failure message methods (<tt>failure_message</tt> and
|
140
|
+
# <tt>failure_message_when_negated</tt>) are passed the actual value (the
|
120
141
|
# receiver of <tt>expect(..)</tt> or <tt>expect(..).not_to</tt>).
|
121
142
|
#
|
122
143
|
# ### Custom Matcher from scratch
|
@@ -133,11 +154,11 @@ module RSpec
|
|
133
154
|
# @target.current_zone.eql?(Zone.new(@expected))
|
134
155
|
# end
|
135
156
|
#
|
136
|
-
# def
|
157
|
+
# def failure_message
|
137
158
|
# "expected #{@target.inspect} to be in Zone #{@expected}"
|
138
159
|
# end
|
139
160
|
#
|
140
|
-
# def
|
161
|
+
# def failure_message_when_negated
|
141
162
|
# "expected #{@target.inspect} not to be in Zone #{@expected}"
|
142
163
|
# end
|
143
164
|
# end
|
@@ -173,34 +194,141 @@ module RSpec
|
|
173
194
|
# RSpec::configure do |config|
|
174
195
|
# config.include(CustomGameMatchers)
|
175
196
|
# end
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
197
|
+
#
|
198
|
+
# ### Making custom matchers composable
|
199
|
+
#
|
200
|
+
# RSpec's built-in matchers are designed to be composed, in expressions like:
|
201
|
+
#
|
202
|
+
# expect(["barn", 2.45]).to contain_exactly(
|
203
|
+
# a_value_within(0.1).of(2.5),
|
204
|
+
# a_string_starting_with("bar")
|
205
|
+
# )
|
206
|
+
#
|
207
|
+
# Custom matchers can easily participate in composed matcher expressions like these.
|
208
|
+
# Include {RSpec::Matchers::Composable} in your custom matcher to make it support
|
209
|
+
# being composed (matchers defined using the DSL have this included automatically).
|
210
|
+
# Within your matcher's `matches?` method (or the `match` block, if using the DSL),
|
211
|
+
# use `values_match?(expected, actual)` rather than `expected == actual`.
|
212
|
+
# Under the covers, `values_match?` is able to match arbitrary
|
213
|
+
# nested data structures containing a mix of both matchers and non-matcher objects.
|
214
|
+
# It uses `===` and `==` to perform the matching, considering the values to
|
215
|
+
# match if either returns `true`. The `Composable` mixin also provides some helper
|
216
|
+
# methods for surfacing the matcher descriptions within your matcher's description
|
217
|
+
# or failure messages.
|
218
|
+
#
|
219
|
+
# RSpec's built-in matchers each have a number of aliases that rephrase the matcher
|
220
|
+
# from a verb phrase (such as `be_within`) to a noun phrase (such as `a_value_within`),
|
221
|
+
# which reads better when the matcher is passed as an argument in a composed matcher
|
222
|
+
# expressions, and also uses the noun-phrase wording in the matcher's `description`,
|
223
|
+
# for readable failure messages. You can alias your custom matchers in similar fashion
|
224
|
+
# using {RSpec::Matchers.alias_matcher}.
|
225
|
+
#
|
226
|
+
# ## Negated Matchers
|
227
|
+
#
|
228
|
+
# Sometimes if you want to test for the opposite using a more descriptive name
|
229
|
+
# instead of using `not_to`, you can use {RSpec::Matchers.define_negated_matcher}:
|
230
|
+
#
|
231
|
+
# RSpec::Matchers.define_negated_matcher :exclude, :include
|
232
|
+
# include(1, 2).description # => "include 1 and 2"
|
233
|
+
# exclude(1, 2).description # => "exclude 1 and 2"
|
234
|
+
#
|
235
|
+
# While the most obvious negated form may be to add a `not_` prefix,
|
236
|
+
# the failure messages you get with that form can be confusing (e.g.
|
237
|
+
# "expected [actual] to not [verb], but did not"). We've found it works
|
238
|
+
# best to find a more positive name for the negated form, such as
|
239
|
+
# `avoid_changing` rather than `not_change`.
|
240
|
+
#
|
241
|
+
module Matchers # rubocop:disable Metrics/ModuleLength
|
242
|
+
extend ::RSpec::Matchers::DSL
|
243
|
+
|
244
|
+
# @!macro [attach] alias_matcher
|
245
|
+
# @!parse
|
246
|
+
# alias $1 $2
|
247
|
+
# @!visibility private
|
248
|
+
# We define this override here so we can attach a YARD macro to it.
|
249
|
+
# It ensures that our docs list all the matcher aliases.
|
250
|
+
def self.alias_matcher(*args, &block)
|
251
|
+
super(*args, &block)
|
252
|
+
end
|
253
|
+
|
254
|
+
# @!method self.alias_matcher(new_name, old_name, options={}, &description_override)
|
255
|
+
# Extended from {RSpec::Matchers::DSL#alias_matcher}.
|
182
256
|
|
183
|
-
|
257
|
+
# @!method self.define(name, &declarations)
|
258
|
+
# Extended from {RSpec::Matchers::DSL#define}.
|
259
|
+
|
260
|
+
# @!method self.define_negated_matcher(negated_name, base_name, &description_override)
|
261
|
+
# Extended from {RSpec::Matchers::DSL#define_negated_matcher}.
|
262
|
+
|
263
|
+
# @method expect
|
264
|
+
# Supports `expect(actual).to matcher` syntax by wrapping `actual` in an
|
265
|
+
# `ExpectationTarget`.
|
266
|
+
# @example
|
267
|
+
# expect(actual).to eq(expected)
|
268
|
+
# expect(actual).not_to eq(expected)
|
269
|
+
# @return [Expectations::ExpectationTarget]
|
270
|
+
# @see Expectations::ExpectationTarget#to
|
271
|
+
# @see Expectations::ExpectationTarget#not_to
|
272
|
+
|
273
|
+
# Allows multiple expectations in the provided block to fail, and then
|
274
|
+
# aggregates them into a single exception, rather than aborting on the
|
275
|
+
# first expectation failure like normal. This allows you to see all
|
276
|
+
# failures from an entire set of expectations without splitting each
|
277
|
+
# off into its own example (which may slow things down if the example
|
278
|
+
# setup is expensive).
|
279
|
+
#
|
280
|
+
# @param label [String] label for this aggregation block, which will be
|
281
|
+
# included in the aggregated exception message.
|
282
|
+
# @param metadata [Hash] additional metadata about this failure aggregation
|
283
|
+
# block. If multiple expectations fail, it will be exposed from the
|
284
|
+
# {Expectations::MultipleExpectationsNotMetError} exception. Mostly
|
285
|
+
# intended for internal RSpec use but you can use it as well.
|
286
|
+
# @yield Block containing as many expectation as you want. The block is
|
287
|
+
# simply yielded to, so you can trust that anything that works outside
|
288
|
+
# the block should work within it.
|
289
|
+
# @raise [Expectations::MultipleExpectationsNotMetError] raised when
|
290
|
+
# multiple expectations fail.
|
291
|
+
# @raise [Expectations::ExpectationNotMetError] raised when a single
|
292
|
+
# expectation fails.
|
293
|
+
# @raise [Exception] other sorts of exceptions will be raised as normal.
|
294
|
+
#
|
295
|
+
# @example
|
296
|
+
# aggregate_failures("verifying response") do
|
297
|
+
# expect(response.status).to eq(200)
|
298
|
+
# expect(response.headers).to include("Content-Type" => "text/plain")
|
299
|
+
# expect(response.body).to include("Success")
|
300
|
+
# end
|
301
|
+
#
|
302
|
+
# @note The implementation of this feature uses a thread-local variable,
|
303
|
+
# which means that if you have an expectation failure in another thread,
|
304
|
+
# it'll abort like normal.
|
305
|
+
def aggregate_failures(label=nil, metadata={}, &block)
|
306
|
+
Expectations::FailureAggregator.new(label, metadata).aggregate(&block)
|
184
307
|
end
|
185
308
|
|
186
309
|
# Passes if actual is truthy (anything but false or nil)
|
187
|
-
def
|
188
|
-
BuiltIn::
|
310
|
+
def be_truthy
|
311
|
+
BuiltIn::BeTruthy.new
|
189
312
|
end
|
313
|
+
alias_matcher :a_truthy_value, :be_truthy
|
190
314
|
|
191
|
-
# Passes if actual is
|
192
|
-
def
|
193
|
-
BuiltIn::
|
315
|
+
# Passes if actual is falsey (false or nil)
|
316
|
+
def be_falsey
|
317
|
+
BuiltIn::BeFalsey.new
|
194
318
|
end
|
319
|
+
alias_matcher :be_falsy, :be_falsey
|
320
|
+
alias_matcher :a_falsey_value, :be_falsey
|
321
|
+
alias_matcher :a_falsy_value, :be_falsey
|
195
322
|
|
196
323
|
# Passes if actual is nil
|
197
324
|
def be_nil
|
198
325
|
BuiltIn::BeNil.new
|
199
326
|
end
|
327
|
+
alias_matcher :a_nil_value, :be_nil
|
200
328
|
|
201
329
|
# @example
|
202
|
-
# expect(actual).to
|
203
|
-
# expect(actual).to
|
330
|
+
# expect(actual).to be_truthy
|
331
|
+
# expect(actual).to be_falsey
|
204
332
|
# expect(actual).to be_nil
|
205
333
|
# expect(actual).to be_[arbitrary_predicate](*args)
|
206
334
|
# expect(actual).not_to be_nil
|
@@ -219,52 +347,66 @@ module RSpec
|
|
219
347
|
# (e.g. be_empty), letting you choose the prefix that best suits the
|
220
348
|
# predicate.
|
221
349
|
def be(*args)
|
222
|
-
args.empty? ?
|
223
|
-
Matchers::BuiltIn::Be.new : equal(*args)
|
350
|
+
args.empty? ? Matchers::BuiltIn::Be.new : equal(*args)
|
224
351
|
end
|
352
|
+
alias_matcher :a_value, :be, :klass => AliasedMatcherWithOperatorSupport
|
225
353
|
|
226
354
|
# passes if target.kind_of?(klass)
|
227
355
|
def be_a(klass)
|
228
356
|
be_a_kind_of(klass)
|
229
357
|
end
|
230
|
-
|
231
358
|
alias_method :be_an, :be_a
|
232
359
|
|
233
360
|
# Passes if actual.instance_of?(expected)
|
234
361
|
#
|
235
362
|
# @example
|
236
|
-
#
|
237
|
-
# expect(5).to be_an_instance_of(Fixnum)
|
363
|
+
# expect(5).to be_an_instance_of(Integer)
|
238
364
|
# expect(5).not_to be_an_instance_of(Numeric)
|
239
365
|
# expect(5).not_to be_an_instance_of(Float)
|
240
366
|
def be_an_instance_of(expected)
|
241
367
|
BuiltIn::BeAnInstanceOf.new(expected)
|
242
368
|
end
|
243
|
-
|
244
369
|
alias_method :be_instance_of, :be_an_instance_of
|
370
|
+
alias_matcher :an_instance_of, :be_an_instance_of
|
245
371
|
|
246
372
|
# Passes if actual.kind_of?(expected)
|
247
373
|
#
|
248
374
|
# @example
|
249
|
-
#
|
250
|
-
# expect(5).to be_a_kind_of(Fixnum)
|
375
|
+
# expect(5).to be_a_kind_of(Integer)
|
251
376
|
# expect(5).to be_a_kind_of(Numeric)
|
252
377
|
# expect(5).not_to be_a_kind_of(Float)
|
253
378
|
def be_a_kind_of(expected)
|
254
379
|
BuiltIn::BeAKindOf.new(expected)
|
255
380
|
end
|
256
|
-
|
257
381
|
alias_method :be_kind_of, :be_a_kind_of
|
382
|
+
alias_matcher :a_kind_of, :be_a_kind_of
|
258
383
|
|
259
|
-
# Passes if actual
|
384
|
+
# Passes if actual.between?(min, max). Works with any Comparable object,
|
385
|
+
# including String, Symbol, Time, or Numeric (Fixnum, Bignum, Integer,
|
386
|
+
# Float, Complex, and Rational).
|
387
|
+
#
|
388
|
+
# By default, `be_between` is inclusive (i.e. passes when given either the max or min value),
|
389
|
+
# but you can make it `exclusive` by chaining that off the matcher.
|
260
390
|
#
|
261
391
|
# @example
|
392
|
+
# expect(5).to be_between(1, 10)
|
393
|
+
# expect(11).not_to be_between(1, 10)
|
394
|
+
# expect(10).not_to be_between(1, 10).exclusive
|
395
|
+
def be_between(min, max)
|
396
|
+
BuiltIn::BeBetween.new(min, max)
|
397
|
+
end
|
398
|
+
alias_matcher :a_value_between, :be_between
|
399
|
+
|
400
|
+
# Passes if actual == expected +/- delta
|
262
401
|
#
|
402
|
+
# @example
|
263
403
|
# expect(result).to be_within(0.5).of(3.0)
|
264
404
|
# expect(result).not_to be_within(0.5).of(3.0)
|
265
405
|
def be_within(delta)
|
266
406
|
BuiltIn::BeWithin.new(delta)
|
267
407
|
end
|
408
|
+
alias_matcher :a_value_within, :be_within
|
409
|
+
alias_matcher :within, :be_within
|
268
410
|
|
269
411
|
# Applied to a proc, specifies that its execution will cause some value to
|
270
412
|
# change.
|
@@ -275,12 +417,23 @@ module RSpec
|
|
275
417
|
# You can either pass <tt>receiver</tt> and <tt>message</tt>, or a block,
|
276
418
|
# but not both.
|
277
419
|
#
|
278
|
-
# When passing a block, it must use the
|
279
|
-
# do/end, as
|
280
|
-
# would errantly bind to the
|
420
|
+
# When passing a block, it must use the `{ ... }` format, not
|
421
|
+
# do/end, as `{ ... }` binds to the `change` method, whereas do/end
|
422
|
+
# would errantly bind to the `expect(..).to` or `expect(...).not_to` method.
|
281
423
|
#
|
282
|
-
#
|
424
|
+
# You can chain any of the following off of the end to specify details
|
425
|
+
# about the change:
|
426
|
+
#
|
427
|
+
# * `from`
|
428
|
+
# * `to`
|
429
|
+
#
|
430
|
+
# or any one of:
|
431
|
+
#
|
432
|
+
# * `by`
|
433
|
+
# * `by_at_least`
|
434
|
+
# * `by_at_most`
|
283
435
|
#
|
436
|
+
# @example
|
284
437
|
# expect {
|
285
438
|
# team.add_player(player)
|
286
439
|
# }.to change(roster, :count)
|
@@ -305,7 +458,7 @@ module RSpec
|
|
305
458
|
# string = "string"
|
306
459
|
# expect {
|
307
460
|
# string
|
308
|
-
# }.not_to change { string }
|
461
|
+
# }.not_to change { string }.from("string")
|
309
462
|
#
|
310
463
|
# expect {
|
311
464
|
# person.happy_birthday
|
@@ -326,15 +479,39 @@ module RSpec
|
|
326
479
|
#
|
327
480
|
# == Notes
|
328
481
|
#
|
329
|
-
# Evaluates
|
330
|
-
# evaluates the block passed to
|
482
|
+
# Evaluates `receiver.message` or `block` before and after it
|
483
|
+
# evaluates the block passed to `expect`. If the value is the same
|
484
|
+
# object, its before/after `hash` value is used to see if it has changed.
|
485
|
+
# Therefore, your object needs to properly implement `hash` to work correctly
|
486
|
+
# with this matcher.
|
331
487
|
#
|
332
|
-
#
|
333
|
-
#
|
334
|
-
#
|
488
|
+
# `expect( ... ).not_to change` supports the form that specifies `from`
|
489
|
+
# (which specifies what you expect the starting, unchanged value to be)
|
490
|
+
# but does not support forms with subsequent calls to `by`, `by_at_least`,
|
491
|
+
# `by_at_most` or `to`.
|
335
492
|
def change(receiver=nil, message=nil, &block)
|
336
493
|
BuiltIn::Change.new(receiver, message, &block)
|
337
494
|
end
|
495
|
+
alias_matcher :a_block_changing, :change
|
496
|
+
alias_matcher :changing, :change
|
497
|
+
|
498
|
+
# Passes if actual contains all of the expected regardless of order.
|
499
|
+
# This works for collections. Pass in multiple args and it will only
|
500
|
+
# pass if all args are found in collection.
|
501
|
+
#
|
502
|
+
# @note This is also available using the `=~` operator with `should`,
|
503
|
+
# but `=~` is not supported with `expect`.
|
504
|
+
#
|
505
|
+
# @example
|
506
|
+
# expect([1, 2, 3]).to contain_exactly(1, 2, 3)
|
507
|
+
# expect([1, 2, 3]).to contain_exactly(1, 3, 2)
|
508
|
+
#
|
509
|
+
# @see #match_array
|
510
|
+
def contain_exactly(*items)
|
511
|
+
BuiltIn::ContainExactly.new(items)
|
512
|
+
end
|
513
|
+
alias_matcher :a_collection_containing_exactly, :contain_exactly
|
514
|
+
alias_matcher :containing_exactly, :contain_exactly
|
338
515
|
|
339
516
|
# Passes if actual covers expected. This works for
|
340
517
|
# Ranges. You can also pass in multiple args
|
@@ -350,7 +527,9 @@ module RSpec
|
|
350
527
|
# ### Warning:: Ruby >= 1.9 only
|
351
528
|
def cover(*values)
|
352
529
|
BuiltIn::Cover.new(*values)
|
353
|
-
end
|
530
|
+
end
|
531
|
+
alias_matcher :a_range_covering, :cover
|
532
|
+
alias_matcher :covering, :cover
|
354
533
|
|
355
534
|
# Matches if the actual value ends with the expected value(s). In the case
|
356
535
|
# of a string, matches against the last `expected.length` characters of the
|
@@ -358,13 +537,15 @@ module RSpec
|
|
358
537
|
# `expected.length` elements of the actual array.
|
359
538
|
#
|
360
539
|
# @example
|
361
|
-
#
|
362
540
|
# expect("this string").to end_with "string"
|
363
541
|
# expect([0, 1, 2, 3, 4]).to end_with 4
|
364
542
|
# expect([0, 2, 3, 4, 4]).to end_with 3, 4
|
365
543
|
def end_with(*expected)
|
366
544
|
BuiltIn::EndWith.new(*expected)
|
367
545
|
end
|
546
|
+
alias_matcher :a_collection_ending_with, :end_with
|
547
|
+
alias_matcher :a_string_ending_with, :end_with
|
548
|
+
alias_matcher :ending_with, :end_with
|
368
549
|
|
369
550
|
# Passes if <tt>actual == expected</tt>.
|
370
551
|
#
|
@@ -372,25 +553,27 @@ module RSpec
|
|
372
553
|
# information about equality in Ruby.
|
373
554
|
#
|
374
555
|
# @example
|
375
|
-
#
|
376
556
|
# expect(5).to eq(5)
|
377
557
|
# expect(5).not_to eq(3)
|
378
558
|
def eq(expected)
|
379
559
|
BuiltIn::Eq.new(expected)
|
380
560
|
end
|
561
|
+
alias_matcher :an_object_eq_to, :eq
|
562
|
+
alias_matcher :eq_to, :eq
|
381
563
|
|
382
|
-
# Passes if
|
564
|
+
# Passes if `actual.eql?(expected)`
|
383
565
|
#
|
384
566
|
# See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more
|
385
567
|
# information about equality in Ruby.
|
386
568
|
#
|
387
569
|
# @example
|
388
|
-
#
|
389
570
|
# expect(5).to eql(5)
|
390
571
|
# expect(5).not_to eql(3)
|
391
572
|
def eql(expected)
|
392
573
|
BuiltIn::Eql.new(expected)
|
393
574
|
end
|
575
|
+
alias_matcher :an_object_eql_to, :eql
|
576
|
+
alias_matcher :eql_to, :eql
|
394
577
|
|
395
578
|
# Passes if <tt>actual.equal?(expected)</tt> (object identity).
|
396
579
|
#
|
@@ -398,12 +581,13 @@ module RSpec
|
|
398
581
|
# information about equality in Ruby.
|
399
582
|
#
|
400
583
|
# @example
|
401
|
-
#
|
402
|
-
# expect(5).to equal(5) # Fixnums are equal
|
584
|
+
# expect(5).to equal(5) # Integers are equal
|
403
585
|
# expect("5").not_to equal("5") # Strings that look the same are not the same object
|
404
586
|
def equal(expected)
|
405
587
|
BuiltIn::Equal.new(expected)
|
406
588
|
end
|
589
|
+
alias_matcher :an_object_equal_to, :equal
|
590
|
+
alias_matcher :equal_to, :equal
|
407
591
|
|
408
592
|
# Passes if `actual.exist?` or `actual.exists?`
|
409
593
|
#
|
@@ -412,134 +596,204 @@ module RSpec
|
|
412
596
|
def exist(*args)
|
413
597
|
BuiltIn::Exist.new(*args)
|
414
598
|
end
|
599
|
+
alias_matcher :an_object_existing, :exist
|
600
|
+
alias_matcher :existing, :exist
|
415
601
|
|
416
|
-
# Passes if
|
417
|
-
#
|
418
|
-
#
|
419
|
-
# If the receiver OWNS the collection, you must use the name of the
|
420
|
-
# collection. So if a `Team` instance has a collection named `#players`,
|
421
|
-
# you must use that name to set the expectation.
|
422
|
-
#
|
423
|
-
# If the receiver IS the collection, you can use any name you like for
|
424
|
-
# `named_collection`. We'd recommend using either "elements", "members", or
|
425
|
-
# "items" as these are all standard ways of describing the things IN a
|
426
|
-
# collection.
|
427
|
-
#
|
428
|
-
# This also works for Strings, letting you set expectations about their
|
429
|
-
# lengths.
|
602
|
+
# Passes if actual's attribute values match the expected attributes hash.
|
603
|
+
# This works no matter how you define your attribute readers.
|
430
604
|
#
|
431
605
|
# @example
|
606
|
+
# Person = Struct.new(:name, :age)
|
607
|
+
# person = Person.new("Bob", 32)
|
432
608
|
#
|
433
|
-
#
|
434
|
-
# expect(
|
609
|
+
# expect(person).to have_attributes(:name => "Bob", :age => 32)
|
610
|
+
# expect(person).to have_attributes(:name => a_string_starting_with("B"), :age => (a_value > 30) )
|
435
611
|
#
|
436
|
-
#
|
437
|
-
# expect([1,2,3]).to have(3).items #"items" is pure sugar
|
438
|
-
#
|
439
|
-
# # Passes if ['a', 'b', 'c'].count == 3
|
440
|
-
# expect([1,2,3]).to have(3).items #"items" is pure sugar
|
441
|
-
#
|
442
|
-
# # Passes if "this string".length == 11
|
443
|
-
# expect("this string").to have(11).characters #"characters" is pure sugar
|
444
|
-
def have(n)
|
445
|
-
BuiltIn::Have.new(n)
|
446
|
-
end
|
447
|
-
alias :have_exactly :have
|
448
|
-
|
449
|
-
# Exactly like have() with >=.
|
612
|
+
# @note It will fail if actual doesn't respond to any of the expected attributes.
|
450
613
|
#
|
451
614
|
# @example
|
452
|
-
# expect(
|
453
|
-
|
454
|
-
|
455
|
-
#
|
456
|
-
# `expect(..).not_to have_at_least` is not supported
|
457
|
-
def have_at_least(n)
|
458
|
-
BuiltIn::Have.new(n, :at_least)
|
459
|
-
end
|
460
|
-
|
461
|
-
# Exactly like have() with <=.
|
462
|
-
#
|
463
|
-
# @example
|
464
|
-
# expect("this").to have_at_most(4).letters
|
465
|
-
#
|
466
|
-
# ### Warning:
|
467
|
-
#
|
468
|
-
# `expect(..).not_to have_at_most` is not supported
|
469
|
-
def have_at_most(n)
|
470
|
-
BuiltIn::Have.new(n, :at_most)
|
615
|
+
# expect(person).to have_attributes(:color => "red")
|
616
|
+
def have_attributes(expected)
|
617
|
+
BuiltIn::HaveAttributes.new(expected)
|
471
618
|
end
|
619
|
+
alias_matcher :an_object_having_attributes, :have_attributes
|
620
|
+
alias_matcher :having_attributes, :have_attributes
|
472
621
|
|
473
622
|
# Passes if actual includes expected. This works for
|
474
623
|
# collections and Strings. You can also pass in multiple args
|
475
624
|
# and it will only pass if all args are found in collection.
|
476
625
|
#
|
477
626
|
# @example
|
478
|
-
#
|
479
627
|
# expect([1,2,3]).to include(3)
|
480
628
|
# expect([1,2,3]).to include(2,3)
|
481
629
|
# expect([1,2,3]).to include(2,3,4) # fails
|
482
630
|
# expect([1,2,3]).not_to include(4)
|
483
631
|
# expect("spread").to include("read")
|
484
632
|
# expect("spread").not_to include("red")
|
633
|
+
# expect(:a => 1, :b => 2).to include(:a)
|
634
|
+
# expect(:a => 1, :b => 2).to include(:a, :b)
|
635
|
+
# expect(:a => 1, :b => 2).to include(:a => 1)
|
636
|
+
# expect(:a => 1, :b => 2).to include(:b => 2, :a => 1)
|
637
|
+
# expect(:a => 1, :b => 2).to include(:c) # fails
|
638
|
+
# expect(:a => 1, :b => 2).not_to include(:a => 2)
|
485
639
|
def include(*expected)
|
486
640
|
BuiltIn::Include.new(*expected)
|
487
641
|
end
|
642
|
+
alias_matcher :a_collection_including, :include
|
643
|
+
alias_matcher :a_string_including, :include
|
644
|
+
alias_matcher :a_hash_including, :include
|
645
|
+
alias_matcher :including, :include
|
488
646
|
|
489
|
-
#
|
647
|
+
# Passes if the provided matcher passes when checked against all
|
648
|
+
# elements of the collection.
|
490
649
|
#
|
491
650
|
# @example
|
651
|
+
# expect([1, 3, 5]).to all be_odd
|
652
|
+
# expect([1, 3, 6]).to all be_odd # fails
|
492
653
|
#
|
493
|
-
#
|
494
|
-
#
|
495
|
-
#
|
496
|
-
# expect(zipcode).to match_regex("90210")
|
654
|
+
# @note The negative form `not_to all` is not supported. Instead
|
655
|
+
# use `not_to include` or pass a negative form of a matcher
|
656
|
+
# as the argument (e.g. `all exclude(:foo)`).
|
497
657
|
#
|
498
|
-
# @note
|
499
|
-
#
|
500
|
-
#
|
501
|
-
#
|
502
|
-
|
658
|
+
# @note You can also use this with compound matchers as well.
|
659
|
+
#
|
660
|
+
# @example
|
661
|
+
# expect([1, 3, 5]).to all( be_odd.and be_an(Integer) )
|
662
|
+
def all(expected)
|
663
|
+
BuiltIn::All.new(expected)
|
664
|
+
end
|
665
|
+
|
666
|
+
# Given a `Regexp` or `String`, passes if `actual.match(pattern)`
|
667
|
+
# Given an arbitrary nested data structure (e.g. arrays and hashes),
|
668
|
+
# matches if `expected === actual` || `actual == expected` for each
|
669
|
+
# pair of elements.
|
670
|
+
#
|
671
|
+
# @example
|
672
|
+
# expect(email).to match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
|
673
|
+
# expect(email).to match("@example.com")
|
674
|
+
#
|
675
|
+
# @example
|
676
|
+
# hash = {
|
677
|
+
# :a => {
|
678
|
+
# :b => ["foo", 5],
|
679
|
+
# :c => { :d => 2.05 }
|
680
|
+
# }
|
681
|
+
# }
|
682
|
+
#
|
683
|
+
# expect(hash).to match(
|
684
|
+
# :a => {
|
685
|
+
# :b => a_collection_containing_exactly(
|
686
|
+
# a_string_starting_with("f"),
|
687
|
+
# an_instance_of(Integer)
|
688
|
+
# ),
|
689
|
+
# :c => { :d => (a_value < 3) }
|
690
|
+
# }
|
691
|
+
# )
|
692
|
+
#
|
693
|
+
# @note The `match_regex` alias is deprecated and is not recommended for use.
|
694
|
+
# It was added in 2.12.1 to facilitate its use from within custom
|
695
|
+
# matchers (due to how the custom matcher DSL was evaluated in 2.x,
|
696
|
+
# `match` could not be used there), but is no longer needed in 3.x.
|
503
697
|
def match(expected)
|
504
698
|
BuiltIn::Match.new(expected)
|
505
699
|
end
|
700
|
+
alias_matcher :match_regex, :match
|
701
|
+
alias_matcher :an_object_matching, :match
|
702
|
+
alias_matcher :a_string_matching, :match
|
703
|
+
alias_matcher :matching, :match
|
506
704
|
|
507
|
-
|
705
|
+
# An alternate form of `contain_exactly` that accepts
|
706
|
+
# the expected contents as a single array arg rather
|
707
|
+
# than splatted out as individual items.
|
708
|
+
#
|
709
|
+
# @example
|
710
|
+
# expect(results).to contain_exactly(1, 2)
|
711
|
+
# # is identical to:
|
712
|
+
# expect(results).to match_array([1, 2])
|
713
|
+
#
|
714
|
+
# @see #contain_exactly
|
715
|
+
def match_array(items)
|
716
|
+
contain_exactly(*items)
|
717
|
+
end
|
718
|
+
alias_matcher :an_array_matching, :match_array do |desc|
|
719
|
+
desc.sub("contain exactly", "an array containing exactly")
|
720
|
+
end
|
721
|
+
|
722
|
+
# With no arg, passes if the block outputs `to_stdout` or `to_stderr`.
|
723
|
+
# With a string, passes if the block outputs that specific string `to_stdout` or `to_stderr`.
|
724
|
+
# With a regexp or matcher, passes if the block outputs a string `to_stdout` or `to_stderr` that matches.
|
725
|
+
#
|
726
|
+
# To capture output from any spawned subprocess as well, use `to_stdout_from_any_process` or
|
727
|
+
# `to_stderr_from_any_process`. Output from any process that inherits the main process's corresponding
|
728
|
+
# standard stream will be captured.
|
729
|
+
#
|
730
|
+
# @example
|
731
|
+
# expect { print 'foo' }.to output.to_stdout
|
732
|
+
# expect { print 'foo' }.to output('foo').to_stdout
|
733
|
+
# expect { print 'foo' }.to output(/foo/).to_stdout
|
734
|
+
#
|
735
|
+
# expect { do_something }.to_not output.to_stdout
|
736
|
+
#
|
737
|
+
# expect { warn('foo') }.to output.to_stderr
|
738
|
+
# expect { warn('foo') }.to output('foo').to_stderr
|
739
|
+
# expect { warn('foo') }.to output(/foo/).to_stderr
|
740
|
+
#
|
741
|
+
# expect { do_something }.to_not output.to_stderr
|
742
|
+
#
|
743
|
+
# expect { system('echo foo') }.to output("foo\n").to_stdout_from_any_process
|
744
|
+
# expect { system('echo foo', out: :err) }.to output("foo\n").to_stderr_from_any_process
|
745
|
+
#
|
746
|
+
# @note `to_stdout` and `to_stderr` work by temporarily replacing `$stdout` or `$stderr`,
|
747
|
+
# so they're not able to intercept stream output that explicitly uses `STDOUT`/`STDERR`
|
748
|
+
# or that uses a reference to `$stdout`/`$stderr` that was stored before the
|
749
|
+
# matcher was used.
|
750
|
+
# @note `to_stdout_from_any_process` and `to_stderr_from_any_process` use Tempfiles, and
|
751
|
+
# are thus significantly (~30x) slower than `to_stdout` and `to_stderr`.
|
752
|
+
def output(expected=nil)
|
753
|
+
BuiltIn::Output.new(expected)
|
754
|
+
end
|
755
|
+
alias_matcher :a_block_outputting, :output
|
508
756
|
|
509
757
|
# With no args, matches if any error is raised.
|
510
758
|
# With a named error, matches only if that specific error is raised.
|
511
|
-
# With a named error and
|
512
|
-
# With a named error and
|
759
|
+
# With a named error and message specified as a String, matches only if both match.
|
760
|
+
# With a named error and message specified as a Regexp, matches only if both match.
|
513
761
|
# Pass an optional block to perform extra verifications on the exception matched
|
514
762
|
#
|
515
763
|
# @example
|
516
|
-
#
|
517
764
|
# expect { do_something_risky }.to raise_error
|
518
765
|
# expect { do_something_risky }.to raise_error(PoorRiskDecisionError)
|
519
766
|
# expect { do_something_risky }.to raise_error(PoorRiskDecisionError) { |error| expect(error.data).to eq 42 }
|
767
|
+
# expect { do_something_risky }.to raise_error { |error| expect(error.data).to eq 42 }
|
520
768
|
# expect { do_something_risky }.to raise_error(PoorRiskDecisionError, "that was too risky")
|
521
769
|
# expect { do_something_risky }.to raise_error(PoorRiskDecisionError, /oo ri/)
|
770
|
+
# expect { do_something_risky }.to raise_error("that was too risky")
|
522
771
|
#
|
523
772
|
# expect { do_something_risky }.not_to raise_error
|
524
|
-
|
525
|
-
# expect { do_something_risky }.not_to raise_error(PoorRiskDecisionError, "that was too risky")
|
526
|
-
# expect { do_something_risky }.not_to raise_error(PoorRiskDecisionError, /oo ri/)
|
527
|
-
def raise_error(error=Exception, message=nil, &block)
|
773
|
+
def raise_error(error=BuiltIn::RaiseError::UndefinedValue, message=nil, &block)
|
528
774
|
BuiltIn::RaiseError.new(error, message, &block)
|
529
775
|
end
|
530
|
-
|
531
776
|
alias_method :raise_exception, :raise_error
|
532
777
|
|
778
|
+
alias_matcher :a_block_raising, :raise_error do |desc|
|
779
|
+
desc.sub("raise", "a block raising")
|
780
|
+
end
|
781
|
+
|
782
|
+
alias_matcher :raising, :raise_error do |desc|
|
783
|
+
desc.sub("raise", "raising")
|
784
|
+
end
|
785
|
+
|
533
786
|
# Matches if the target object responds to all of the names
|
534
787
|
# provided. Names can be Strings or Symbols.
|
535
788
|
#
|
536
789
|
# @example
|
537
|
-
#
|
538
|
-
# expect("string").to respond_to(:length)
|
790
|
+
# expect("string").to respond_to(:length)
|
539
791
|
#
|
540
792
|
def respond_to(*names)
|
541
793
|
BuiltIn::RespondTo.new(*names)
|
542
794
|
end
|
795
|
+
alias_matcher :an_object_responding_to, :respond_to
|
796
|
+
alias_matcher :responding_to, :respond_to
|
543
797
|
|
544
798
|
# Passes if the submitted block returns true. Yields target to the
|
545
799
|
# block.
|
@@ -551,12 +805,16 @@ module RSpec
|
|
551
805
|
# If you do find yourself in such a situation, you could always write
|
552
806
|
# a custom matcher, which would likely make your specs more expressive.
|
553
807
|
#
|
554
|
-
# @
|
808
|
+
# @param description [String] optional description to be used for this matcher.
|
555
809
|
#
|
810
|
+
# @example
|
556
811
|
# expect(5).to satisfy { |n| n > 3 }
|
557
|
-
|
558
|
-
|
812
|
+
# expect(5).to satisfy("be greater than 3") { |n| n > 3 }
|
813
|
+
def satisfy(description=nil, &block)
|
814
|
+
BuiltIn::Satisfy.new(description, &block)
|
559
815
|
end
|
816
|
+
alias_matcher :an_object_satisfying, :satisfy
|
817
|
+
alias_matcher :satisfying, :satisfy
|
560
818
|
|
561
819
|
# Matches if the actual value starts with the expected value(s). In the
|
562
820
|
# case of a string, matches against the first `expected.length` characters
|
@@ -564,13 +822,15 @@ module RSpec
|
|
564
822
|
# `expected.length` elements of the actual array.
|
565
823
|
#
|
566
824
|
# @example
|
567
|
-
#
|
568
825
|
# expect("this string").to start_with "this s"
|
569
826
|
# expect([0, 1, 2, 3, 4]).to start_with 0
|
570
827
|
# expect([0, 2, 3, 4, 4]).to start_with 0, 1
|
571
828
|
def start_with(*expected)
|
572
829
|
BuiltIn::StartWith.new(*expected)
|
573
830
|
end
|
831
|
+
alias_matcher :a_collection_starting_with, :start_with
|
832
|
+
alias_matcher :a_string_starting_with, :start_with
|
833
|
+
alias_matcher :starting_with, :start_with
|
574
834
|
|
575
835
|
# Given no argument, matches if a proc throws any Symbol.
|
576
836
|
#
|
@@ -580,7 +840,6 @@ module RSpec
|
|
580
840
|
# specified Symbol with the specified arg.
|
581
841
|
#
|
582
842
|
# @example
|
583
|
-
#
|
584
843
|
# expect { do_something_risky }.to throw_symbol
|
585
844
|
# expect { do_something_risky }.to throw_symbol(:that_was_risky)
|
586
845
|
# expect { do_something_risky }.to throw_symbol(:that_was_risky, 'culprit')
|
@@ -592,27 +851,33 @@ module RSpec
|
|
592
851
|
BuiltIn::ThrowSymbol.new(expected_symbol, expected_arg)
|
593
852
|
end
|
594
853
|
|
854
|
+
alias_matcher :a_block_throwing, :throw_symbol do |desc|
|
855
|
+
desc.sub("throw", "a block throwing")
|
856
|
+
end
|
857
|
+
|
858
|
+
alias_matcher :throwing, :throw_symbol do |desc|
|
859
|
+
desc.sub("throw", "throwing")
|
860
|
+
end
|
861
|
+
|
595
862
|
# Passes if the method called in the expect block yields, regardless
|
596
863
|
# of whether or not arguments are yielded.
|
597
864
|
#
|
598
865
|
# @example
|
599
|
-
#
|
600
866
|
# expect { |b| 5.tap(&b) }.to yield_control
|
601
867
|
# expect { |b| "a".to_sym(&b) }.not_to yield_control
|
602
868
|
#
|
603
869
|
# @note Your expect block must accept a parameter and pass it on to
|
604
870
|
# the method-under-test as a block.
|
605
|
-
# @note This matcher is not designed for use with methods that yield
|
606
|
-
# multiple times.
|
607
871
|
def yield_control
|
608
872
|
BuiltIn::YieldControl.new
|
609
873
|
end
|
874
|
+
alias_matcher :a_block_yielding_control, :yield_control
|
875
|
+
alias_matcher :yielding_control, :yield_control
|
610
876
|
|
611
877
|
# Passes if the method called in the expect block yields with
|
612
878
|
# no arguments. Fails if it does not yield, or yields with arguments.
|
613
879
|
#
|
614
880
|
# @example
|
615
|
-
#
|
616
881
|
# expect { |b| User.transaction(&b) }.to yield_with_no_args
|
617
882
|
# expect { |b| 5.tap(&b) }.not_to yield_with_no_args # because it yields with `5`
|
618
883
|
# expect { |b| "a".to_sym(&b) }.not_to yield_with_no_args # because it does not yield
|
@@ -624,6 +889,8 @@ module RSpec
|
|
624
889
|
def yield_with_no_args
|
625
890
|
BuiltIn::YieldWithNoArgs.new
|
626
891
|
end
|
892
|
+
alias_matcher :a_block_yielding_with_no_args, :yield_with_no_args
|
893
|
+
alias_matcher :yielding_with_no_args, :yield_with_no_args
|
627
894
|
|
628
895
|
# Given no arguments, matches if the method called in the expect
|
629
896
|
# block yields with arguments (regardless of what they are or how
|
@@ -637,10 +904,9 @@ module RSpec
|
|
637
904
|
# operator, the matcher will pass.
|
638
905
|
#
|
639
906
|
# @example
|
640
|
-
#
|
641
907
|
# expect { |b| 5.tap(&b) }.to yield_with_args # because #tap yields an arg
|
642
908
|
# expect { |b| 5.tap(&b) }.to yield_with_args(5) # because 5 == 5
|
643
|
-
# expect { |b| 5.tap(&b) }.to yield_with_args(
|
909
|
+
# expect { |b| 5.tap(&b) }.to yield_with_args(Integer) # because Integer === 5
|
644
910
|
# expect { |b| File.open("f.txt", &b) }.to yield_with_args(/txt/) # because /txt/ === "f.txt"
|
645
911
|
#
|
646
912
|
# expect { |b| User.transaction(&b) }.not_to yield_with_args # because it yields no args
|
@@ -653,6 +919,8 @@ module RSpec
|
|
653
919
|
def yield_with_args(*args)
|
654
920
|
BuiltIn::YieldWithArgs.new(*args)
|
655
921
|
end
|
922
|
+
alias_matcher :a_block_yielding_with_args, :yield_with_args
|
923
|
+
alias_matcher :yielding_with_args, :yield_with_args
|
656
924
|
|
657
925
|
# Designed for use with methods that repeatedly yield (such as
|
658
926
|
# iterators). Passes if the method called in the expect block yields
|
@@ -663,7 +931,6 @@ module RSpec
|
|
663
931
|
# operator, the matcher will pass.
|
664
932
|
#
|
665
933
|
# @example
|
666
|
-
#
|
667
934
|
# expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3)
|
668
935
|
# expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [:b, 2])
|
669
936
|
# expect { |b| [1, 2, 3].each(&b) }.not_to yield_successive_args(1, 2)
|
@@ -673,25 +940,105 @@ module RSpec
|
|
673
940
|
def yield_successive_args(*args)
|
674
941
|
BuiltIn::YieldSuccessiveArgs.new(*args)
|
675
942
|
end
|
943
|
+
alias_matcher :a_block_yielding_successive_args, :yield_successive_args
|
944
|
+
alias_matcher :yielding_successive_args, :yield_successive_args
|
676
945
|
|
677
|
-
#
|
678
|
-
# This
|
679
|
-
#
|
680
|
-
#
|
681
|
-
# @
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
946
|
+
# Delegates to {RSpec::Expectations.configuration}.
|
947
|
+
# This is here because rspec-core's `expect_with` option
|
948
|
+
# looks for a `configuration` method on the mixin
|
949
|
+
# (`RSpec::Matchers`) to yield to a block.
|
950
|
+
# @return [RSpec::Expectations::Configuration] the configuration object
|
951
|
+
def self.configuration
|
952
|
+
Expectations.configuration
|
953
|
+
end
|
954
|
+
|
955
|
+
private
|
956
|
+
|
957
|
+
BE_PREDICATE_REGEX = /^(?:be_(?:an?_)?)(.*)/
|
958
|
+
HAS_REGEX = /^(?:have_)(.*)/
|
959
|
+
DYNAMIC_MATCHER_REGEX = Regexp.union(BE_PREDICATE_REGEX, HAS_REGEX)
|
960
|
+
|
961
|
+
def method_missing(method, *args, &block)
|
962
|
+
case method.to_s
|
963
|
+
when BE_PREDICATE_REGEX
|
964
|
+
BuiltIn::BePredicate.new(method, *args, &block)
|
965
|
+
when HAS_REGEX
|
966
|
+
BuiltIn::Has.new(method, *args, &block)
|
967
|
+
else
|
968
|
+
super
|
969
|
+
end
|
693
970
|
end
|
971
|
+
ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
|
694
972
|
|
695
|
-
|
973
|
+
if RUBY_VERSION.to_f >= 1.9
|
974
|
+
def respond_to_missing?(method, *)
|
975
|
+
method =~ DYNAMIC_MATCHER_REGEX || super
|
976
|
+
end
|
977
|
+
else # for 1.8.7
|
978
|
+
# :nocov:
|
979
|
+
def respond_to?(method, *)
|
980
|
+
method = method.to_s
|
981
|
+
method =~ DYNAMIC_MATCHER_REGEX || super
|
982
|
+
end
|
983
|
+
public :respond_to?
|
984
|
+
# :nocov:
|
985
|
+
end
|
986
|
+
|
987
|
+
# @api private
|
988
|
+
def self.is_a_matcher?(obj)
|
989
|
+
return true if ::RSpec::Matchers::BuiltIn::BaseMatcher === obj
|
990
|
+
begin
|
991
|
+
return false if obj.respond_to?(:i_respond_to_everything_so_im_not_really_a_matcher)
|
992
|
+
rescue NoMethodError
|
993
|
+
# Some objects, like BasicObject, don't implemented standard
|
994
|
+
# reflection methods.
|
995
|
+
return false
|
996
|
+
end
|
997
|
+
return false unless obj.respond_to?(:matches?)
|
998
|
+
|
999
|
+
obj.respond_to?(:failure_message) ||
|
1000
|
+
obj.respond_to?(:failure_message_for_should) # support legacy matchers
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
::RSpec::Support.register_matcher_definition do |obj|
|
1004
|
+
is_a_matcher?(obj)
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
# @api private
|
1008
|
+
def self.is_a_describable_matcher?(obj)
|
1009
|
+
is_a_matcher?(obj) && obj.respond_to?(:description)
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
class << self
|
1013
|
+
private
|
1014
|
+
|
1015
|
+
if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9'
|
1016
|
+
# Note that `included` doesn't work for this because it is triggered
|
1017
|
+
# _after_ `RSpec::Matchers` is an ancestor of the inclusion host, rather
|
1018
|
+
# than _before_, like `append_features`. It's important we check this before
|
1019
|
+
# in order to find the cases where it was already previously included.
|
1020
|
+
# @api private
|
1021
|
+
def append_features(mod)
|
1022
|
+
return super if mod < self # `mod < self` indicates a re-inclusion.
|
1023
|
+
|
1024
|
+
subclasses = ObjectSpace.each_object(Class).select { |c| c < mod && c < self }
|
1025
|
+
return super unless subclasses.any?
|
1026
|
+
|
1027
|
+
subclasses.reject! { |s| subclasses.any? { |s2| s < s2 } } # Filter to the root ancestor.
|
1028
|
+
subclasses = subclasses.map { |s| "`#{s}`" }.join(", ")
|
1029
|
+
|
1030
|
+
RSpec.warning "`#{self}` has been included in a superclass (`#{mod}`) " \
|
1031
|
+
"after previously being included in subclasses (#{subclasses}), " \
|
1032
|
+
"which can trigger infinite recursion from `super` due to an MRI 1.9 bug " \
|
1033
|
+
"(https://redmine.ruby-lang.org/issues/3351). To work around this, " \
|
1034
|
+
"either upgrade to MRI 2.0+, include a dup of the module (e.g. " \
|
1035
|
+
"`include #{self}.dup`), or find a way to include `#{self}` in `#{mod}` " \
|
1036
|
+
"before it is included in subclasses (#{subclasses}). See " \
|
1037
|
+
"https://github.com/rspec/rspec-expectations/issues/814 for more info"
|
1038
|
+
|
1039
|
+
super
|
1040
|
+
end
|
1041
|
+
end
|
1042
|
+
end
|
696
1043
|
end
|
697
1044
|
end
|