rspec-expectations 3.8.6 → 3.12.2

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Changelog.md +147 -1
  4. data/README.md +35 -20
  5. data/lib/rspec/expectations/configuration.rb +15 -0
  6. data/lib/rspec/expectations/expectation_target.rb +42 -6
  7. data/lib/rspec/expectations/failure_aggregator.rb +41 -6
  8. data/lib/rspec/expectations/handler.rb +20 -8
  9. data/lib/rspec/expectations/version.rb +1 -1
  10. data/lib/rspec/matchers/aliased_matcher.rb +3 -3
  11. data/lib/rspec/matchers/built_in/base_matcher.rb +5 -0
  12. data/lib/rspec/matchers/built_in/be.rb +10 -107
  13. data/lib/rspec/matchers/built_in/be_within.rb +2 -2
  14. data/lib/rspec/matchers/built_in/change.rb +22 -0
  15. data/lib/rspec/matchers/built_in/compound.rb +20 -1
  16. data/lib/rspec/matchers/built_in/contain_exactly.rb +10 -2
  17. data/lib/rspec/matchers/built_in/count_expectation.rb +169 -0
  18. data/lib/rspec/matchers/built_in/exist.rb +1 -1
  19. data/lib/rspec/matchers/built_in/has.rb +88 -24
  20. data/lib/rspec/matchers/built_in/have_attributes.rb +1 -1
  21. data/lib/rspec/matchers/built_in/include.rb +72 -15
  22. data/lib/rspec/matchers/built_in/output.rb +7 -0
  23. data/lib/rspec/matchers/built_in/raise_error.rb +63 -22
  24. data/lib/rspec/matchers/built_in/respond_to.rb +53 -18
  25. data/lib/rspec/matchers/built_in/throw_symbol.rb +10 -4
  26. data/lib/rspec/matchers/built_in/yield.rb +26 -83
  27. data/lib/rspec/matchers/built_in.rb +2 -1
  28. data/lib/rspec/matchers/composable.rb +1 -1
  29. data/lib/rspec/matchers/dsl.rb +29 -11
  30. data/lib/rspec/matchers/english_phrasing.rb +1 -1
  31. data/lib/rspec/matchers/expecteds_for_multiple_diffs.rb +16 -7
  32. data/lib/rspec/matchers/matcher_protocol.rb +6 -0
  33. data/lib/rspec/matchers.rb +75 -65
  34. data.tar.gz.sig +0 -0
  35. metadata +27 -12
  36. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1f0c43e7a6933605f4b96eb0a5545bd5e1b03a2b2de4471edada5000f3c5c37
4
- data.tar.gz: 62b85e7625d066114174dfaa586dbb2cb419aa0bc470b68918c2524b841f8762
3
+ metadata.gz: f0b59eb5a0bf0dcaf99ae45b411fa1d8e73a3cf5b0694f06170205ff36b22bc1
4
+ data.tar.gz: 91f0f17601c3853d8e10219dfb2c41a53fba78b4d3c546870ebe1fac9de70a6b
5
5
  SHA512:
