rspec-expectations 2.14.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +15 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/Changelog.md +369 -25
  4. data/License.txt +1 -0
  5. data/README.md +88 -15
  6. data/lib/rspec/{matchers → expectations}/configuration.rb +44 -14
  7. data/lib/rspec/expectations/expectation_target.rb +67 -33
  8. data/lib/rspec/expectations/fail_with.rb +11 -53
  9. data/lib/rspec/expectations/handler.rb +126 -31
  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 +45 -23
  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 -81
  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 +39 -15
  22. data/lib/rspec/matchers/built_in/change.rb +273 -80
  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 +64 -27
  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 +84 -42
  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 +175 -68
  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 +27 -20
  47. data/lib/rspec/matchers.rb +361 -136
  48. data.tar.gz.sig +1 -0
  49. metadata +99 -215
  50. metadata.gz.sig +0 -0
  51. data/features/README.md +0 -48
  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 -161
  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 -14
  83. data/features/syntax_configuration.feature +0 -71
  84. data/features/test_frameworks/test_unit.feature +0 -44
  85. data/lib/rspec/expectations/deprecation.rb +0 -17
  86. data/lib/rspec/expectations/differ.rb +0 -133
  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 -29
  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 -124
  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/matchers/test_unit_integration.rb +0 -11
  100. data/lib/rspec-expectations.rb +0 -1
  101. data/spec/rspec/expectations/differ_spec.rb +0 -192
  102. data/spec/rspec/expectations/expectation_target_spec.rb +0 -82
  103. data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
  104. data/spec/rspec/expectations/fail_with_spec.rb +0 -114
  105. data/spec/rspec/expectations/handler_spec.rb +0 -227
  106. data/spec/rspec/expectations/syntax_spec.rb +0 -139
  107. data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
  108. data/spec/rspec/matchers/be_close_spec.rb +0 -22
  109. data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
  110. data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
  111. data/spec/rspec/matchers/be_spec.rb +0 -516
  112. data/spec/rspec/matchers/be_within_spec.rb +0 -137
  113. data/spec/rspec/matchers/change_spec.rb +0 -553
  114. data/spec/rspec/matchers/configuration_spec.rb +0 -206
  115. data/spec/rspec/matchers/cover_spec.rb +0 -69
  116. data/spec/rspec/matchers/description_generation_spec.rb +0 -190
  117. data/spec/rspec/matchers/dsl_spec.rb +0 -57
  118. data/spec/rspec/matchers/eq_spec.rb +0 -60
  119. data/spec/rspec/matchers/eql_spec.rb +0 -41
  120. data/spec/rspec/matchers/equal_spec.rb +0 -78
  121. data/spec/rspec/matchers/exist_spec.rb +0 -124
  122. data/spec/rspec/matchers/has_spec.rb +0 -122
  123. data/spec/rspec/matchers/have_spec.rb +0 -455
  124. data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
  125. data/spec/rspec/matchers/include_spec.rb +0 -531
  126. data/spec/rspec/matchers/match_array_spec.rb +0 -194
  127. data/spec/rspec/matchers/match_spec.rb +0 -61
  128. data/spec/rspec/matchers/matcher_spec.rb +0 -471
  129. data/spec/rspec/matchers/matchers_spec.rb +0 -37
  130. data/spec/rspec/matchers/method_missing_spec.rb +0 -28
  131. data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
  132. data/spec/rspec/matchers/raise_error_spec.rb +0 -485
  133. data/spec/rspec/matchers/respond_to_spec.rb +0 -292
  134. data/spec/rspec/matchers/satisfy_spec.rb +0 -44
  135. data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
  136. data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
  137. data/spec/rspec/matchers/yield_spec.rb +0 -514
  138. data/spec/spec_helper.rb +0 -54
  139. data/spec/support/classes.rb +0 -56
  140. data/spec/support/in_sub_process.rb +0 -38
  141. data/spec/support/matchers.rb +0 -22
  142. data/spec/support/ruby_version.rb +0 -10
  143. data/spec/support/shared_examples.rb +0 -13
data/README.md CHANGED
@@ -1,4 +1,4 @@
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.
@@ -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(
@@ -54,7 +54,7 @@ expect(actual).to eq(expected) # passes if actual == expected
54
54
  expect(actual).to eql(expected) # passes if actual.eql?(expected)
55
55
  ```
56
56
 
57
- Note: The new `expect` syntax no longer supports `==` matcher.
57
+ Note: The new `expect` syntax no longer supports the `==` matcher.
58
58
 
59
59
  ### Identity
60
60
 
@@ -79,21 +79,25 @@ expect(actual).to be_within(delta).of(expected)
79
79
  expect(actual).to match(/expression/)
80
80
  ```
81
81
 
82
- Note: The new `expect` syntax no longer supports `=~` matcher.
82
+ Note: The new `expect` syntax no longer supports the `=~` matcher.
83
83
 
84
84
  ### Types/classes
85
85
 
86
86
  ```ruby
87
- expect(actual).to be_an_instance_of(expected)
88
- expect(actual).to 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
89
91
  ```
90
92
 
91
93
  ### Truthiness
92
94
 
93
95
  ```ruby
94
- expect(actual).to be_true # passes if actual is truthy (not nil or false)
95
- expect(actual).to be_false # passes if actual is falsy (nil or false)
96
- expect(actual).to 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
97
101
  ```
98
102
 
99
103
  ### Expecting errors
@@ -147,21 +151,27 @@ expect(1..10).to cover(3)
147
151
  expect(actual).to include(expected)
148
152
  expect(actual).to start_with(expected)
149
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)
150
158
  ```
151
159
 
152
160
  #### Examples
153
161
 
154
162
  ```ruby
