rspec-expectations 2.13.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. checksums.yaml +15 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/Changelog.md +413 -23
  4. data/License.txt +1 -0
  5. data/README.md +109 -80
  6. data/lib/rspec/{matchers → expectations}/configuration.rb +44 -14
  7. data/lib/rspec/expectations/expectation_target.rb +71 -38
  8. data/lib/rspec/expectations/fail_with.rb +12 -44
  9. data/lib/rspec/expectations/handler.rb +135 -35
  10. data/lib/rspec/expectations/minitest_integration.rb +16 -0
  11. data/lib/rspec/expectations/syntax.rb +60 -94
  12. data/lib/rspec/expectations/version.rb +1 -1
  13. data/lib/rspec/expectations.rb +46 -24
  14. data/lib/rspec/matchers/aliased_matcher.rb +41 -0
  15. data/lib/rspec/matchers/built_in/all.rb +78 -0
  16. data/lib/rspec/matchers/built_in/base_matcher.rb +63 -15
  17. data/lib/rspec/matchers/built_in/be.rb +170 -79
  18. data/lib/rspec/matchers/built_in/be_between.rb +77 -0
  19. data/lib/rspec/matchers/built_in/be_instance_of.rb +11 -3
  20. data/lib/rspec/matchers/built_in/be_kind_of.rb +5 -0
  21. data/lib/rspec/matchers/built_in/be_within.rb +40 -16
  22. data/lib/rspec/matchers/built_in/change.rb +275 -74
  23. data/lib/rspec/matchers/built_in/compound.rb +122 -0
  24. data/lib/rspec/matchers/built_in/contain_exactly.rb +256 -0
  25. data/lib/rspec/matchers/built_in/cover.rb +3 -0
  26. data/lib/rspec/matchers/built_in/eq.rb +60 -6
  27. data/lib/rspec/matchers/built_in/eql.rb +17 -5
  28. data/lib/rspec/matchers/built_in/equal.rb +55 -21
  29. data/lib/rspec/matchers/built_in/exist.rb +74 -10
  30. data/lib/rspec/matchers/built_in/has.rb +71 -15
  31. data/lib/rspec/matchers/built_in/include.rb +58 -29
  32. data/lib/rspec/matchers/built_in/match.rb +19 -1
  33. data/lib/rspec/matchers/built_in/operators.rb +119 -0
  34. data/lib/rspec/matchers/built_in/output.rb +150 -0
  35. data/lib/rspec/matchers/built_in/raise_error.rb +91 -33
  36. data/lib/rspec/matchers/built_in/respond_to.rb +42 -20
  37. data/lib/rspec/matchers/built_in/satisfy.rb +19 -3
  38. data/lib/rspec/matchers/built_in/start_and_end_with.rb +54 -18
  39. data/lib/rspec/matchers/built_in/throw_symbol.rb +38 -8
  40. data/lib/rspec/matchers/built_in/yield.rb +237 -55
  41. data/lib/rspec/matchers/built_in.rb +45 -33
  42. data/lib/rspec/matchers/composable.rb +179 -0
  43. data/lib/rspec/matchers/dsl.rb +362 -5
  44. data/lib/rspec/matchers/generated_descriptions.rb +13 -6
  45. data/lib/rspec/matchers/matcher_delegator.rb +37 -0
  46. data/lib/rspec/matchers/pretty.rb +33 -20
  47. data/lib/rspec/matchers.rb +450 -227
  48. data.tar.gz.sig +1 -0
  49. metadata +100 -215
  50. metadata.gz.sig +0 -0
  51. data/features/README.md +0 -49
  52. data/features/Upgrade.md +0 -53
  53. data/features/built_in_matchers/README.md +0 -90
  54. data/features/built_in_matchers/be.feature +0 -175
  55. data/features/built_in_matchers/be_within.feature +0 -48
  56. data/features/built_in_matchers/cover.feature +0 -47
  57. data/features/built_in_matchers/end_with.feature +0 -48
  58. data/features/built_in_matchers/equality.feature +0 -139
  59. data/features/built_in_matchers/exist.feature +0 -45
  60. data/features/built_in_matchers/expect_change.feature +0 -59
  61. data/features/built_in_matchers/expect_error.feature +0 -144
  62. data/features/built_in_matchers/have.feature +0 -109
  63. data/features/built_in_matchers/include.feature +0 -174
  64. data/features/built_in_matchers/match.feature +0 -52
  65. data/features/built_in_matchers/operators.feature +0 -227
  66. data/features/built_in_matchers/predicates.feature +0 -137
  67. data/features/built_in_matchers/respond_to.feature +0 -84
  68. data/features/built_in_matchers/satisfy.feature +0 -33
  69. data/features/built_in_matchers/start_with.feature +0 -48
  70. data/features/built_in_matchers/throw_symbol.feature +0 -91
  71. data/features/built_in_matchers/types.feature +0 -116
  72. data/features/built_in_matchers/yield.feature +0 -146
  73. data/features/custom_matchers/access_running_example.feature +0 -53
  74. data/features/custom_matchers/define_diffable_matcher.feature +0 -27
  75. data/features/custom_matchers/define_matcher.feature +0 -368
  76. data/features/custom_matchers/define_matcher_outside_rspec.feature +0 -38
  77. data/features/custom_matchers/define_matcher_with_fluent_interface.feature +0 -24
  78. data/features/customized_message.feature +0 -22
  79. data/features/diffing.feature +0 -85
  80. data/features/implicit_docstrings.feature +0 -52
  81. data/features/step_definitions/additional_cli_steps.rb +0 -22
  82. data/features/support/env.rb +0 -5
  83. data/features/syntax_configuration.feature +0 -68
  84. data/features/test_frameworks/test_unit.feature +0 -46
  85. data/lib/rspec/expectations/deprecation.rb +0 -38
  86. data/lib/rspec/expectations/differ.rb +0 -115
  87. data/lib/rspec/expectations/errors.rb +0 -9
  88. data/lib/rspec/expectations/extensions/array.rb +0 -9
  89. data/lib/rspec/expectations/extensions/object.rb +0 -39
  90. data/lib/rspec/expectations/extensions.rb +0 -2
  91. data/lib/rspec/matchers/be_close.rb +0 -9
  92. data/lib/rspec/matchers/built_in/have.rb +0 -108
  93. data/lib/rspec/matchers/built_in/match_array.rb +0 -51
  94. data/lib/rspec/matchers/compatibility.rb +0 -14
  95. data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
  96. data/lib/rspec/matchers/matcher.rb +0 -300
  97. data/lib/rspec/matchers/method_missing.rb +0 -12
  98. data/lib/rspec/matchers/operator_matcher.rb +0 -109
  99. data/lib/rspec-expectations.rb +0 -1
  100. data/spec/rspec/expectations/differ_spec.rb +0 -170
  101. data/spec/rspec/expectations/expectation_target_spec.rb +0 -75
  102. data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
  103. data/spec/rspec/expectations/fail_with_spec.rb +0 -95
  104. data/spec/rspec/expectations/handler_spec.rb +0 -206
  105. data/spec/rspec/expectations/syntax_spec.rb +0 -97
  106. data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
  107. data/spec/rspec/matchers/be_close_spec.rb +0 -22
  108. data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
  109. data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
  110. data/spec/rspec/matchers/be_spec.rb +0 -516
  111. data/spec/rspec/matchers/be_within_spec.rb +0 -129
  112. data/spec/rspec/matchers/change_spec.rb +0 -542
  113. data/spec/rspec/matchers/configuration_spec.rb +0 -238
  114. data/spec/rspec/matchers/cover_spec.rb +0 -69
  115. data/spec/rspec/matchers/description_generation_spec.rb +0 -176
  116. data/spec/rspec/matchers/dsl_spec.rb +0 -57
  117. data/spec/rspec/matchers/eq_spec.rb +0 -60
  118. data/spec/rspec/matchers/eql_spec.rb +0 -41
  119. data/spec/rspec/matchers/equal_spec.rb +0 -78
  120. data/spec/rspec/matchers/exist_spec.rb +0 -124
  121. data/spec/rspec/matchers/has_spec.rb +0 -122
  122. data/spec/rspec/matchers/have_spec.rb +0 -445
  123. data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
  124. data/spec/rspec/matchers/include_spec.rb +0 -531
  125. data/spec/rspec/matchers/match_array_spec.rb +0 -194
  126. data/spec/rspec/matchers/match_spec.rb +0 -61
  127. data/spec/rspec/matchers/matcher_spec.rb +0 -471
  128. data/spec/rspec/matchers/matchers_spec.rb +0 -37
  129. data/spec/rspec/matchers/method_missing_spec.rb +0 -28
  130. data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
  131. data/spec/rspec/matchers/raise_error_spec.rb +0 -395
  132. data/spec/rspec/matchers/respond_to_spec.rb +0 -292
  133. data/spec/rspec/matchers/satisfy_spec.rb +0 -44
  134. data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
  135. data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
  136. data/spec/rspec/matchers/yield_spec.rb +0 -437
  137. data/spec/spec_helper.rb +0 -54
  138. data/spec/support/classes.rb +0 -56
  139. data/spec/support/in_sub_process.rb +0 -38
  140. data/spec/support/matchers.rb +0 -22
  141. data/spec/support/ruby_version.rb +0 -10
  142. data/spec/support/shared_examples.rb +0 -13
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # RSpec Expectations [![Build Status](https://secure.travis-ci.org/rspec/rspec-expectations.png?branch=master)](http://travis-ci.org/rspec/rspec-expectations) [![Code Climate](https://codeclimate.com/github/rspec/rspec-expectations.png)](https://codeclimate.com/github/rspec/rspec-expectations)
1
+ # RSpec Expectations [![Build Status](https://secure.travis-ci.org/rspec/rspec-expectations.png?branch=master)](http://travis-ci.org/rspec/rspec-expectations) [![Code Climate](https://codeclimate.com/github/rspec/rspec-expectations.png)](https://codeclimate.com/github/rspec/rspec-expectations) [![Inline docs](http://inch-pages.github.io/github/rspec/rspec-expectations.png)](http://inch-pages.github.io/github/rspec/rspec-expectations)
2
2
 
