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
@@ -1,22 +1,379 @@
1
1
  module RSpec
2
2
  module Matchers
3
+ # Defines the custom matcher DSL.
3
4
  module DSL
4
5
  # Defines a custom matcher.
5
6
  # @see RSpec::Matchers
6
7
  def define(name, &declarations)
7
- matcher_template = RSpec::Matchers::DSL::Matcher.new(name, &declarations)
8
8
  define_method name do |*expected|
9
- matcher = matcher_template.for_expected(*expected)
10
- matcher.matcher_execution_context = @matcher_execution_context ||= self
11
- matcher
9
+ RSpec::Matchers::DSL::Matcher.new(name, declarations, self, *expected)
12
10
  end
13
11
  end
14
-
15
12
  alias_method :matcher, :define
16
13
 
17
14
  if RSpec.respond_to?(:configure)
18
15
  RSpec.configure {|c| c.extend self}
19
16
  end
17
+
18
+ # Contains the methods that are available from within the
19
+ # `RSpec::Matchers.define` DSL for creating custom matchers.
20
+ module Macros
21
+ # Stores the block that is used to determine whether this matcher passes
22
+ # or fails. The block should return a boolean value. When the matcher is
23
+ # passed to `expect(...).to` and the block returns `true`, then the expectation
24
+ # passes. Similarly, when the matcher is passed to `expect(...).not_to` and the
25
+ # block returns `false`, then the expectation passes.
26
+ #
27
+ # @example
28
+ #
29
+ # RSpec::Matchers.define :be_even do
30
+ # match do |actual|
31
+ # actual.even?
32
+ # end
33
+ # end
34
+ #
35
+ # expect(4).to be_even # passes
36
+ # expect(3).not_to be_even # passes
37
+ # expect(3).to be_even # fails
38
+ # expect(4).not_to be_even # fails
39
+ #
40
+ # @yield [Object] actual the actual value (i.e. the value wrapped by `expect`)
41
+ def match(&match_block)
42
+ define_user_override(:matches?, match_block) do |actual|
43
+ begin
44
+ @actual = actual
45
+ super(*actual_arg_for(match_block))
46
+ rescue RSpec::Expectations::ExpectationNotMetError
47
+ false
48
+ end
49
+ end
50
+ end
51
+
52
+ # Use this to define the block for a negative expectation (`expect(...).not_to`)
53
+ # when the positive and negative forms require different handling. This
54
+ # is rarely necessary, but can be helpful, for example, when specifying
55
+ # asynchronous processes that require different timeouts.
56
+ #
57
+ # @yield [Object] actual the actual value (i.e. the value wrapped by `expect`)
58
+ def match_when_negated(&match_block)
59
+ define_user_override(:does_not_match?, match_block) do |actual|
60
+ @actual = actual
61
+ super(*actual_arg_for(match_block))
62
+ end
63
+ end
64
+
65
+ # Use this instead of `match` when the block will raise an exception
66
+ # rather than returning false to indicate a failure.
67
+ #
68
+ # @example
69
+ #
70
+ # RSpec::Matchers.define :accept_as_valid do |candidate_address|
71
+ # match_unless_raises ValidationException do |validator|
72
+ # validator.validate(candidate_address)
73
+ # end
74
+ # end
75
+ #
76
+ # expect(email_validator).to accept_as_valid("person@company.com")
77
+ #
78
+ # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
79
+ def match_unless_raises(expected_exception=Exception, &match_block)
80
+ define_user_override(:matches?, match_block) do |actual|
81
+ @actual = actual
82
+ begin
83
+ super(*actual_arg_for(match_block))
84
+ rescue expected_exception => @rescued_exception
85
+ false
86
+ else
87
+ true
88
+ end
89
+ end
90
+ end
91
+
92
+ # Customizes the failure messsage to use when this matcher is
93
+ # asked to positively match. Only use this when the message
94
+ # generated by default doesn't suit your needs.
95
+ #
96
+ # @example
97
+ #
98
+ # RSpec::Matchers.define :have_strength do |expected|
99
+ # match { your_match_logic }
100
+ #
101
+ # failure_message do |actual|
102
+ # "Expected strength of #{expected}, but had #{actual.strength}"
103
+ # end
104
+ # end
105
+ #
106
+ # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
107
+ def failure_message(&definition)
108
+ define_user_override(__method__, definition)
109
+ end
110
+
111
+ # Customize the failure messsage to use when this matcher is asked
112
+ # to negatively match. Only use this when the message generated by
113
+ # default doesn't suit your needs.
114
+ #
115
+ # @example
116
+ #
117
+ # RSpec::Matchers.define :have_strength do |expected|
118
+ # match { your_match_logic }
119
+ #
120
+ # failure_message_when_negated do |actual|
121
+ # "Expected not to have strength of #{expected}, but did"
122
+ # end
123
+ # end
124
+ #
125
+ # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
126
+ def failure_message_when_negated(&definition)
127
+ define_user_override(__method__, definition)
128
+ end
129
+
130
+ # Customize the description to use for one-liners. Only use this when
131
+ # the description generated by default doesn't suit your needs.
132
+ #
133
+ # @example
134
+ #
135
+ # RSpec::Matchers.define :qualify_for do |expected|
136
+ # match { your_match_logic }
137
+ #
138
+ # description do
139
+ # "qualify for #{expected}"
140
+ # end
141
+ # end
142
+ #
143
+ # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
144
+ def description(&definition)
145
+ define_user_override(__method__, definition)
146
+ end
147
+
148
+ # Tells the matcher to diff the actual and expected values in the failure
149
+ # message.
150
+ def diffable
151
+ define_method(:diffable?) { true }
152
+ end
153
+
154
+ # Declares that the matcher can be used in a block expectation.
155
+ # Users will not be able to use your matcher in a block
156
+ # expectation without declaring this.
157
+ # (e.g. `expect { do_something }.to matcher`).
158
+ def supports_block_expectations
159
+ define_method(:supports_block_expectations?) { true }
160
+ end
161
+
162
+ # Convenience for defining methods on this matcher to create a fluent
163
+ # interface. The trick about fluent interfaces is that each method must
164
+ # return self in order to chain methods together. `chain` handles that
165
+ # for you.
166
+ #
167
+ # @example
168
+ #
169
+ # RSpec::Matchers.define :have_errors_on do |key|
170
+ # chain :with do |message|
171
+ # @message = message
172
+ # end
173
+ #
174
+ # match do |actual|
175
+ # actual.errors[key] == @message
176
+ # end
177
+ # end
178
+ #
179
+ # expect(minor).to have_errors_on(:age).with("Not old enough to participate")
180
+ def chain(name, &definition)
181
+ define_user_override(name, definition) do |*args, &block|
182
+ super(*args, &block)
183
+ self
184
+ end
185
+ end
186
+
187
+ private
188
+
189
+ # Does the following:
190
+ #
191
+ # - Defines the named method usign a user-provided block
192
+ # in @user_method_defs, which is included as an ancestor
193
+ # in the singleton class in which we eval the `define` block.
194
+ # - Defines an overriden definition for the same method
195
+ # usign the provided `our_def` block.
196
+ # - Provides a default `our_def` block for the common case
197
+ # of needing to call the user's definition with `@actual`
198
+ # as an arg, but only if their block's arity can handle it.
199
+ #
200
+ # This compiles the user block into an actual method, allowing
201
+ # them to use normal method constructs like `return`
202
+ # (e.g. for a early guard statement), while allowing us to define
203
+ # an override that can provide the wrapped handling
204
+ # (e.g. assigning `@actual`, rescueing errors, etc) and
205
+ # can `super` to the user's definition.
206
+ def define_user_override(method_name, user_def, &our_def)
207
+ @user_method_defs.__send__(:define_method, method_name, &user_def)
208
+ our_def ||= lambda { super(*actual_arg_for(user_def)) }
209
+ define_method(method_name, &our_def)
210
+ end
211
+
212
+ # Defines deprecated macro methods from RSpec 2 for backwards compatibility.
213
+ # @deprecated Use the methods from {Macros} instead.
214
+ module Deprecated
215
+ # @deprecated Use {Macros#match} instead.
216
+ def match_for_should(&definition)
217
+ RSpec.deprecate("`match_for_should`", :replacement => "`match`")
218
+ match(&definition)
219
+ end
220
+
221
+ # @deprecated Use {Macros#match_when_negated} instead.
222
+ def match_for_should_not(&definition)
223
+ RSpec.deprecate("`match_for_should_not`", :replacement => "`match_when_negated`")
224
+ match_when_negated(&definition)
225
+ end
226
+
227
+ # @deprecated Use {Macros#failure_message} instead.
228
+ def failure_message_for_should(&definition)
229
+ RSpec.deprecate("`failure_message_for_should`", :replacement => "`failure_message`")
230
+ failure_message(&definition)
231
+ end
232
+
233
+ # @deprecated Use {Macros#failure_message_when_negated} instead.
234
+ def failure_message_for_should_not(&definition)
235
+ RSpec.deprecate("`failure_message_for_should_not`", :replacement => "`failure_message_when_negated`")
236
+ failure_message_when_negated(&definition)
237
+ end
238
+ end
239
+ end
240
+
241
+ # Defines default implementations of the matcher
242
+ # protocol methods for custom matchers. You can
243
+ # override any of these using the {RSpec::Matchers::DSL::Macros Macros} methods
244
+ # from within an `RSpec::Matchers.define` block.
245
+ module DefaultImplementations
246
+ # @api private
247
+ # Used internally by objects returns by `should` and `should_not`.
248
+ def diffable?
249
+ false
250
+ end
251
+
252
+ # The default description.
253
+ def description
254
+ "#{name_to_sentence}#{to_sentence expected}"
255
+ end
256
+
257
+ # The default failure message for positive expectations.
258
+ def failure_message
259
+ "expected #{actual.inspect} to #{name_to_sentence}#{to_sentence expected}"
260
+ end
261
+
262
+ # The default failure message for negative expectations.
263
+ def failure_message_when_negated
264
+ "expected #{actual.inspect} not to #{name_to_sentence}#{to_sentence expected}"
265
+ end
266
+
267
+ # Matchers do not support block expectations by default. You
268
+ # must opt-in.
269
+ def supports_block_expectations?
270
+ false
271
+ end
272
+ end
273
+
274
+ # The class used for custom matchers. The block passed to
275
+ # `RSpec::Matchers.define` will be evaluated in the context
276
+ # of the singleton class of an instance, and will have the
277
+ # {RSpec::Matchers::DSL::Macros Macros} methods available.
278
+ class Matcher
279
+ # Provides default implementations for the matcher protocol methods.
280
+ include DefaultImplementations
281
+
282
+ # Allows expectation expressions to be used in the match block.
283
+ include RSpec::Matchers
284
+
285
+ # Converts matcher name and expected args to an English expresion.
286
+ include RSpec::Matchers::Pretty
287
+
288
+ # Supports the matcher composability features of RSpec 3+.
289
+ include Composable
290
+
291
+ # Makes the macro methods available to an `RSpec::Matchers.define` block.
292
+ extend Macros
293
+ extend Macros::Deprecated
294
+
295
+ # Exposes the value being matched against -- generally the object
296
+ # object wrapped by `expect`.
297
+ attr_reader :actual
298
+
299
+ # Exposes the exception raised during the matching by `match_unless_raises`.
300
+ # Could be useful to extract details for a failure message.
301
+ attr_reader :rescued_exception
302
+
303
+ # @api private
304
+ def initialize(name, declarations, matcher_execution_context, *expected)
305
+ @name = name
306
+ @actual = nil
307
+ @expected_as_array = expected
308
+ @matcher_execution_context = matcher_execution_context
309
+
310
+ class << self
311
+ # See `Macros#define_user_override` above, for an explanation.
312
+ include(@user_method_defs = Module.new)
313
+ self
314
+ end.class_exec(*expected, &declarations)
315
+ end
316
+
317
+ # Provides the expected value. This will return an array if
318
+ # multiple arguments were passed to the matcher; otherwise it
319
+ # will return a single value.
320
+ # @see #expected_as_array
321
+ def expected
322
+ if expected_as_array.size == 1
323
+ expected_as_array[0]
324
+ else
325
+ expected_as_array
326
+ end
327
+ end
328
+
329
+ # Returns the expected value as an an array. This exists primarily
330
+ # to aid in upgrading from RSpec 2.x, since in RSpec 2, `expected`
331
+ # always returned an array.
332
+ # @see #expected
333
+ attr_reader :expected_as_array
334
+
335
+ # Adds the name (rather than a cryptic hex number)
336
+ # so we can identify an instance of
337
+ # the matcher in error messages (e.g. for `NoMethodError`)
338
+ def inspect
339
+ "#<#{self.class.name} #{name}>"
340
+ end
341
+
342
+ if RUBY_VERSION.to_f >= 1.9
343
+ # Indicates that this matcher responds to messages
344
+ # from the `@matcher_execution_context` as well.
345
+ # Also, supports getting a method object for such methods.
346
+ def respond_to_missing?(method, include_private=false)
347
+ super || @matcher_execution_context.respond_to?(method, include_private)
348
+ end
349
+ else # for 1.8.7
350
+ # Indicates that this matcher responds to messages
351
+ # from the `@matcher_execution_context` as well.
352
+ def respond_to?(method, include_private=false)
353
+ super || @matcher_execution_context.respond_to?(method, include_private)
354
+ end
355
+ end
356
+
357
+ private
358
+
359
+ def actual_arg_for(block)
360
+ block.arity.zero? ? [] : [@actual]
361
+ end
362
+
363
+ # Takes care of forwarding unhandled messages to the
364
+ # `@matcher_execution_context` (typically the current
365
+ # running `RSpec::Core::Example`). This is needed by
366
+ # rspec-rails so that it can define matchers that wrap
367
+ # Rails' test helper methods, but it's also a useful
368
+ # feature in its own right.
369
+ def method_missing(method, *args, &block)
370
+ if @matcher_execution_context.respond_to?(method)
371
+ @matcher_execution_context.__send__ method, *args, &block
372
+ else
373
+ super(method, *args, &block)
374
+ end
375
+ end
376
+ end
20
377
  end