155
- expect([1,2,3]).to include(1)
156
- expect([1,2,3]).to include(1, 2)
157
- expect([1,2,3]).to start_with(1)
158
- expect([1,2,3]).to start_with(1,2)
159
- expect([1,2,3]).to end_with(3)
160
- expect([1,2,3]).to end_with(2,3)
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)
161
169
  expect({:a => 'b'}).to include(:a => 'b')
162
170
  expect("this string").to include("is str")
163
171
  expect("this string").to start_with("this")
164
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])
165
175
  ```
166
176
 
167
177
  ## `should` syntax
@@ -177,8 +187,71 @@ actual.should be > 3
177
187
 
178
188
  See [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/master/Should.md)
179
189
 
190
+ ## Compound Matcher Expressions
191
+
192
+ You can also create compound matcher expressions using `and` or `or`:
193
+
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
+ ```
198
+
199
+ ## Composing Matchers
200
+
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.
206
+
207
+ ### Examples
208
+
209
+ ```ruby
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 )
250
+ ```
251
+
180
252
  ## Also see
181
253
 
182
254
  * [http://github.com/rspec/rspec](http://github.com/rspec/rspec)
183
255
  * [http://github.com/rspec/rspec-core](http://github.com/rspec/rspec-core)
184
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
12
  # # with `not_to`
11
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,11 +46,11 @@ 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
 
@@ -39,47 +59,61 @@ module RSpec
39
59
  # expect(value).not_to eq(5)
40
60
  # @param [Matcher]
41
61
  # matcher
42
- # @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
43
63
  # @return [Boolean] false if the negative expectation succeeds (else raises)
44
64
  # @see RSpec::Matchers
45
65
  def not_to(matcher=nil, message=nil, &block)
46
- prevent_operator_matchers(:not_to, matcher)
66
+ prevent_operator_matchers(:not_to) unless matcher
47
67
  RSpec::Expectations::NegativeExpectationHandler.handle_matcher(@target, matcher, message, &block)
48
68
  end
49
69
  alias to_not not_to
50
70
 
51
- def self.enable_deprecated_should
52
- return if deprecated_should_enabled?
71
+ private
53
72
 
54
- def should(*args)
55
- RSpec.deprecate "`expect { }.should`", :replacement => "`expect { }.to`"
56
- @target.should(*args)
57
- 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
58
78
 
59
- def should_not(*args)
60
- RSpec.deprecate "`expect { }.should_not`", :replacement => "`expect { }.not_to`"
61
- @target.should_not(*args)
62
- 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
63
89
 
64
- self.deprecated_should_enabled = true
90
+ def not_to(matcher, message=nil, &block)
91
+ enforce_block_expectation(matcher)
92
+ super
65
93
  end
94
+ alias to_not not_to
66
95
 
67
- def self.disable_deprecated_should
68
- return unless deprecated_should_enabled?
96
+ private
69
97
 
70
- remove_method :should
71
- remove_method :should_not
98
+ def enforce_block_expectation(matcher)
99
+ return if supports_block_expectations?(matcher)
72
100
 
73
- 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?`."
74
105
  end
75
106
 
76
- private
77
-
78
- def prevent_operator_matchers(verb, matcher)
79
- return if matcher
107
+ def supports_block_expectations?(matcher)
108
+ matcher.supports_block_expectations?
109
+ rescue NoMethodError
110
+ false
111
+ end
80
112
 
81
- raise ArgumentError, "The expect syntax does not support operator matchers, " +
82
- "so you must pass a matcher to `##{verb}`."
113
+ def description_of(matcher)
114
+ matcher.description
115
+ rescue NoMethodError
116
+ matcher.inspect
83
117
  end
84
118
  end
85
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,63 +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
44
-
45
- def any_multiline_strings?(*args)
46
- all_strings?(*args) && args.flatten.any? { |a| multiline?(a) }
47
- end
27
+ diff = differ.diff(actual, expected)
48
28
 
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
- diffably_stringify(string_or_array).join("\n")
56
- end
57
-
58
- def diffably_stringify(array)
59
- array.map do |entry|
60
- if Array === entry
61
- entry.inspect
62
- else
63
- entry.to_s.gsub("\n", "\\n")
64
- end
29
+ unless diff.empty?
30
+ message = "#{message}\nDiff:#{diff}"
65
31
  end
66
- end
67
32
 
68
- if String.method_defined?(:encoding)
69
- def multiline?(string)
70
- string.include?("\n".encode(string.encoding))
71
- end
72
- else
73
- def multiline?(string)
74
- string.include?("\n")
75
- end
33
+ raise RSpec::Expectations::ExpectationNotMetError.new(message)
76
34
  end
77
35
  end
78
36
  end