3
3
  RSpec::Expectations lets you express expected outcomes on an object in an
4
4
  example.
5
5
 
6
- account.balance.should eq(Money.new(37.42, :USD))
6
+ expect(account.balance).to eq(Money.new(37.42, :USD))
7
7
 
8
8
  ## Install
9
9
 
@@ -23,7 +23,7 @@ Minitest, or Cucumber, you can install it directly:
23
23
  Here's an example using rspec-core:
24
24
 
25
25
  ```ruby
26
- describe Order do
26
+ RSpec.describe Order do
27
27
  it "sums the prices of the items in its line items" do
28
28
  order = Order.new
29
29
  order.add_entry(LineItem.new(:item => Item.new(
@@ -38,8 +38,7 @@ describe Order do
38
38
  end
39
39
  ```
40
40
 
41
- The `describe` and `it` methods come from rspec-core. The `Order`, `LineItem`,
42
- and `Item` classes would be from _your_ code. The last line of the example
41
+ The `describe` and `it` methods come from rspec-core. The `Order`, `LineItem`, `Item` and `Money` classes would be from _your_ code. The last line of the example
43
42
  expresses an expected outcome. If `order.total == Money.new(5.55, :USD)`, then
44
43
  the example passes. If not, it fails with a message like:
45
44
 