21
378
  end
22
379
  end
@@ -1,17 +1,24 @@
1
1
  module RSpec
2
2
  module Matchers
3
3
  class << self
4
- attr_accessor :last_matcher, :last_should
4
+ # @private
5
+ attr_accessor :last_matcher, :last_expectation_handler
5
6
  end
6
7
 
8
+ # @api private
9
+ # Used by rspec-core to clear the state used to generate
10
+ # descriptions after an example.
7
11
  def self.clear_generated_description
8
12
  self.last_matcher = nil
9
- self.last_should = nil
13
+ self.last_expectation_handler = nil
10
14
  end
11
15
 
16
+ # @api private
17
+ # Generates an an example description based on the last expectation.
18
+ # Used by rspec-core's one-liner syntax.
12
19
  def self.generated_description
13
- return nil if last_should.nil?
14
- "#{last_should.to_s.gsub('_',' ')} #{last_description}"
20
+ return nil if last_expectation_handler.nil?
21
+ "#{last_expectation_handler.verb} #{last_description}"
15
22
  end
16
23
 
17
24
  private
@@ -20,11 +27,11 @@ module RSpec
20
27
  last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE
21
28
  When you call a matcher in an example without a String, like this:
22
29
 
23
- specify { object.should matcher }
30
+ specify { expect(object).to matcher }
24
31
 
