rspec-expectations 3.2.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +55 -4
- data/README.md +1 -1
- data/lib/rspec/expectations.rb +13 -1
- data/lib/rspec/expectations/configuration.rb +17 -0
- data/lib/rspec/expectations/expectation_target.rb +3 -9
- data/lib/rspec/expectations/fail_with.rb +1 -3
- data/lib/rspec/expectations/failure_aggregator.rb +194 -0
- data/lib/rspec/expectations/minitest_integration.rb +13 -0
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +59 -5
- data/lib/rspec/matchers/built_in/base_matcher.rb +56 -7
- data/lib/rspec/matchers/built_in/be.rb +25 -15
- data/lib/rspec/matchers/built_in/be_between.rb +1 -1
- data/lib/rspec/matchers/built_in/be_within.rb +2 -2
- data/lib/rspec/matchers/built_in/contain_exactly.rb +12 -8
- data/lib/rspec/matchers/built_in/eq.rb +3 -38
- data/lib/rspec/matchers/built_in/eql.rb +2 -2
- data/lib/rspec/matchers/built_in/equal.rb +3 -3
- data/lib/rspec/matchers/built_in/exist.rb +2 -2
- data/lib/rspec/matchers/built_in/has.rb +3 -1
- data/lib/rspec/matchers/built_in/have_attributes.rb +5 -4
- data/lib/rspec/matchers/built_in/include.rb +44 -19
- data/lib/rspec/matchers/built_in/match.rb +9 -1
- data/lib/rspec/matchers/built_in/operators.rb +14 -5
- data/lib/rspec/matchers/built_in/output.rb +9 -2
- data/lib/rspec/matchers/built_in/raise_error.rb +64 -22
- data/lib/rspec/matchers/built_in/respond_to.rb +2 -3
- data/lib/rspec/matchers/built_in/satisfy.rb +7 -9
- data/lib/rspec/matchers/built_in/start_or_end_with.rb +3 -1
- data/lib/rspec/matchers/built_in/throw_symbol.rb +1 -1
- data/lib/rspec/matchers/built_in/yield.rb +7 -5
- data/lib/rspec/matchers/composable.rb +5 -4
- data/lib/rspec/matchers/dsl.rb +19 -6
- data/lib/rspec/matchers/english_phrasing.rb +42 -0
- data/lib/rspec/matchers/expecteds_for_multiple_diffs.rb +2 -8
- data/lib/rspec/matchers/fail_matchers.rb +42 -0
- data/lib/rspec/matchers/matcher_delegator.rb +2 -0
- metadata +9 -7
- metadata.gz.sig +0 -0
- data/lib/rspec/matchers/pretty.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 050cebd3fe559b7cd5391cba39333fc9815e7650
|
4
|
+
data.tar.gz: 0034049cdc0f2fd7ab5210ba606b72a267b3abbc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afee08bfc1eedff07267817c53989802b649cab426c15f55aa869e71bac7db27eadb679b854d5c9da3bbdb7ac39bedcc7c448e8fd7ae8eec311b1a19a694ff07
|
7
|
+
data.tar.gz: 1215a16c5ec70686dba0fd02d4ae14c4238352a995850a4c437eda0d7a4279597e1866f7426c623afc31ba32db5215517102576a2442caeddfdc44da308e5123
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/Changelog.md
CHANGED
@@ -1,3 +1,54 @@
|
|
1
|
+
### 3.3.0 / 2015-06-12
|
2
|
+
[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.2.1...v3.3.0)
|
3
|
+
|
4
|
+
Enhancements:
|
5
|
+
|
6
|
+
* Expose `RSpec::Matchers::EnglishPhrasing` to make it easier to write
|
7
|
+
nice failure messages in custom matchers. (Jared Beck, #736)
|
8
|
+
* Add `RSpec::Matchers::FailMatchers`, a mixin which provides
|
9
|
+
`fail`, `fail_with` and `fail_including` matchers for use in
|
10
|
+
specifying that an expectation fails for use by
|
11
|
+
extension/plugin authors. (Charlie Rudolph, #729)
|
12
|
+
* Avoid loading `tempfile` (and its dependencies) unless
|
13
|
+
it is absolutely needed. (Myron Marston, #735)
|
14
|
+
* Improve failure output when attempting to use `be_true` or `be_false`.
|
15
|
+
(Tim Wade, #744)
|
16
|
+
* Define `RSpec::Matchers#respond_to_missing?` so that
|
17
|
+
`RSpec::Matchers#respond_to?` and `RSpec::Matchers#method` handle
|
18
|
+
dynamic predicate matchers. (Andrei Botalov, #751)
|
19
|
+
* Use custom Time/DateTime/BigDecimal formatting for all matchers
|
20
|
+
so they are consistently represented in failure messages.
|
21
|
+
(Gavin Miller, #740)
|
22
|
+
* Add configuration to turn off warnings about matcher combinations that
|
23
|
+
may cause false positives. (Jon Rowe, #768)
|
24
|
+
* Warn when using a bare `raise_error` matcher that you may be subject to
|
25
|
+
false positives. (Jon Rowe, #768)
|
26
|
+
* Warn rather than raise when using the`raise_error` matcher in negative
|
27
|
+
expectations that may be subject to false positives. (Jon Rowe, #775)
|
28
|
+
* Improve failure message for `include(a, b, c)` so that if `a` and `b`
|
29
|
+
are included the failure message only mentions `c`. (Chris Arcand, #780)
|
30
|
+
* Allow `satisfy` matcher to take an optional description argument
|
31
|
+
that will be used in the `description`, `failure_message` and
|
32
|
+
`failure_message_when_negated` in place of the undescriptive
|
33
|
+
"sastify block". (Chris Arcand, #783)
|
34
|
+
* Add new `aggregate_failures` API that allows multiple independent
|
35
|
+
expectations to all fail and be listed in the failure output, rather
|
36
|
+
than the example aborting on the first failure. (Myron Marston, #776)
|
37
|
+
* Improve `raise_error` matcher so that it can accept a matcher as a single argument
|
38
|
+
that matches the message. (Time Wade, #782)
|
39
|
+
|
40
|
+
Bug Fixes:
|
41
|
+
|
42
|
+
* Make `contain_exactly` / `match_array` work with strict test doubles
|
43
|
+
that have not defined `<=>`. (Myron Marston, #758)
|
44
|
+
* Fix `include` matcher so that it omits the diff when it would
|
45
|
+
confusingly highlight items that are actually included but are not
|
46
|
+
an exact match in a line-by-line diff. (Tim Wade, #763)
|
47
|
+
* Fix `match` matcher so that it does not blow up when matching a string
|
48
|
+
or regex against another matcher (rather than a string or regex).
|
49
|
+
(Myron Marston, #772)
|
50
|
+
* Silence whitespace-only diffs. (Myron Marston, #801)
|
51
|
+
|
1
52
|
### 3.2.1 / 2015-04-06
|
2
53
|
[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.2.0...v3.2.1)
|
3
54
|
|
@@ -321,7 +372,7 @@ Breaking Changes for 3.0.0:
|
|
321
372
|
(Sam Phippen)
|
322
373
|
* Remove the deprecated `have`, `have_at_least` and `have_at_most` matchers.
|
323
374
|
You can continue using those matchers through https://github.com/rspec/rspec-collection_matchers,
|
324
|
-
or you can rewrite your expectations with something like
|
375
|
+
or you can rewrite your expectations with something like
|
325
376
|
`expect(your_object.size).to eq(num)`. (Hugo Baraúna)
|
326
377
|
* Rename `be_true` and `be_false` to `be_truthy` and `be_falsey`. (Sam Phippen)
|
327
378
|
* Make `expect { }.to_not raise_error(SomeSpecificClass, message)`,
|
@@ -442,9 +493,9 @@ Deprecations:
|
|
442
493
|
Deprecations
|
443
494
|
|
444
495
|
* Deprecate `have`, `have_at_least` and `have_at_most`. You can continue using those
|
445
|
-
|
446
|
-
|
447
|
-
|
496
|
+
matchers through https://github.com/rspec/rspec-collection_matchers, or
|
497
|
+
you can rewrite your expectations with something like
|
498
|
+
`expect(your_object.size).to eq(num)`. (Hugo Baraúna)
|
448
499
|
* Deprecate `be_xyz` predicate matcher when `xyz?` is a private method.
|
449
500
|
(Jon Rowe)
|
450
501
|
* Deprecate `be_true`/`be_false` in favour of `be_truthy`/`be_falsey`
|
data/README.md
CHANGED
@@ -95,7 +95,7 @@ Note: The new `expect` syntax no longer supports the `=~` matcher.
|
|
95
95
|
|
96
96
|
```ruby
|
97
97
|
expect(actual).to be_an_instance_of(expected) # passes if actual.class == expected
|
98
|
-
expect(actual).to be_a(expected) # passes if actual.
|
98
|
+
expect(actual).to be_a(expected) # passes if actual.kind_of?(expected)
|
99
99
|
expect(actual).to be_an(expected) # an alias for be_a
|
100
100
|
expect(actual).to be_a_kind_of(expected) # another alias
|
101
101
|
```
|
data/lib/rspec/expectations.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rspec/support'
|
2
2
|
RSpec::Support.require_rspec_support "caller_filter"
|
3
3
|
RSpec::Support.require_rspec_support "warnings"
|
4
|
+
RSpec::Support.require_rspec_support "object_formatter"
|
4
5
|
|
5
6
|
require 'rspec/matchers'
|
6
7
|
|
@@ -63,7 +64,18 @@ module RSpec
|
|
63
64
|
# the user sets an expectation, it can't be caught in their
|
64
65
|
# code by a bare `rescue`.
|
65
66
|
# @api public
|
66
|
-
class ExpectationNotMetError <
|
67
|
+
class ExpectationNotMetError < Exception
|
67
68
|
end
|
69
|
+
|
70
|
+
# Exception raised from `aggregate_failures` when multiple expectations fail.
|
71
|
+
#
|
72
|
+
# @note The constant is defined here but the extensive logic of this class
|
73
|
+
# is lazily defined when `FailureAggregator` is autoloaded, since we do
|
74
|
+
# not need to waste time defining that functionality unless
|
75
|
+
# `aggregate_failures` is used.
|
76
|
+
class MultipleExpectationsNotMetError < ExpectationNotMetError
|
77
|
+
end
|
78
|
+
|
79
|
+
autoload :FailureAggregator, "rspec/expectations/failure_aggregator"
|
68
80
|
end
|
69
81
|
end
|
@@ -18,6 +18,10 @@ module RSpec
|
|
18
18
|
#
|
19
19
|
# RSpec::Expectations.configuration
|
20
20
|
class Configuration
|
21
|
+
def initialize
|
22
|
+
@warn_about_potential_false_positives = true
|
23
|
+
end
|
24
|
+
|
21
25
|
# Configures the supported syntax.
|
22
26
|
# @param [Array<Symbol>, Symbol] values the syntaxes to enable
|
23
27
|
# @example
|
@@ -133,6 +137,19 @@ module RSpec
|
|
133
137
|
backtrace
|
134
138
|
end
|
135
139
|
end
|
140
|
+
|
141
|
+
# Configures whether RSpec will warn about matcher use which will
|
142
|
+
# potentially cause false positives in tests.
|
143
|
+
#
|
144
|
+
# @param value [Boolean]
|
145
|
+
attr_writer :warn_about_potential_false_positives
|
146
|
+
|
147
|
+
# Indicates whether RSpec will warn about matcher use which will
|
148
|
+
# potentially cause false positives in tests, generally you want to
|
149
|
+
# avoid such scenarios so this defaults to `true`.
|
150
|
+
def warn_about_potential_false_positives?
|
151
|
+
@warn_about_potential_false_positives
|
152
|
+
end
|
136
153
|
end
|
137
154
|
|
138
155
|
# The configuration object.
|
@@ -98,9 +98,9 @@ module RSpec
|
|
98
98
|
def enforce_block_expectation(matcher)
|
99
99
|
return if supports_block_expectations?(matcher)
|
100
100
|
|
101
|
-
raise ExpectationNotMetError, "You must pass an argument rather than " \
|
102
|
-
"
|
103
|
-
"
|
101
|
+
raise ExpectationNotMetError, "You must pass an argument rather than a block to use the provided " \
|
102
|
+
"matcher (#{RSpec::Support::ObjectFormatter.format(matcher)}), or the matcher must implement " \
|
103
|
+
"`supports_block_expectations?`."
|
104
104
|
end
|
105
105
|
|
106
106
|
def supports_block_expectations?(matcher)
|
@@ -108,12 +108,6 @@ module RSpec
|
|
108
108
|
rescue NoMethodError
|
109
109
|
false
|
110
110
|
end
|
111
|
-
|
112
|
-
def description_of(matcher)
|
113
|
-
matcher.description
|
114
|
-
rescue NoMethodError
|
115
|
-
matcher.inspect
|
116
|
-
end
|
117
111
|
end
|
118
112
|
end
|
119
113
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
RSpec::Support.require_rspec_support 'differ'
|
2
|
-
|
3
1
|
module RSpec
|
4
2
|
module Expectations
|
5
3
|
class << self
|
@@ -26,7 +24,7 @@ module RSpec
|
|
26
24
|
|
27
25
|
message = ::RSpec::Matchers::ExpectedsForMultipleDiffs.from(expected).message_with_diff(message, differ, actual)
|
28
26
|
|
29
|
-
|
27
|
+
RSpec::Support.notify_failure(RSpec::Expectations::ExpectationNotMetError.new message)
|
30
28
|
end
|
31
29
|
end
|
32
30
|
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Expectations
|
3
|
+
# @private
|
4
|
+
class FailureAggregator
|
5
|
+
attr_reader :block_label, :metadata
|
6
|
+
|
7
|
+
def aggregate
|
8
|
+
RSpec::Support.with_failure_notifier(self) do
|
9
|
+
begin
|
10
|
+
yield
|
11
|
+
rescue ExpectationNotMetError => e
|
12
|
+
# Normally, expectation failures will be notified via the `call` method, below,
|
13
|
+
# but since the failure notifier uses a thread local variable, failing expectations
|
14
|
+
# in another thread will still raise. We handle that here and categorize it as part
|
15
|
+
# of `failures` rather than letting it fall through and be categorized as part of
|
16
|
+
# `other_errors`.
|
17
|
+
failures << e
|
18
|
+
rescue Exception => e
|
19
|
+
# While it is normally a bad practice to rescue `Exception`, it's important we do
|
20
|
+
# so here. It's low risk (`notify_aggregated_failures` below will re-raise the exception,
|
21
|
+
# or raise a `MultipleExpectationsNotMetError` that includes the exception), and it's
|
22
|
+
# essential that the user is notified of expectation failures that may have already
|
23
|
+
# occurred in the `aggregate_failures` block. Those expectation failures may provide
|
24
|
+
# important diagnostics for understanding why this exception occurred, and if we simply
|
25
|
+
# allowed this exception to be raised as-is, it would (wrongly) suggest to the user
|
26
|
+
# that the expectation passed when it did not, which would be quite confusing.
|
27
|
+
other_errors << e
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
notify_aggregated_failures
|
32
|
+
end
|
33
|
+
|
34
|
+
def failures
|
35
|
+
@failures ||= []
|
36
|
+
end
|
37
|
+
|
38
|
+
def other_errors
|
39
|
+
@other_errors ||= []
|
40
|
+
end
|
41
|
+
|
42
|
+
# This method is defined to satisfy the callable interface
|
43
|
+
# expected by `RSpec::Support.with_failure_notifier`.
|
44
|
+
def call(failure, options)
|
45
|
+
source_id = options[:source_id]
|
46
|
+
return if source_id && @seen_source_ids.key?(source_id)
|
47
|
+
|
48
|
+
@seen_source_ids[source_id] = true
|
49
|
+
assign_backtrace(failure) unless failure.backtrace
|
50
|
+
failures << failure
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
if RSpec::Support::Ruby.jruby?
|
56
|
+
# On JRuby, `caller` and `raise` produce different backtraces with regards to `.java`
|
57
|
+
# stack frames. It's important that we use `raise` for JRuby to produce a backtrace
|
58
|
+
# that has a continuous common section with the raised `MultipleExpectationsNotMetError`,
|
59
|
+
# so that rspec-core's truncation logic can work properly on it to list the backtrace
|
60
|
+
# relative to the `aggregate_failures` block.
|
61
|
+
def assign_backtrace(failure)
|
62
|
+
raise failure
|
63
|
+
rescue failure.class => e
|
64
|
+
failure.set_backtrace(e.backtrace)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
# Using `caller` performs better (and is simpler) than `raise` on most Rubies.
|
68
|
+
def assign_backtrace(failure)
|
69
|
+
failure.set_backtrace(caller)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def initialize(block_label, metadata)
|
74
|
+
@block_label = block_label
|
75
|
+
@metadata = metadata
|
76
|
+
@seen_source_ids = {} # don't want to load stdlib set
|
77
|
+
end
|
78
|
+
|
79
|
+
def notify_aggregated_failures
|
80
|
+
all_errors = failures + other_errors
|
81
|
+
|
82
|
+
case all_errors.size
|
83
|
+
when 0 then return nil
|
84
|
+
when 1 then RSpec::Support.notify_failure all_errors.first
|
85
|
+
else RSpec::Support.notify_failure MultipleExpectationsNotMetError.new(self)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Exception raised from `aggregate_failures` when multiple expectations fail.
|
91
|
+
class MultipleExpectationsNotMetError
|
92
|
+
# @return [String] The fully formatted exception message.
|
93
|
+
def message
|
94
|
+
@message ||= (["#{summary}:"] + enumerated_failures + enumerated_errors).join("\n\n")
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [Array<RSpec::Expectations::ExpectationNotMetError>] The list of expectation failures.
|
98
|
+
def failures
|
99
|
+
@failure_aggregator.failures
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [Array<Exception>] The list of other exceptions.
|
103
|
+
def other_errors
|
104
|
+
@failure_aggregator.other_errors
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [Array<Exception>] The list of expectation failures and other exceptions, combined.
|
108
|
+
attr_reader :all_exceptions
|
109
|
+
|
110
|
+
# @return [String] The user-assigned label for the aggregation block.
|
111
|
+
def aggregation_block_label
|
112
|
+
@failure_aggregator.block_label
|
113
|
+
end
|
114
|
+
|
115
|
+
# @return [Hash] The metadata hash passed to `aggregate_failures`.
|
116
|
+
def aggregation_metadata
|
117
|
+
@failure_aggregator.metadata
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [String] A summary of the failure, including the block label and a count of failures.
|
121
|
+
def summary
|
122
|
+
"Got #{exception_count_description} from failure aggregation " \
|
123
|
+
"block#{block_description}"
|
124
|
+
end
|
125
|
+
|
126
|
+
# return [String] A description of the failure/error counts.
|
127
|
+
def exception_count_description
|
128
|
+
failure_count = pluralize("failure", failures.size)
|
129
|
+
return failure_count if other_errors.empty?
|
130
|
+
error_count = pluralize("other error", other_errors.size)
|
131
|
+
"#{failure_count} and #{error_count}"
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def initialize(failure_aggregator)
|
137
|
+
@failure_aggregator = failure_aggregator
|
138
|
+
@all_exceptions = failures + other_errors
|
139
|
+
end
|
140
|
+
|
141
|
+
def block_description
|
142
|
+
return "" unless aggregation_block_label
|
143
|
+
" #{aggregation_block_label.inspect}"
|
144
|
+
end
|
145
|
+
|
146
|
+
def pluralize(noun, count)
|
147
|
+
"#{count} #{noun}#{'s' unless count == 1}"
|
148
|
+
end
|
149
|
+
|
150
|
+
def enumerated(exceptions, index_offset)
|
151
|
+
exceptions.each_with_index.map do |exception, index|
|
152
|
+
index += index_offset
|
153
|
+
formatted_message = yield exception
|
154
|
+
"#{index_label index}#{indented formatted_message, index}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def enumerated_failures
|
159
|
+
enumerated(failures, 0, &:message)
|
160
|
+
end
|
161
|
+
|
162
|
+
def enumerated_errors
|
163
|
+
enumerated(other_errors, failures.size) do |error|
|
164
|
+
"#{error.class}: #{error.message}"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def indented(failure_message, index)
|
169
|
+
line_1, *rest = failure_message.strip.lines.to_a
|
170
|
+
first_line_indentation = ' ' * (longest_index_label_width - width_of_label(index))
|
171
|
+
|
172
|
+
first_line_indentation + line_1 + rest.map do |line|
|
173
|
+
line =~ /\S/ ? indentation + line : line
|
174
|
+
end.join
|
175
|
+
end
|
176
|
+
|
177
|
+
def indentation
|
178
|
+
@indentation ||= ' ' * longest_index_label_width
|
179
|
+
end
|
180
|
+
|
181
|
+
def longest_index_label_width
|
182
|
+
@longest_index_label_width ||= width_of_label(failures.size)
|
183
|
+
end
|
184
|
+
|
185
|
+
def width_of_label(index)
|
186
|
+
index_label(index).chars.count
|
187
|
+
end
|
188
|
+
|
189
|
+
def index_label(index)
|
190
|
+
" #{index + 1}) "
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -7,6 +7,19 @@ Minitest::Test.class_eval do
|
|
7
7
|
assert(true) # so each expectation gets counted in minitest's assertion stats
|
8
8
|
super
|
9
9
|
end
|
10
|
+
|
11
|
+
# Convert a `MultipleExpectationsNotMetError` to a `Minitest::Assertion` error so
|
12
|
+
# it gets counted in minitest's summary stats as a failure rather than an error.
|
13
|
+
# It would be nice to make `MultipleExpectationsNotMetError` subclass
|
14
|
+
# `Minitest::Assertion`, but Minitest's implementation does not treat subclasses
|
15
|
+
# the same, so this is the best we can do.
|
16
|
+
def aggregate_failures(*args, &block)
|
17
|
+
super
|
18
|
+
rescue RSpec::Expectations::MultipleExpectationsNotMetError => e
|
19
|
+
assertion_failed = Minitest::Assertion.new(e.message)
|
20
|
+
assertion_failed.set_backtrace e.backtrace
|
21
|
+
raise assertion_failed
|
22
|
+
end
|
10
23
|
end
|
11
24
|
|
12
25
|
module RSpec
|
data/lib/rspec/matchers.rb
CHANGED
@@ -3,7 +3,7 @@ RSpec::Support.require_rspec_support 'matcher_definition'
|
|
3
3
|
RSpec::Support.define_optimized_require_for_rspec(:matchers) { |f| require_relative(f) }
|
4
4
|
|
5
5
|
%w[
|
6
|
-
|
6
|
+
english_phrasing
|
7
7
|
composable
|
8
8
|
built_in
|
9
9
|
generated_descriptions
|
@@ -243,7 +243,7 @@ module RSpec
|
|
243
243
|
# alias $1 $2
|
244
244
|
def self.alias_matcher(new_name, old_name, options={}, &description_override)
|
245
245
|
description_override ||= lambda do |old_desc|
|
246
|
-
old_desc.gsub(
|
246
|
+
old_desc.gsub(EnglishPhrasing.split_words(old_name), EnglishPhrasing.split_words(new_name))
|
247
247
|
end
|
248
248
|
klass = options.fetch(:klass) { AliasedMatcher }
|
249
249
|
|
@@ -277,6 +277,42 @@ module RSpec
|
|
277
277
|
alias_matcher(negated_name, base_name, :klass => AliasedNegatedMatcher, &description_override)
|
278
278
|
end
|
279
279
|
|
280
|
+
# Allows multiple expectations in the provided block to fail, and then
|
281
|
+
# aggregates them into a single exception, rather than aborting on the
|
282
|
+
# first expectation failure like normal. This allows you to see all
|
283
|
+
# failures from an entire set of expectations without splitting each
|
284
|
+
# off into its own example (which may slow things down if the example
|
285
|
+
# setup is expensive).
|
286
|
+
#
|
287
|
+
# @param label [String] label for this aggregation block, which will be
|
288
|
+
# included in the aggregated exception message.
|
289
|
+
# @param metadata [Hash] additional metadata about this failure aggregation
|
290
|
+
# block. If multiple expectations fail, it will be exposed from the
|
291
|
+
# {Expectations::MultipleExpectationsNotMetError} exception. Mostly
|
292
|
+
# intended for internal RSpec use but you can use it as well.
|
293
|
+
# @yield Block containing as many expectation as you want. The block is
|
294
|
+
# simply yielded to, so you can trust that anything that works outside
|
295
|
+
# the block should work within it.
|
296
|
+
# @raise [Expectations::MultipleExpectationsNotMetError] raised when
|
297
|
+
# multiple expectations fail.
|
298
|
+
# @raise [Expectations::ExpectationNotMetError] raised when a single
|
299
|
+
# expectation fails.
|
300
|
+
# @raise [Exception] other sorts of exceptions will be raised as normal.
|
301
|
+
#
|
302
|
+
# @example
|
303
|
+
# aggregate_failures("verifying response") do
|
304
|
+
# expect(response.status).to eq(200)
|
305
|
+
# expect(response.headers).to include("Content-Type" => "text/plain")
|
306
|
+
# expect(response.body).to include("Success")
|
307
|
+
# end
|
308
|
+
#
|
309
|
+
# @note The implementation of this feature uses a thread-local variable,
|
310
|
+
# which means that if you have an expectation failure in another thread,
|
311
|
+
# it'll abort like normal.
|
312
|
+
def aggregate_failures(label=nil, metadata={}, &block)
|
313
|
+
Expectations::FailureAggregator.new(label, metadata).aggregate(&block)
|
314
|
+
end
|
315
|
+
|
280
316
|
# Passes if actual is truthy (anything but false or nil)
|
281
317
|
def be_truthy
|
282
318
|
BuiltIn::BeTruthy.new
|
@@ -732,7 +768,7 @@ module RSpec
|
|
732
768
|
# expect { do_something_risky }.to raise_error(PoorRiskDecisionError, /oo ri/)
|
733
769
|
#
|
734
770
|
# expect { do_something_risky }.not_to raise_error
|
735
|
-
def raise_error(error=
|
771
|
+
def raise_error(error=nil, message=nil, &block)
|
736
772
|
BuiltIn::RaiseError.new(error, message, &block)
|
737
773
|
end
|
738
774
|
alias_method :raise_exception, :raise_error
|
@@ -767,10 +803,13 @@ module RSpec
|
|
767
803
|
# If you do find yourself in such a situation, you could always write
|
768
804
|
# a custom matcher, which would likely make your specs more expressive.
|
769
805
|
#
|
806
|
+
# @param description [String] optional description to be used for this matcher.
|
807
|
+
#
|
770
808
|
# @example
|
771
809
|
# expect(5).to satisfy { |n| n > 3 }
|
772
|
-
|
773
|
-
|
810
|
+
# expect(5).to satisfy("be greater than 3") { |n| n > 3 }
|
811
|
+
def satisfy(description="satisfy block", &block)
|
812
|
+
BuiltIn::Satisfy.new(description, &block)
|
774
813
|
end
|
775
814
|
alias_matcher :an_object_satisfying, :satisfy
|
776
815
|
alias_matcher :satisfying, :satisfy
|
@@ -915,6 +954,7 @@ module RSpec
|
|
915
954
|
|
916
955
|
BE_PREDICATE_REGEX = /^(be_(?:an?_)?)(.*)/
|
917
956
|
HAS_REGEX = /^(?:have_)(.*)/
|
957
|
+
DYNAMIC_MATCHER_REGEX = Regexp.union(BE_PREDICATE_REGEX, HAS_REGEX)
|
918
958
|
|
919
959
|
def method_missing(method, *args, &block)
|
920
960
|
case method.to_s
|
@@ -927,6 +967,20 @@ module RSpec
|
|
927
967
|
end
|
928
968
|
end
|
929
969
|
|
970
|
+
if RUBY_VERSION.to_f >= 1.9
|
971
|
+
def respond_to_missing?(method, *)
|
972
|
+
method =~ DYNAMIC_MATCHER_REGEX || super
|
973
|
+
end
|
974
|
+
else # for 1.8.7
|
975
|
+
# :nocov:
|
976
|
+
def respond_to?(method, *)
|
977
|
+
method = method.to_s
|
978
|
+
method =~ DYNAMIC_MATCHER_REGEX || super
|
979
|
+
end
|
980
|
+
public :respond_to?
|
981
|
+
# :nocov:
|
982
|
+
end
|
983
|
+
|
930
984
|
# @api private
|
931
985
|
def self.is_a_matcher?(obj)
|
932
986
|
return true if ::RSpec::Matchers::BuiltIn::BaseMatcher === obj
|