@@ -51,52 +50,54 @@ the example passes. If not, it fails with a message like:
51
50
  ### Equivalence
52
51
 
53
52
  ```ruby
54
- actual.should eq(expected) # passes if actual == expected
55
- actual.should == expected # passes if actual == expected
56
- actual.should eql(expected) # passes if actual.eql?(expected)
53
+ expect(actual).to eq(expected) # passes if actual == expected
54
+ expect(actual).to eql(expected) # passes if actual.eql?(expected)
57
55
  ```
58
56
 
59
- Note: we recommend the `eq` matcher over `==` to avoid Ruby's "== in a
60
- useless context" warning when the `==` matcher is used anywhere but the
61
- last statement of an example.
57
+ Note: The new `expect` syntax no longer supports the `==` matcher.
62
58
 
63
59
  ### Identity
64
60
 
65
61
  ```ruby
66
- actual.should be(expected) # passes if actual.equal?(expected)
67
- actual.should equal(expected) # passes if actual.equal?(expected)
62
+ expect(actual).to be(expected) # passes if actual.equal?(expected)
63
+ expect(actual).to equal(expected) # passes if actual.equal?(expected)
68
64
  ```
69
65
 
70
66
  ### Comparisons
71
67
 
72
68
  ```ruby
73
- actual.should be > expected
74
- actual.should be >= expected
75
- actual.should be <= expected
76
- actual.should be < expected
77
- actual.should be_within(delta).of(expected)
69
+ expect(actual).to be > expected
70
+ expect(actual).to be >= expected
71
+ expect(actual).to be <= expected
72
+ expect(actual).to be < expected
73
+ expect(actual).to be_within(delta).of(expected)
78
74
  ```