25
32
  or this:
26
33
 
27
- it { should matcher }
34
+ it { is_expected.to matcher }
28
35
 
29
36
  RSpec expects the matcher to have a #description method. You should either
30
37
  add a String to the example this matcher is being used in, or give it a
@@ -0,0 +1,37 @@
1
+ module RSpec
2
+ module Matchers
3
+ # Provides the necessary plumbing to wrap a matcher with a decorator.
4
+ # @private
5
+ class MatcherDelegator
6
+ attr_reader :base_matcher
7
+
8
+ def initialize(base_matcher)
9
+ @base_matcher = base_matcher
10
+ end
11
+
12
+ def method_missing(*args, &block)
13
+ base_matcher.__send__(*args, &block)
14
+ end
15
+
16
+ if ::RUBY_VERSION.to_f > 1.8
17
+ def respond_to_missing?(name, include_all=false)
18
+ super || base_matcher.respond_to?(name, include_all)
19
+ end
20
+ else
21
+ def respond_to?(name, include_all=false)
22
+ super || base_matcher.respond_to?(name, include_all)
23
+ end
24
+ end
25
+
26
+ def initialize_copy(other)
27
+ @base_matcher = @base_matcher.clone
28
+ super
29
+ end
30
+
31
+ # So `===` is delegated via `method_missing`.
32
+ undef ===
33
+ undef ==
34
+ end
35
+ end
36
+ end
37
+
@@ -1,12 +1,20 @@
1
1
  module RSpec