6
- metadata.gz: 5ba237ec4317b7af0780f5e929e10da26b501f76a23cb807684498a21118ef0f72598c1ded7ee0436a8a29f97ea16a0d4f887c7b345b22302f5b8ef50c660beb
7
- data.tar.gz: 4138b8b208b668216660d55f5634440e8240c4a36f15489fc3e1e6093d4a8530fc419d9f958ea4526ac63e7e9e2d589c7716a21832d257adac823486d5dfae77
6
+ metadata.gz: 99e2aff242508b307566d95120c66e507cde5da5e6aec973365b747e1b16fde3ab34445ce2cfddf153baeac2c3f75c05b1e0f105465118544aad8fb9dafbe37e
7
+ data.tar.gz: c69b2d96fc2c3abec310e9e36b346cc3a1017a160906c795b1218b1e1a2dbea10055a80fc89da6510c89eb9cc7ef82e7f24c63ff2893f3c692a008de0ec838f1
checksums.yaml.gz.sig CHANGED
Binary file
data/Changelog.md CHANGED
@@ -1,3 +1,149 @@
1
+ ### Development
2
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.1...3-12-maintenance)
3
+
4
+ ### 3.12.2 / 2023-01-07
5
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.1...v3.12.2)
6
+
7
+ Bug Fixes:
8
+
9
+ * Prevent deprecation warning when using the `exist` matcher with `Dir`.
10
+ (Steve Dierker, #1398)
11
+
12
+ ### 3.12.1 / 2022-12-16
13
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.0...v3.12.1)
14
+
15
+ Bug Fixes:
16
+
17
+ * Pass keyword arguments through to aliased (and thus negated) matchers. (Jon Rowe, #1394)
18
+ * When handling failures in an aggregated_failures block (or example) prevent
19
+ the failure list leaking out. (Maciek Rząsa, #1392)
20
+
21
+ ### 3.12.0 / 2022-10-26
22
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.11.1...v3.12.0)
23
+
24
+ Enhancements:
25
+
26
+ * Add `an_array_matching` alias for `match_array` to improve readability as an argument
27
+ matcher. (Mark Schneider, #1361)
28
+
29
+ ### 3.11.1 / 2022-09-12
30
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.11.0...v3.11.1)
31
+
32
+ Bug Fixes:
33
+
34
+ * Allow the `contain_exactly` matcher to be reused by resetting its
35
+ internals on `matches?` (@bclayman-sq, #1326)
36
+ * Using the exist matcher on `FileTest` no longer produces a deprecation warning.
37
+ (Ryo Nakamura, #1383)
38
+
39
+ ### 3.11.0 / 2022-02-09
40
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.2...v3.11.0)
41
+
42
+ Enhancements:
43
+
44
+ * Return `true` from `aggregate_failures` when no exception occurs. (Jon Rowe, #1225)
45
+
46
+ Deprecations:
47
+
48
+ * Print a deprecation message when using the implicit block expectation syntax.
49
+ (Phil Pirozhkov, #1139)
50
+
51
+ ### 3.10.2 / 2022-01-14
52
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.1...v3.10.2)
53
+
54
+ Bug Fixes:
55
+
56
+ * Fix support for dynamic matchers for expectation target checks (Phil Pirozhkov, #1294)
57
+ * Fix `expect(array).to include(hash).times`, previously this would fail due to
58
+ matching the entire array as a single hash, rather than a member of the hash.
59
+ (Slava Kardakov, #1322)
60
+ * Ensure `raise_error` matches works with the `error_highlight` option from Ruby 3.1.
61
+ (Peter Goldstein, #1339)
62
+
63
+ ### 3.10.1 / 2020-12-27
64
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.0...v3.10.1)
65
+
66
+ Bug Fixes:
67
+
68
+ * Allow JRuby 9.2.x.x to generate backtraces normally rather than via our
69
+ backfill workaround. (#1230, Jon Rowe)
70
+
71
+ ### 3.10.0 / 2020-10-30
72
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.3...v3.10.0)
73
+
74
+ Enhancements:
75
+
76
+ * Allow `include` matcher to be chained with `once`, `at_least`, etc. for simple cases.
77
+ (Marc-André Lafortune, #1168)
78
+ * Add an explicit warning when `nil` is passed to `raise_error`. (Phil Pirozhkov, #1143)
79
+ * Improve `include` matcher's composability. (Phil Pirozhkov, #1155)
80
+ * Mocks expectations can now set a custom failure message.
81
+ (Benoit Tigeot and Nicolas Zermati, #1156)
82
+ * `aggregate_failures` now shows the backtrace line for each failure. (Fabricio Bedin, #1163)
83
+ * Support multiple combinations of `yield_control` modifiers like `at_least`, `at_most`.
84
+ (Jon Rowe, #1169)
85
+ * Dynamic `have_<n>` matchers now have output consistent with other dynamic matchers.
86
+ (Marc-André Lafortune, #1195)
87
+ * New config option `strict_predicate_matchers` allows predicate matcher to be strict
88
+ (i.e. match for `true` or `false`) instead of the default (match truthy vs `false` or `nil`).
89
+ (Marc-André Lafortune, #1196)
90
+
91
+ ### 3.9.4 / 2020-10-29
92
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.3...v3.9.4)
93
+
94
+ Bug Fixes:
95
+
96
+ * Fix regression with `be_` and `have_` matchers and arguments implementing `to_hash`
97
+ were they would act like keywords and be cast to a hash. (Jon Rowe, #1222)
98
+
99
+ ### 3.9.3 / 2020-10-23
100
+
101
+ Bug Fixes:
102
+
103
+ * Swap the comparison of the delta vs the expected for the `be_within` matcher allowing
104
+ more complicated oobjects to be compared providing they provide `abs` and other
105
+ comparison methods. (Kelly Stannard, #1182)
106
+ * Properly format expected in the description of the `be_within` matcher. (Jon Rowe, #1185)
107
+ * Remove warning when using keyword arguments with `be_` and `have_` matchers on 2.7.x
108
+ (Jon Rowe, #1187)
109
+ * Prevent formatting a single hash as a list of key value pairs in default failure messages
110
+ for custom matches (fixes formatting in `EnglishPhrasing#list`). (Robert Eshleman, #1193)
111
+ * Prevent errors from causing false positives when using `be <operator>` comparison, e.g.
112
+ `expect(1).not_to be < 'a'` will now correctly fail rather than pass. (Jon Rowe, #1208)
113
+
114
+
115
+ ### 3.9.2 / 2020-05-08
116
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.1...v3.9.2)
117
+
118
+ Bug Fixes:
119
+
120
+ * Issue a proper `ArgumentError` when invalid arguments are given to `yield_control`
121
+ modifiers such as `at_least` et al. (Marc-André Lafortune, #1167)
122
+ * Prevent Ruby 2.7 keyword arguments warning from being issued by custom
123
+ matcher definitions. (Jon Rowe, #1176)
124
+
125
+ ### 3.9.1 / 2020-03-13
126
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.0...v3.9.1)
127
+
128
+ Bug Fixes:
129
+
130
+ * Issue an improved warning when using `respond_to(...).with(n).arguments` and ignore
131
+ the warning when using with `have_attributes(...)`. (Jon Rowe, #1164)
132
+
133
+ ### 3.9.0 / 2019-10-08
134
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.8.6...v3.9.0)
135
+
136
+ Enhancements:
137
+
138
+ * The `respond_to` matcher now uses the signature from `initialize` to validate checks
139
+ for `new` (unless `new` is non standard). (Jon Rowe, #1072)
140
+ * Generated descriptions for matchers now use `is expected to` rather than `should` in
141
+ line with our preferred DSL. (Pete Johns, #1080, rspec/rspec-core#2572)
142
+ * Add the ability to re-raise expectation errors when matching
143
+ with `match_when_negated` blocks. (Jon Rowe, #1130)
144
+ * Add a warning when an empty diff is produce due to identical inspect output.
145
+ (Benoit Tigeot, #1126)
146
+
1
147
  ### 3.8.6 / 2019-10-07
2
148
 
3
149
  Bug Fixes:
@@ -29,7 +175,7 @@ Bug Fixes:
29
175
  * Prevent composed `all` matchers from leaking into their siblings leading to duplicate
30
176
  failures. (Jamie English, #1086)
31
177
  * Prevent objects which change their hash on comparison from failing change checks.
32
- (Phil Pirozhkov, #1110)
178
+ (Phil Pirozhkov, #1100)
33
179
  * Issue an `ArgumentError` rather than a `NoMethodError` when `be_an_instance_of` and
34
180
  `be_kind_of` matchers encounter objects not supporting those methods.
35
181
  (Taichi Ishitani, #1107)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RSpec Expectations [![Build Status](https://secure.travis-ci.org/rspec/rspec-expectations.svg?branch=master)](http://travis-ci.org/rspec/rspec-expectations) [![Code Climate](https://codeclimate.com/github/rspec/rspec-expectations.svg)](https://codeclimate.com/github/rspec/rspec-expectations)
1
+ # RSpec Expectations [![Build Status](https://github.com/rspec/rspec-expectations/workflows/RSpec%20CI/badge.svg)](https://github.com/rspec/rspec-expectations/actions) [![Code Climate](https://codeclimate.com/github/rspec/rspec-expectations.svg)](https://codeclimate.com/github/rspec/rspec-expectations)
2
2
 
3
3
  RSpec::Expectations lets you express expected outcomes on an object in an
4
4
  example.
@@ -15,12 +15,12 @@ rspec-core and rspec-mocks):
15
15
 
16
16
  gem install rspec
17
17
 
18
- Want to run against the `master` branch? You'll need to include the dependent
18
+ Want to run against the `main` branch? You'll need to include the dependent
19
19
  RSpec repos as well. Add the following to your `Gemfile`:
20
20
 
21
21
  ```ruby
22
22
  %w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib|
23
- gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'master'
23
+ gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'main'
24
24
  end
25
25
  ```
26
26
 
@@ -175,30 +175,45 @@ expect(1..10).to cover(3)
175
175
  ### Collection membership
176
176
 
177
177
  ```ruby
178
- expect(actual).to include(expected)
178
+ # exact order, entire collection
179
+ expect(actual).to eq(expected)
180
+
181
+ # exact order, partial collection (based on an exact position)
179
182
  expect(actual).to start_with(expected)
180
183
  expect(actual).to end_with(expected)
181
184
 
182
- expect(actual).to contain_exactly(individual, items)
183
- # ...which is the same as:
184
- expect(actual).to match_array(expected_array)
185
+ # any order, entire collection
186
+ expect(actual).to match_array(expected)
187
+
188
+ # You can also express this by passing the expected elements
189
+ # as individual arguments
190
+ expect(actual).to contain_exactly(expected_element1, expected_element2)
191
+
192
+ # any order, partial collection
193
+ expect(actual).to include(expected)
185
194
  ```
186
195
 
187
196
  #### Examples
188
197
 
189
198
  ```ruby
190
- expect([1, 2, 3]).to include(1)
191
- expect([1, 2, 3]).to include(1, 2)
192
- expect([1, 2, 3]).to start_with(1)
193
- expect([1, 2, 3]).to start_with(1, 2)
194
- expect([1, 2, 3]).to end_with(3)
195
- expect([1, 2, 3]).to end_with(2, 3)
196
- expect({:a => 'b'}).to include(:a => 'b')
197
- expect("this string").to include("is str")
198
- expect("this string").to start_with("this")
199
- expect("this string").to end_with("ring")
200
- expect([1, 2, 3]).to contain_exactly(2, 3, 1)
201
- expect([1, 2, 3]).to match_array([3, 2, 1])
199
+ expect([1, 2, 3]).to eq([1, 2, 3]) # Order dependent equality check
200
+ expect([1, 2, 3]).to include(1) # Exact ordering, partial collection matches
201
+ expect([1, 2, 3]).to include(2, 3) #
202
+ expect([1, 2, 3]).to start_with(1) # As above, but from the start of the collection
203
+ expect([1, 2, 3]).to start_with(1, 2) #
204
+ expect([1, 2, 3]).to end_with(3) # As above but from the end of the collection
205
+ expect([1, 2, 3]).to end_with(2, 3) #
206
+ expect({:a => 'b'}).to include(:a => 'b') # Matching within hashes
207
+ expect("this string").to include("is str") # Matching within strings
208
+ expect("this string").to start_with("this") #
209
+ expect("this string").to end_with("ring") #
210
+ expect([1, 2, 3]).to contain_exactly(2, 3, 1) # Order independent matches
211
+ expect([1, 2, 3]).to match_array([3, 2, 1]) #
212
+
213
+ # Order dependent compound matchers
214
+ expect(
215
+ [{:a => 'hash'},{:a => 'another'}]
216
+ ).to match([a_hash_including(:a => 'hash'), a_hash_including(:a => 'another')])
202
217
  ```
203
218
 
204
219
  ## `should` syntax
@@ -212,7 +227,7 @@ actual.should be > 3
212
227
  [1, 2, 3].should_not include 4
213
228
  ```
214
229
 
215
- See [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/master/Should.md)
230
+ See [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/main/Should.md)
216
231
 
217
232
  ## Compound Matcher Expressions
218
233
 
@@ -28,6 +28,7 @@ module RSpec
28
28
 
29
29
  def initialize
30
30
  @on_potential_false_positives = :warn
31
+ @strict_predicate_matchers = false
31
32
  end
32
33
 
33
34
  # Configures the supported syntax.
@@ -185,6 +186,20 @@ module RSpec
185
186
  @on_potential_false_positives = behavior
186
187
  end
187
188
 
189
+ # Configures RSpec to check predicate matchers to `be(true)` / `be(false)` (strict),
190
+ # or `be_truthy` / `be_falsey` (not strict).
191
+ # Historically, the default was `false`, but `true` is recommended.
192
+ def strict_predicate_matchers=(flag)
193
+ raise ArgumentError, "Pass `true` or `false`" unless flag == true || flag == false
194
+ @strict_predicate_matchers = flag
195
+ end
196
+
197
+ attr_reader :strict_predicate_matchers
198
+
199
+ def strict_predicate_matchers?
200
+ @strict_predicate_matchers
201
+ end
202
+
188
203
  # Indicates what RSpec will do about matcher use which will
189
204
  # potentially cause false positives in tests, generally you want to
190
205
  # avoid such scenarios so this defaults to `true`.
@@ -42,7 +42,7 @@ module RSpec
42
42
  elsif block
43
43
  raise ArgumentError, "You cannot pass both an argument and a block to `expect`."
44
44
  else
45
- new(value)
45
+ ValueExpectationTarget.new(value)
46
46
  end
47
47
  end
48
48
 
@@ -57,7 +57,7 @@ module RSpec
57
57
  # expect { perform }.to raise_error
58
58
  # @param [Matcher]
59
59
  # matcher
60
- # @param [String or Proc] message optional message to display when the expectation fails
60
+ # @param [String, Proc] message optional message to display when the expectation fails
61
61
  # @return [Boolean] true if the expectation succeeds (else raises)
62
62
  # @see RSpec::Matchers
63
63
  def to(matcher=nil, message=nil, &block)
@@ -70,7 +70,7 @@ module RSpec
70
70
  # expect(value).not_to eq(5)
71
71
  # @param [Matcher]
72
72
  # matcher
73
- # @param [String or Proc] message optional message to display when the expectation fails
73
+ # @param [String, Proc] message optional message to display when the expectation fails
74
74
  # @return [Boolean] false if the negative expectation succeeds (else raises)
75
75
  # @see RSpec::Matchers
76
76
  def not_to(matcher=nil, message=nil, &block)
@@ -90,6 +90,44 @@ module RSpec
90
90
  include InstanceMethods
91
91
  end
92
92
 
93
+ # @private
94
+ # Validates the provided matcher to ensure it supports block
95
+ # expectations, in order to avoid user confusion when they
96
+ # use a block thinking the expectation will be on the return
97
+ # value of the block rather than the block itself.
98
+ class ValueExpectationTarget < ExpectationTarget
99
+ def to(matcher=nil, message=nil, &block)
100
+ enforce_value_expectation(matcher)
101
+ super
102
+ end
103
+
104
+ def not_to(matcher=nil, message=nil, &block)
105
+ enforce_value_expectation(matcher)
106
+ super
107
+ end
108
+
109
+ private
110
+
111
+ def enforce_value_expectation(matcher)
112
+ return if supports_value_expectations?(matcher)
113
+
114
+ RSpec.deprecate(
115
+ "expect(value).to #{RSpec::Support::ObjectFormatter.format(matcher)}",
116
+ :message =>
117
+ "The implicit block expectation syntax is deprecated, you should pass " \
118
+ "a block rather than an argument to `expect` to use the provided " \
119
+ "block expectation matcher or the matcher must implement " \
120
+ "`supports_value_expectations?`. e.g `expect { value }.to " \
121
+ "#{RSpec::Support::ObjectFormatter.format(matcher)}` not " \
122
+ "`expect(value).to #{RSpec::Support::ObjectFormatter.format(matcher)}`"
123
+ )
124
+ end
125
+
126
+ def supports_value_expectations?(matcher)
127
+ !matcher.respond_to?(:supports_value_expectations?) || matcher.supports_value_expectations?
128
+ end
129
+ end
130
+
93
131
  # @private
94
132
  # Validates the provided matcher to ensure it supports block
95
133
  # expectations, in order to avoid user confusion when they
@@ -118,9 +156,7 @@ module RSpec
118
156
  end
119
157
 
120
158
  def supports_block_expectations?(matcher)
121
- matcher.supports_block_expectations?
122
- rescue NoMethodError
123
- false
159
+ matcher.respond_to?(:supports_block_expectations?) && matcher.supports_block_expectations?
124
160
  end
125
161
  end
126
162
  end
@@ -4,6 +4,21 @@ module RSpec
4
4
  class FailureAggregator
5
5
  attr_reader :block_label, :metadata
6
6
 
7
+ # @private
8
+ class AggregatedFailure
9
+ # @private
10
+ MESSAGE =
11
+ 'AggregatedFailure: This method caused a failure which has been ' \
12
+ 'suppressed to be aggregated into our failure report by returning ' \
13
+ 'this value, further errors can be ignored.'
14
+
15
+ def inspect
16
+ MESSAGE
17
+ end
18
+ end
19
+
20
+ AGGREGATED_FAILURE = AggregatedFailure.new
21
+
7
22
  def aggregate
8
23
  RSpec::Support.with_failure_notifier(self) do
9
24
  begin
@@ -48,14 +63,16 @@ module RSpec
48
63
  @seen_source_ids[source_id] = true
49
64
  assign_backtrace(failure) unless failure.backtrace
50
65
  failures << failure
66
+
67
+ AGGREGATED_FAILURE
51
68
  end
52
69
 
53
70
  private
54
71
 
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`,
72
+ if RSpec::Support::Ruby.jruby? && RSpec::Support::Ruby.jruby_version < '9.2.0.0'
73
+ # On JRuby 9.1.x.x and before, `caller` and `raise` produce different backtraces with
74
+ # regards to `.java` stack frames. It's important that we use `raise` for JRuby to produce
75
+ # a backtrace that has a continuous common section with the raised `MultipleExpectationsNotMetError`,
59
76
  # so that rspec-core's truncation logic can work properly on it to list the backtrace
60
77
  # relative to the `aggregate_failures` block.
61
78
  def assign_backtrace(failure)
@@ -80,7 +97,7 @@ module RSpec
80
97
  all_errors = failures + other_errors
81
98
 
82
99
  case all_errors.size
83
- when 0 then return nil
100
+ when 0 then return true
84
101
  when 1 then RSpec::Support.notify_failure all_errors.first
85
102
  else RSpec::Support.notify_failure MultipleExpectationsNotMetError.new(self)
86
103
  end
@@ -150,11 +167,29 @@ module RSpec
150
167
  def enumerated(exceptions, index_offset)
151
168
  exceptions.each_with_index.map do |exception, index|
152
169
  index += index_offset
153
- formatted_message = yield exception
170
+ formatted_message = "#{yield exception}\n#{format_backtrace(exception.backtrace).first}"
154
171
  "#{index_label index}#{indented formatted_message, index}"
155
172
  end
156
173
  end
157
174
 
175
+ def exclusion_patterns
176
+ patterns = %w[/lib\d*/ruby/ bin/ exe/rspec /lib/bundler/ /exe/bundle:]
177
+ patterns << "org/jruby/" if RSpec::Support::Ruby.jruby?
178
+ patterns.map! { |s| Regexp.new(s.gsub('/', File::SEPARATOR)) }
179
+ end
180
+
181
+ def format_backtrace(backtrace)
182
+ backtrace.map { |l| backtrace_line(l) }.compact.tap { |filtered| filtered.concat backtrace if filtered.empty? }
183
+ end
184
+
185
+ def backtrace_line(line)
186
+ return if [Regexp.union(RSpec::CallerFilter::IGNORE_REGEX, *exclusion_patterns)].any? { |p| line =~ p }
187
+
188
+ # It changes the current path that is relative to
189
+ # system root to be relative to the project root.
190
+ line.sub(/(\A|\s)#{File.expand_path('.')}(#{File::SEPARATOR}|\s|\Z)/, '\\1.\\2'.freeze).sub(/\A([^:]+:\d+)$/, '\\1'.freeze)
191
+ end
192
+
158
193
  def enumerated_failures
159
194
  enumerated(failures, 0, &:message)
160
195
  end
@@ -44,15 +44,21 @@ module RSpec
44
44
 
45
45
  # @private
46
46
  class PositiveExpectationHandler
47
- def self.handle_matcher(actual, initial_matcher, message=nil, &block)
48
- ExpectationHelper.with_matcher(self, initial_matcher, message) do |matcher|
47
+ def self.handle_matcher(actual, initial_matcher, custom_message=nil, &block)
48
+ ExpectationHelper.with_matcher(self, initial_matcher, custom_message) do |matcher|
49
49
  return ::RSpec::Matchers::BuiltIn::PositiveOperatorMatcher.new(actual) unless initial_matcher
50
- matcher.matches?(actual, &block) || ExpectationHelper.handle_failure(matcher, message, :failure_message)
50
+
51
+ match_result = matcher.matches?(actual, &block)
52
+ if custom_message && match_result.respond_to?(:error_generator)
53
+ match_result.error_generator.opts[:message] = custom_message
54
+ end
55
+
56
+ match_result || ExpectationHelper.handle_failure(matcher, custom_message, :failure_message)
51
57
  end
52
58
  end
53
59
 
54
60
  def self.verb
55
- "should"
61
+ 'is expected to'
56
62
  end
57
63
 
58
64
  def self.should_method
@@ -66,10 +72,16 @@ module RSpec
66
72
 
67
73
  # @private
68
74
  class NegativeExpectationHandler
69
- def self.handle_matcher(actual, initial_matcher, message=nil, &block)
70
- ExpectationHelper.with_matcher(self, initial_matcher, message) do |matcher|
75
+ def self.handle_matcher(actual, initial_matcher, custom_message=nil, &block)
76
+ ExpectationHelper.with_matcher(self, initial_matcher, custom_message) do |matcher|
71
77
  return ::RSpec::Matchers::BuiltIn::NegativeOperatorMatcher.new(actual) unless initial_matcher
72
- does_not_match?(matcher, actual, &block) || ExpectationHelper.handle_failure(matcher, message, :failure_message_when_negated)
78
+
79
+ negated_match_result = does_not_match?(matcher, actual, &block)
80
+ if custom_message && negated_match_result.respond_to?(:error_generator)
81
+ negated_match_result.error_generator.opts[:message] = custom_message
82
+ end
83
+
84
+ negated_match_result || ExpectationHelper.handle_failure(matcher, custom_message, :failure_message_when_negated)
73
85
  end
74
86
  end
75
87
 
@@ -82,7 +94,7 @@ module RSpec
82
94
  end
83
95
 
84
96
  def self.verb
85
- "should not"
97
+ 'is expected not to'
86
98
  end
87
99
 
88
100
  def self.should_method
@@ -2,7 +2,7 @@ module RSpec
2
2
  module Expectations
3
3
  # @private
4
4
  module Version
5
- STRING = '3.8.6'
5
+ STRING = '3.12.2'
6
6
  end
7
7
  end
8
8
  end
@@ -99,14 +99,14 @@ module RSpec
99
99
  # by going through the effort of defining a negated matcher.
100
100
  #
101
101
  # However, if the override didn't actually change anything, then we
102
- # should return the opposite failure message instead -- the overriden
102
+ # should return the opposite failure message instead -- the overridden
103
103
  # message is going to be confusing if we return it as-is, as it represents
104
104
  # the non-negated failure message for a negated match (or vice versa).
105
105
  def optimal_failure_message(same, inverted)
106
106
  if DefaultFailureMessages.has_default_failure_messages?(@base_matcher)
107
107
  base_message = @base_matcher.__send__(same)
108
- overriden = @description_block.call(base_message)
109
- return overriden if overriden != base_message
108
+ overridden = @description_block.call(base_message)
109
+ return overridden if overridden != base_message
110
110
  end
111
111
 
112
112
  @base_matcher.__send__(inverted)
@@ -78,6 +78,11 @@ module RSpec
78
78
  false
79
79
  end
80
80
 
81
+ # @private
82
+ def supports_value_expectations?
83
+ true
84
+ end
85
+
81
86
  # @api private
82
87
  def expects_call_stack_jump?
83
88
  false