79
75
 
80
76
  ### Regular expressions
81
77
 
82
78
  ```ruby
83
- actual.should match(/expression/)
84
- actual.should =~ /expression/
79
+ expect(actual).to match(/expression/)
85
80
  ```
86
81
 
82
+ Note: The new `expect` syntax no longer supports the `=~` matcher.
83
+
87
84
  ### Types/classes
88
85
 
89
86
  ```ruby
90
- actual.should be_an_instance_of(expected)
91
- actual.should be_a_kind_of(expected)
87
+ expect(actual).to be_an_instance_of(expected) # passes if actual.class == expected
88
+ expect(actual).to be_a(expected) # passes if actual.is_a?(expected)
89
+ expect(actual).to be_an(expected) # an alias for be_a
90
+ expect(actual).to be_a_kind_of(expected) # another alias
92
91
  ```
93
92
 
94
93
  ### Truthiness
95
94
 
96
95
  ```ruby
97
- actual.should be_true # passes if actual is truthy (not nil or false)
98
- actual.should be_false # passes if actual is falsy (nil or false)
99
- actual.should be_nil # passes if actual is nil
96
+ expect(actual).to be_truthy # passes if actual is truthy (not nil or false)
97
+ expect(actual).to be true # passes if actual == true
98
+ expect(actual).to be_falsy # passes if actual is falsy (nil or false)
99
+ expect(actual).to be false # passes if actual == false
100
+ expect(actual).to be_nil # passes if actual is nil
100
101
  ```
101
102
 
102
103
  ### Expecting errors