2
2
  module Matchers
3
+ # @api private
4
+ # Contains logic to facilitate converting ruby symbols and
5
+ # objects to english phrases.
3
6
  module Pretty
7
+ # @api private
8
+ # Converts a symbol into an english expression.
4
9
  def split_words(sym)
5
10
  sym.to_s.gsub(/_/,' ')
6
11
  end
12
+ module_function :split_words
7
13
 
14
+ # @api private
15
+ # Converts a collection of objects into an english expression.
8
16
  def to_sentence(words)
9
- return "" unless words
17
+ return " #{words.inspect}" unless words
10
18
  words = Array(words).map { |w| to_word(w) }
11
19
  case words.length
12
20
  when 0
@@ -20,36 +28,25 @@ module RSpec
20
28
  end
21
29
  end
22
30
 
23
- def _pretty_print(array)
24
- result = ""
25
- array.each_with_index do |item, index|
26
- if index < (array.length - 2)
27
- result << "#{item.inspect}, "
28
- elsif index < (array.length - 1)
29
- result << "#{item.inspect} and "
30
- else
31
- result << "#{item.inspect}"
32
- end
33
- end
34
- result
35
- end
36
-
31
+ # @api private
32
+ # Converts the given item to string suitable for use in a list expression.
37
33
  def to_word(item)