@@ -134,91 +135,118 @@ expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [
134
135
  ### Predicate matchers
135
136
 
136
137
  ```ruby
137
- actual.should be_xxx # passes if actual.xxx?
138
- actual.should have_xxx(:arg) # passes if actual.has_xxx?(:arg)
138
+ expect(actual).to be_xxx # passes if actual.xxx?
139
+ expect(actual).to have_xxx(:arg) # passes if actual.has_xxx?(:arg)
139
140
  ```
140
141
 
141
142
  ### Ranges (Ruby >= 1.9 only)
142
143
 
143
144
  ```ruby
144
- (1..10).should cover(3)
145
+ expect(1..10).to cover(3)
145
146
  ```
146
147
 
147
148
  ### Collection membership
148
149
 
149
150
  ```ruby
150
- actual.should include(expected)
151
- actual.should start_with(expected)
152
- actual.should end_with(expected)
151
+ expect(actual).to include(expected)
152
+ expect(actual).to start_with(expected)
153
+ expect(actual).to end_with(expected)
154
+
155
+ expect(actual).to contain_exactly(individual, items)
156
+ # ...which is the same as:
157
+ expect(actual).to match_array(expected_array)
153
158
  ```
154
159
 
155
160
  #### Examples
156
161
 
157
162
  ```ruby
158
- [1,2,3].should include(1)
159
- [1,2,3].should include(1, 2)
160
- [1,2,3].should start_with(1)
161
- [1,2,3].should start_with(1,2)
162
- [1,2,3].should end_with(3)
163
- [1,2,3].should end_with(2,3)
164
- {:a => 'b'}.should include(:a => 'b')
165
- "this string".should include("is str")
166
- "this string".should start_with("this")
167
- "this string".should end_with("ring")
163
+ expect([1, 2, 3]).to include(1)
164
+ expect([1, 2, 3]).to include(1, 2)
165
+ expect([1, 2, 3]).to start_with(1)
166
+ expect([1, 2, 3]).to start_with(1, 2)
167
+ expect([1, 2, 3]).to end_with(3)
168
+ expect([1, 2, 3]).to end_with(2, 3)
169
+ expect({:a => 'b'}).to include(:a => 'b')
170
+ expect("this string").to include("is str")
171
+ expect("this string").to start_with("this")
172
+ expect("this string").to end_with("ring")
173
+ expect([1, 2, 3]).to contain_exactly(2, 3, 1)
174
+ expect([1, 2, 3]).to match_array([3, 2, 1])
168
175
  ```
169
176
 
170
- ## `expect` syntax
177
+ ## `should` syntax
171
178
 
172
- In addition to the `should` syntax, rspec-expectations supports
173
- a new `expect` syntax as of version 2.11.0:
179
+ In addition to the `expect` syntax, rspec-expectations continues to support the
180
+ `should` syntax:
174
181
 
175
182
  ```ruby
176
- expect(actual).to eq expected
177
- expect(actual).to be > 3
178
- expect([1, 2, 3]).to_not include 4
183
+ actual.should eq expected
184
+ actual.should be > 3
185
+ [1, 2, 3].should_not include 4
179
186
  ```
180
187
 
181
- If you want your project to only use one of these syntaxes, you can
182
- configure it:
188
+ See [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/master/Should.md)
183
189
 
184
- ```ruby
185
- RSpec.configure do |config|
186
- config.expect_with :rspec do |c|
187
- c.syntax = :expect
188
- # or
189
- c.syntax = :should
190
- # or
191
- c.syntax = [:should, :expect]
192
- end
193
- end
194
- ```
195
-
196
- See
197
- [RSpec::Expectations::Syntax#expect](http://rubydoc.info/gems/rspec-expectations/RSpec/Expectations/Syntax:expect)
198
- for more information.
190
+ ## Compound Matcher Expressions
199
191
 
200
- ### Motivation for `expect`
192
+ You can also create compound matcher expressions using `and` or `or`:
201
193
 
202
- We added the `expect` syntax to resolve some edge case issues, most notably
203
- that objects whose definitions wipe out all but a few methods were throwing
204
- `should` and `should_not` away. `expect` solves that by not monkey patching
205
- those methods onto `Kernel` (or any global object).
194
+ ``` ruby
195
+ expect(alphabet).to start_with("a").and end_with("z")
196
+ expect(stoplight.color).to eq("red").or eq("green").or eq("yellow")
197
+ ```
206
198
 
207
- See
208
- [http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax](http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax)
209
- for a detailed explanation.
199
+ ## Composing Matchers
210
200
 
211
- ### One-liners
201
+ Many of the built-in matchers are designed to take matchers as
202
+ arguments, to allow you to flexibly specify only the essential
203
+ aspects of an object or data structure. In addition, all of the
204
+ built-in matchers have one or more aliases that provide better
205
+ phrasing for when they are used as arguments to another matcher.
212
206
 
213
- The one-liner syntax supported by
214
- [rspec-core](http://rubydoc.info/gems/rspec-core) uses `should` even when
215
- `config.syntax = :expect`. It reads better than the alternative, and does not
216
- require a global monkey patch:
207
+ ### Examples
217
208
 
218
209
  ```ruby
219
- describe User do
220
- it { should validate_presence_of :email }
221
- end
210
+ expect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(1.0) )
211
+
212
+ expect { s = "barn" }.to change { s }
213
+ .from( a_string_matching(/foo/) )
214
+ .to( a_string_matching(/bar/) )
215
+
216
+ expect(["barn", 2.45]).to contain_exactly(
217
+ a_value_within(0.1).of(2.5),
218
+ a_string_starting_with("bar")
219
+ )
220
+
221
+ expect(["barn", "food", 2.45]).to end_with(
222
+ a_string_matching("foo"),
223
+ a_value > 2
224
+ )
225
+
226
+ expect(["barn", 2.45]).to include( a_string_starting_with("bar") )
227
+
228
+ expect(:a => "food", :b => "good").to include(:a => a_string_matching(/foo/))
229
+
230
+ hash = {
231
+ :a => {
232
+ :b => ["foo", 5],
233
+ :c => { :d => 2.05 }
234
+ }
235
+ }
236
+
237
+ expect(hash).to match(
238
+ :a => {
239
+ :b => a_collection_containing_exactly(
240
+ a_string_starting_with("f"),
241
+ an_instance_of(Fixnum)
242
+ ),
243
+ :c => { :d => (a_value < 3) }
244
+ }
245
+ )
246
+
247
+ expect { |probe|
248
+ [1, 2, 3].each(&probe)
249
+ }.to yield_successive_args( a_value < 2, 2, a_value > 2 )
222
250
  ```
223
251
 
224
252
  ## Also see
@@ -226,3 +254,4 @@ end
226
254
  * [http://github.com/rspec/rspec](http://github.com/rspec/rspec)
227
255
  * [http://github.com/rspec/rspec-core](http://github.com/rspec/rspec-core)
228
256
  * [http://github.com/rspec/rspec-mocks](http://github.com/rspec/rspec-mocks)
257
+ * [http://github.com/rspec/rspec-collection_matchers](https://github.com/rspec/rspec-collection_matchers)
@@ -1,8 +1,22 @@
1
- require 'rspec/expectations/syntax'
1
+ RSpec::Support.require_rspec_expectations "syntax"
2
2
 
3
3
  module RSpec
4
- module Matchers
4
+ module Expectations
5
5
  # Provides configuration options for rspec-expectations.
6
+ # If you are using rspec-core, you can access this via a
7
+ # block passed to `RSpec::Core::Configuration#expect_with`.
8
+ # Otherwise, you can access it via RSpec::Expectations.configuration.
9
+ #
10
+ # @example
11
+ # RSpec.configure do |rspec|
12
+ # rspec.expect_with :rspec do |c|
13
+ # # c is the config object
14
+ # end
15
+ # end
16
+ #
17
+ # # or
18
+ #
19
+ # RSpec::Expectations.configuration
6
20
  class Configuration
7
21
  # Configures the supported syntax.
8
22
  # @param [Array<Symbol>, Symbol] values the syntaxes to enable
@@ -32,6 +46,10 @@ module RSpec
32
46
 
33
47
  # The list of configured syntaxes.
34
48
  # @return [Array<Symbol>] the list of configured syntaxes.
49
+ # @example
50
+ # unless RSpec::Matchers.configuration.syntax.include?(:expect)
51
+ # raise "this RSpec extension gem requires the rspec-expectations `:expect` syntax"
52
+ # end
35
53
  def syntax
36
54
  syntaxes = []
37
55
  syntaxes << :should if Expectations::Syntax.should_enabled?
@@ -39,14 +57,21 @@ module RSpec
39
57
  syntaxes
40
58
  end
41
59
 
42
- # color config for expectations
43
- # fallback if rspec core not available
44
60
  if ::RSpec.respond_to?(:configuration)
45
61
  def color?
46
62
  ::RSpec.configuration.color_enabled?
47
63
  end
48
64
  else
49
- attr_writer :color
65
+ # Indicates whether or not diffs should be colored.
66
+ # Delegates to rspec-core's color option if rspec-core
67
+ # is loaded; otherwise you can set it here.
68
+ def color=(value)
69
+ @color = value
70
+ end
71
+
72
+ # Indicates whether or not diffs should be colored.
73
+ # Delegates to rspec-core's color option if rspec-core
74
+ # is loaded; otherwise you can set it here.
50
75
  def color?
51
76
  @color
52
77
  end
@@ -74,20 +99,25 @@ module RSpec
74
99
  # will be used (including respecting the presence or absence of
75
100
  # the `--backtrace` option).
76
101
  #
77
- # @overload backtrace_formatter
78
- # @return [#format_backtrace] the backtrace formatter
79
- # @overload backtrace_formatter=
80
- # @param value [#format_backtrace] sets the backtrace formatter
102
+ # @!attribute [rw] backtrace_formatter
81
103
  attr_writer :backtrace_formatter
82
104
  def backtrace_formatter
83
- @backtrace_formatter ||= if defined?(::RSpec::Core::BacktraceFormatter)
84
- ::RSpec::Core::BacktraceFormatter
105
+ @backtrace_formatter ||= if defined?(::RSpec.configuration.backtrace_formatter)
106
+ ::RSpec.configuration.backtrace_formatter
85
107
  else
86
108
  NullBacktraceFormatter
87
109
  end
88
110
  end
89
111
 
112
+ # @private
113
+ def reset_syntaxes_to_default
114
+ self.syntax = [:should, :expect]
115
+ RSpec::Expectations::Syntax.warn_about_should!
116
+ end
117
+
90
118
  # @api private
119
+ # Null implementation of a backtrace formatter used by default
120
+ # when rspec-core is not loaded. Does no filtering.
91
121
  NullBacktraceFormatter = Module.new do
92
122
  def self.format_backtrace(backtrace)
93
123
  backtrace
@@ -95,14 +125,14 @@ module RSpec
95
125
  end
96
126
  end
97
127
 
98
- # The configuration object
99
- # @return [RSpec::Matchers::Configuration] the configuration object
128
+ # The configuration object.
129
+ # @return [RSpec::Expectations::Configuration] the configuration object
100
130
  def self.configuration
101
131
  @configuration ||= Configuration.new
102
132
  end
103
133
 
104
134
  # set default syntax
105
- configuration.syntax = [:expect, :should]
135
+ configuration.reset_syntaxes_to_default
106
136
  end
107
137
  end
108
138
 
@@ -1,23 +1,43 @@
1
1
  module RSpec
2
2
  module Expectations
3
3
  # Wraps the target of an expectation.
4
+ #
4
5
  # @example
5
- # expect(something) # => ExpectationTarget wrapping something
6
+ # expect(something) # => ExpectationTarget wrapping something
7
+ # expect { do_something } # => ExpectationTarget wrapping the block
6
8
  #
7
9
  # # used with `to`
8
10
  # expect(actual).to eq(3)
9
11
  #
10
- # # with `to_not`
11
- # expect(actual).to_not eq(3)
12
+ # # with `not_to`
13
+ # expect(actual).not_to eq(3)
14
+ #
15
+ # @note `ExpectationTarget` is not intended to be instantiated
16
+ # directly by users. Use `expect` instead.
12
17
  class ExpectationTarget
13
- class << self
14
- attr_accessor :deprecated_should_enabled
15
- alias deprecated_should_enabled? deprecated_should_enabled
16
- end
18
+ # @private
19
+ # Used as a sentinel value to be able to tell when the user
20
+ # did not pass an argument. We can't use `nil` for that because
21
+ # `nil` is a valid value to pass.
22
+ UndefinedValue = Module.new
17
23
 
18
24
  # @api private
19
- def initialize(target)
20
- @target = target
25
+ def initialize(value)
26
+ @target = value
27
+ end
28
+
29
+ # @private
30
+ def self.for(value, block)
31
+ if UndefinedValue.equal?(value)
32
+ unless block
33
+ raise ArgumentError, "You must pass either an argument or a block to `expect`."
34
+ end
35
+ BlockExpectationTarget.new(block)
36
+ elsif block
37
+ raise ArgumentError, "You cannot pass both an argument and a block to `expect`."
38
+ else
39
+ new(value)
40
+ end
21
41
  end
22
42
 
23
43
  # Runs the given expectation, passing if `matcher` returns true.
@@ -26,61 +46,74 @@ module RSpec
26
46
  # expect { perform }.to raise_error
27
47
  # @param [Matcher]
28
48
  # matcher
29
- # @param [String] message optional message to display when the expectation fails
49
+ # @param [String or Proc] message optional message to display when the expectation fails
30
50
  # @return [Boolean] true if the expectation succeeds (else raises)
31
51
  # @see RSpec::Matchers
32
52
  def to(matcher=nil, message=nil, &block)
33
- prevent_operator_matchers(:to, matcher)
53
+ prevent_operator_matchers(:to) unless matcher
34
54
  RSpec::Expectations::PositiveExpectationHandler.handle_matcher(@target, matcher, message, &block)
35
55
  end
36
56
 
37
57
  # Runs the given expectation, passing if `matcher` returns false.
38
58
  # @example
39
- # expect(value).to_not eq(5)
40
59
  # expect(value).not_to eq(5)
41
60
  # @param [Matcher]
42
61
  # matcher
43
- # @param [String] message optional message to display when the expectation fails
62
+ # @param [String or Proc] message optional message to display when the expectation fails
44
63
  # @return [Boolean] false if the negative expectation succeeds (else raises)
45
64
  # @see RSpec::Matchers
46
- def to_not(matcher=nil, message=nil, &block)
47
- prevent_operator_matchers(:to_not, matcher)
65
+ def not_to(matcher=nil, message=nil, &block)
66
+ prevent_operator_matchers(:not_to) unless matcher
48
67
  RSpec::Expectations::NegativeExpectationHandler.handle_matcher(@target, matcher, message, &block)
49
68
  end
50
- alias not_to to_not
69
+ alias to_not not_to
51
70
 
52
- def self.enable_deprecated_should
53
- return if deprecated_should_enabled?
71
+ private
54
72
 
55
- def should(*args)
56
- RSpec.deprecate "`expect { }.should`", "`expect { }.to`", 3
57
- @target.should(*args)
58
- end
73
+ def prevent_operator_matchers(verb)
74
+ raise ArgumentError, "The expect syntax does not support operator matchers, " +
75
+ "so you must pass a matcher to `##{verb}`."
76
+ end
77
+ end
59
78
 
60
- def should_not(*args)
61
- RSpec.deprecate "`expect { }.should_not`", "`expect { }.to_not`", 3
62
- @target.should_not(*args)
63
- end
79
+ # @private
80
+ # Validates the provided matcher to ensure it supports block
81
+ # expectations, in order to avoid user confusion when they
82
+ # use a block thinking the expectation will be on the return
83
+ # value of the block rather than the block itself.
84
+ class BlockExpectationTarget < ExpectationTarget
85
+ def to(matcher, message=nil, &block)
86
+ enforce_block_expectation(matcher)
87
+ super
88
+ end
64
89
 
65
- self.deprecated_should_enabled = true
90
+ def not_to(matcher, message=nil, &block)
91
+ enforce_block_expectation(matcher)
92
+ super
66
93
  end
94
+ alias to_not not_to
67
95
 
68
- def self.disable_deprecated_should
69
- return unless deprecated_should_enabled?
96
+ private
70
97
 
71
- remove_method :should
72
- remove_method :should_not
98
+ def enforce_block_expectation(matcher)
99
+ return if supports_block_expectations?(matcher)
73
100
 
74
- self.deprecated_should_enabled = false
101
+ raise ExpectationNotMetError,
102
+ "You must pass an argument rather than a block to use the provided " +
103
+ "matcher (#{description_of matcher}), or the matcher must implement " +
104
+ "`supports_block_expectations?`."
75
105
  end
76
106
 
77
- private
78
-
79
- def prevent_operator_matchers(verb, matcher)
80
- return if matcher
107
+ def supports_block_expectations?(matcher)
108
+ matcher.supports_block_expectations?
109
+ rescue NoMethodError
110
+ false
111
+ end
81
112
 
82
- raise ArgumentError, "The expect syntax does not support operator matchers, " +
83
- "so you must pass a matcher to `##{verb}`."
113
+ def description_of(matcher)
114
+ matcher.description
115
+ rescue NoMethodError
116
+ matcher.inspect
84
117
  end
85
118
  end
86
119
  end
@@ -1,9 +1,14 @@
1
+ RSpec::Support.require_rspec_support 'differ'
2
+
1
3
  module RSpec
2
4
  module Expectations
3
5
  class << self
4
6
  # @private
5
7
  def differ
6
- @differ ||= Differ.new
8
+ RSpec::Support::Differ.new(
9
+ :object_preparer => lambda {|object| RSpec::Matchers::Composable.surface_descriptions_in(object) },
10
+ :color => RSpec::Matchers.configuration.color?
11
+ )
7
12
  end
8
13
 
9
14
  # Raises an RSpec::Expectations::ExpectationNotMetError with message.
@@ -16,53 +21,16 @@ module RSpec
16
21
  def fail_with(message, expected=nil, actual=nil)
17
22
  if !message
18
23
  raise ArgumentError, "Failure message is nil. Does your matcher define the " +
19
- "appropriate failure_message_for_* method to return a string?"
20
- end
21
-
22
- if actual && expected
23
- if all_strings?(actual, expected)
24
- if any_multiline_strings?(actual, expected)
25
- message << "\nDiff:" << differ.diff_as_string(coerce_to_string(actual), coerce_to_string(expected))
26
- end
27
- elsif no_procs?(actual, expected) && no_numbers?(actual, expected)
28
- message << "\nDiff:" << differ.diff_as_object(actual, expected)
29
- end
24
+ "appropriate failure_message[_when_negated] method to return a string?"
30
25
  end
31
26
 
32
- raise(RSpec::Expectations::ExpectationNotMetError.new(message))
33
- end
34
-
35
- private
36
-
37
- def no_procs?(*args)
38
- args.flatten.none? {|a| Proc === a}
39
- end
40
-
41
- def all_strings?(*args)
42
- args.flatten.all? {|a| String === a}
43
- end
27
+ diff = differ.diff(actual, expected)
44
28
 
45
- def any_multiline_strings?(*args)
46
- all_strings?(*args) && args.flatten.any? { |a| multiline?(a) }
47
- end
48
-
49
- def no_numbers?(*args)
50
- args.flatten.none? {|a| Numeric === a}
51
- end
52
-
53
- def coerce_to_string(string_or_array)
54
- return string_or_array unless Array === string_or_array
55
- string_or_array.join(',')
56
- end
57
-
58
- if String.method_defined?(:encoding)
59
- def multiline?(string)
60
- string.include?("\n".encode(string.encoding))
61
- end
62
- else
63
- def multiline?(string)
64
- string.include?("\n")
29
+ unless diff.empty?
30
+ message = "#{message}\nDiff:#{diff}"
65
31
  end
32
+
33
+ raise RSpec::Expectations::ExpectationNotMetError.new(message)
66
34
  end
67
35
  end
68
36
  end