38
34
  is_matcher_with_description?(item) ? item.description : item.inspect
39
35
  end
40
36
 
37
+ # @private
38
+ # Provides an English expression for the matcher name.
41
39
  def name_to_sentence
42
40
  split_words(name)
43
41
  end
44
42
 
45
- def expected_to_sentence
46
- to_sentence(@expected) if defined?(@expected)
47
- end
48
-
43
+ # @api private
44
+ # Provides a name for the matcher.
49
45
  def name
50
46
  defined?(@name) ? @name : underscore(self.class.name.split("::").last)
51
47
  end
52
48
 
49
+ # @private
53
50
  # Borrowed from ActiveSupport
54
51
  def underscore(camel_cased_word)
55
52
  word = camel_cased_word.to_s.dup
@@ -60,11 +57,21 @@ module RSpec
60
57
  word
61
58
  end
62
59
 
63
- private
60
+ private
64
61
 
65
62
  def is_matcher_with_description?(object)
66
63
  RSpec::Matchers.is_a_matcher?(object) && object.respond_to?(:description)
67
64
  end
65
+
66
+ # `{ :a => 5, :b => 2 }.inspect` produces:
67
+ # {:a=>5, :b=>2}
68
+ # ...but it looks much better as:
69
+ # {:a => 5, :b => 2}
70
+ #
71
+ # This is idempotent and safe to run on a string multiple times.
72
+ def improve_hash_formatting(inspect_string)
73
+ inspect_string.gsub(/(\S)=>(\S)/, '\1 => \2')
74
+ end
68
75
  end
69
76
  end
70
77
  end