rspec-expectations 2.14.0 → 3.13.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 (155) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.document +1 -1
  4. data/.yardopts +1 -1
  5. data/Changelog.md +976 -25
  6. data/{License.txt → LICENSE.md} +5 -3
  7. data/README.md +162 -26
  8. data/lib/rspec/expectations/block_snippet_extractor.rb +253 -0
  9. data/lib/rspec/expectations/configuration.rb +230 -0
  10. data/lib/rspec/expectations/expectation_target.rb +127 -51
  11. data/lib/rspec/expectations/fail_with.rb +17 -57
  12. data/lib/rspec/expectations/failure_aggregator.rb +229 -0
  13. data/lib/rspec/expectations/handler.rb +146 -32
  14. data/lib/rspec/expectations/minitest_integration.rb +58 -0
  15. data/lib/rspec/expectations/syntax.rb +68 -100
  16. data/lib/rspec/expectations/version.rb +1 -1
  17. data/lib/rspec/expectations.rb +58 -23
  18. data/lib/rspec/matchers/aliased_matcher.rb +116 -0
  19. data/lib/rspec/matchers/built_in/all.rb +86 -0
  20. data/lib/rspec/matchers/built_in/base_matcher.rb +191 -20
  21. data/lib/rspec/matchers/built_in/be.rb +114 -114
  22. data/lib/rspec/matchers/built_in/be_between.rb +77 -0
  23. data/lib/rspec/matchers/built_in/be_instance_of.rb +15 -4
  24. data/lib/rspec/matchers/built_in/be_kind_of.rb +10 -1
  25. data/lib/rspec/matchers/built_in/be_within.rb +35 -18
  26. data/lib/rspec/matchers/built_in/change.rb +389 -80
  27. data/lib/rspec/matchers/built_in/compound.rb +290 -0
  28. data/lib/rspec/matchers/built_in/contain_exactly.rb +310 -0
  29. data/lib/rspec/matchers/built_in/count_expectation.rb +169 -0
  30. data/lib/rspec/matchers/built_in/cover.rb +3 -0
  31. data/lib/rspec/matchers/built_in/eq.rb +30 -8
  32. data/lib/rspec/matchers/built_in/eql.rb +23 -8
  33. data/lib/rspec/matchers/built_in/equal.rb +55 -22
  34. data/lib/rspec/matchers/built_in/exist.rb +74 -10
  35. data/lib/rspec/matchers/built_in/has.rb +141 -22
  36. data/lib/rspec/matchers/built_in/have_attributes.rb +114 -0
  37. data/lib/rspec/matchers/built_in/include.rb +184 -32
  38. data/lib/rspec/matchers/built_in/match.rb +95 -1
  39. data/lib/rspec/matchers/built_in/operators.rb +128 -0
  40. data/lib/rspec/matchers/built_in/output.rb +207 -0
  41. data/lib/rspec/matchers/built_in/raise_error.rb +192 -44
  42. data/lib/rspec/matchers/built_in/respond_to.rb +154 -28
  43. data/lib/rspec/matchers/built_in/satisfy.rb +39 -9
  44. data/lib/rspec/matchers/built_in/start_or_end_with.rb +94 -0
  45. data/lib/rspec/matchers/built_in/throw_symbol.rb +58 -14
  46. data/lib/rspec/matchers/built_in/yield.rb +240 -161
  47. data/lib/rspec/matchers/built_in.rb +47 -33
  48. data/lib/rspec/matchers/composable.rb +171 -0
  49. data/lib/rspec/matchers/dsl.rb +531 -10
  50. data/lib/rspec/matchers/english_phrasing.rb +58 -0
  51. data/lib/rspec/matchers/fail_matchers.rb +42 -0
  52. data/lib/rspec/matchers/generated_descriptions.rb +14 -8
  53. data/lib/rspec/matchers/matcher_delegator.rb +61 -0
  54. data/lib/rspec/matchers/matcher_protocol.rb +105 -0
  55. data/lib/rspec/matchers/multi_matcher_diff.rb +82 -0
  56. data/lib/rspec/matchers.rb +520 -173
  57. data.tar.gz.sig +0 -0
  58. metadata +141 -242
  59. metadata.gz.sig +2 -0
  60. data/features/README.md +0 -48
  61. data/features/Upgrade.md +0 -53
  62. data/features/built_in_matchers/README.md +0 -90
  63. data/features/built_in_matchers/be.feature +0 -175
  64. data/features/built_in_matchers/be_within.feature +0 -48
  65. data/features/built_in_matchers/cover.feature +0 -47
  66. data/features/built_in_matchers/end_with.feature +0 -48
  67. data/features/built_in_matchers/equality.feature +0 -139
  68. data/features/built_in_matchers/exist.feature +0 -45
  69. data/features/built_in_matchers/expect_change.feature +0 -59
  70. data/features/built_in_matchers/expect_error.feature +0 -144
  71. data/features/built_in_matchers/have.feature +0 -109
  72. data/features/built_in_matchers/include.feature +0 -174
  73. data/features/built_in_matchers/match.feature +0 -52
  74. data/features/built_in_matchers/operators.feature +0 -227
  75. data/features/built_in_matchers/predicates.feature +0 -137
  76. data/features/built_in_matchers/respond_to.feature +0 -84
  77. data/features/built_in_matchers/satisfy.feature +0 -33
  78. data/features/built_in_matchers/start_with.feature +0 -48
  79. data/features/built_in_matchers/throw_symbol.feature +0 -91
  80. data/features/built_in_matchers/types.feature +0 -116
  81. data/features/built_in_matchers/yield.feature +0 -161
  82. data/features/custom_matchers/access_running_example.feature +0 -53
  83. data/features/custom_matchers/define_diffable_matcher.feature +0 -27
  84. data/features/custom_matchers/define_matcher.feature +0 -368
  85. data/features/custom_matchers/define_matcher_outside_rspec.feature +0 -38
  86. data/features/custom_matchers/define_matcher_with_fluent_interface.feature +0 -24
  87. data/features/customized_message.feature +0 -22
  88. data/features/diffing.feature +0 -85
  89. data/features/implicit_docstrings.feature +0 -52
  90. data/features/step_definitions/additional_cli_steps.rb +0 -22
  91. data/features/support/env.rb +0 -14
  92. data/features/syntax_configuration.feature +0 -71
  93. data/features/test_frameworks/test_unit.feature +0 -44
  94. data/lib/rspec/expectations/deprecation.rb +0 -17
  95. data/lib/rspec/expectations/differ.rb +0 -133
  96. data/lib/rspec/expectations/errors.rb +0 -9
  97. data/lib/rspec/expectations/extensions/array.rb +0 -9
  98. data/lib/rspec/expectations/extensions/object.rb +0 -29
  99. data/lib/rspec/expectations/extensions.rb +0 -2
  100. data/lib/rspec/matchers/be_close.rb +0 -9
  101. data/lib/rspec/matchers/built_in/have.rb +0 -124
  102. data/lib/rspec/matchers/built_in/match_array.rb +0 -51
  103. data/lib/rspec/matchers/built_in/start_and_end_with.rb +0 -48
  104. data/lib/rspec/matchers/compatibility.rb +0 -14
  105. data/lib/rspec/matchers/configuration.rb +0 -108
  106. data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
  107. data/lib/rspec/matchers/matcher.rb +0 -300
  108. data/lib/rspec/matchers/method_missing.rb +0 -12
  109. data/lib/rspec/matchers/operator_matcher.rb +0 -109
  110. data/lib/rspec/matchers/pretty.rb +0 -70
  111. data/lib/rspec/matchers/test_unit_integration.rb +0 -11
  112. data/lib/rspec-expectations.rb +0 -1
  113. data/spec/rspec/expectations/differ_spec.rb +0 -192
  114. data/spec/rspec/expectations/expectation_target_spec.rb +0 -82
  115. data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
  116. data/spec/rspec/expectations/fail_with_spec.rb +0 -114
  117. data/spec/rspec/expectations/handler_spec.rb +0 -227
  118. data/spec/rspec/expectations/syntax_spec.rb +0 -139
  119. data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
  120. data/spec/rspec/matchers/be_close_spec.rb +0 -22
  121. data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
  122. data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
  123. data/spec/rspec/matchers/be_spec.rb +0 -516
  124. data/spec/rspec/matchers/be_within_spec.rb +0 -137
  125. data/spec/rspec/matchers/change_spec.rb +0 -553
  126. data/spec/rspec/matchers/configuration_spec.rb +0 -206
  127. data/spec/rspec/matchers/cover_spec.rb +0 -69
  128. data/spec/rspec/matchers/description_generation_spec.rb +0 -190
  129. data/spec/rspec/matchers/dsl_spec.rb +0 -57
  130. data/spec/rspec/matchers/eq_spec.rb +0 -60
  131. data/spec/rspec/matchers/eql_spec.rb +0 -41
  132. data/spec/rspec/matchers/equal_spec.rb +0 -78
  133. data/spec/rspec/matchers/exist_spec.rb +0 -124
  134. data/spec/rspec/matchers/has_spec.rb +0 -122
  135. data/spec/rspec/matchers/have_spec.rb +0 -455
  136. data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
  137. data/spec/rspec/matchers/include_spec.rb +0 -531
  138. data/spec/rspec/matchers/match_array_spec.rb +0 -194
  139. data/spec/rspec/matchers/match_spec.rb +0 -61
  140. data/spec/rspec/matchers/matcher_spec.rb +0 -471
  141. data/spec/rspec/matchers/matchers_spec.rb +0 -37
  142. data/spec/rspec/matchers/method_missing_spec.rb +0 -28
  143. data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
  144. data/spec/rspec/matchers/raise_error_spec.rb +0 -485
  145. data/spec/rspec/matchers/respond_to_spec.rb +0 -292
  146. data/spec/rspec/matchers/satisfy_spec.rb +0 -44
  147. data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
  148. data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
  149. data/spec/rspec/matchers/yield_spec.rb +0 -514
  150. data/spec/spec_helper.rb +0 -54
  151. data/spec/support/classes.rb +0 -56
  152. data/spec/support/in_sub_process.rb +0 -38
  153. data/spec/support/matchers.rb +0 -22
  154. data/spec/support/ruby_version.rb +0 -10
  155. data/spec/support/shared_examples.rb +0 -13
@@ -0,0 +1,230 @@
1
+ RSpec::Support.require_rspec_expectations "syntax"
2
+
3
+ module RSpec
4
+ module Expectations
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
20
+ class Configuration
21
+ # @private
22
+ FALSE_POSITIVE_BEHAVIOURS =
23
+ {
24
+ :warn => lambda { |message| RSpec.warning message },
25
+ :raise => lambda { |message| raise ArgumentError, message },
26
+ :nothing => lambda { |_| true },
27
+ }
28
+
29
+ def initialize
30
+ @on_potential_false_positives = :warn
31
+ @strict_predicate_matchers = false
32
+ end
33
+
34
+ # Configures the supported syntax.
35
+ # @param [Array<Symbol>, Symbol] values the syntaxes to enable
36
+ # @example
37
+ # RSpec.configure do |rspec|
38
+ # rspec.expect_with :rspec do |c|
39
+ # c.syntax = :should
40
+ # # or
41
+ # c.syntax = :expect
42
+ # # or
43
+ # c.syntax = [:should, :expect]
44
+ # end
45
+ # end
46
+ def syntax=(values)
47
+ if Array(values).include?(:expect)
48
+ Expectations::Syntax.enable_expect
49
+ else
50
+ Expectations::Syntax.disable_expect
51
+ end
52
+
53
+ if Array(values).include?(:should)
54
+ Expectations::Syntax.enable_should
55
+ else
56
+ Expectations::Syntax.disable_should
57
+ end
58
+ end
59
+
60
+ # Configures the maximum character length that RSpec will print while
61
+ # formatting an object. You can set length to nil to prevent RSpec from
62
+ # doing truncation.
63
+ # @param [Fixnum] length the number of characters to limit the formatted output to.
64
+ # @example
65
+ # RSpec.configure do |rspec|
66
+ # rspec.expect_with :rspec do |c|
67
+ # c.max_formatted_output_length = 200
68
+ # end
69
+ # end
70
+ def max_formatted_output_length=(length)
71
+ RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = length
72
+ end
73
+
74
+ # The list of configured syntaxes.
75
+ # @return [Array<Symbol>] the list of configured syntaxes.
76
+ # @example
77
+ # unless RSpec::Matchers.configuration.syntax.include?(:expect)
78
+ # raise "this RSpec extension gem requires the rspec-expectations `:expect` syntax"
79
+ # end
80
+ def syntax
81
+ syntaxes = []
82
+ syntaxes << :should if Expectations::Syntax.should_enabled?
83
+ syntaxes << :expect if Expectations::Syntax.expect_enabled?
84
+ syntaxes
85
+ end
86
+
87
+ if ::RSpec.respond_to?(:configuration)
88
+ def color?
89
+ ::RSpec.configuration.color_enabled?
90
+ end
91
+ else
92
+ # Indicates whether or not diffs should be colored.
93
+ # Delegates to rspec-core's color option if rspec-core
94
+ # is loaded; otherwise you can set it here.
95
+ attr_writer :color
96
+
97
+ # Indicates whether or not diffs should be colored.
98
+ # Delegates to rspec-core's color option if rspec-core
99
+ # is loaded; otherwise you can set it here.
100
+ def color?
101
+ defined?(@color) && @color
102
+ end
103
+ end
104
+
105
+ # Adds `should` and `should_not` to the given classes
106
+ # or modules. This can be used to ensure `should` works
107
+ # properly on things like proxy objects (particular
108
+ # `Delegator`-subclassed objects on 1.8).
109
+ #
110
+ # @param [Array<Module>] modules the list of classes or modules
111
+ # to add `should` and `should_not` to.
112
+ def add_should_and_should_not_to(*modules)
113
+ modules.each do |mod|
114
+ Expectations::Syntax.enable_should(mod)
115
+ end
116
+ end
117
+
118
+ # Sets or gets the backtrace formatter. The backtrace formatter should
119
+ # implement `#format_backtrace(Array<String>)`. This is used
120
+ # to format backtraces of errors handled by the `raise_error`
121
+ # matcher.
122
+ #
123
+ # If you are using rspec-core, rspec-core's backtrace formatting
124
+ # will be used (including respecting the presence or absence of
125
+ # the `--backtrace` option).
126
+ #
127
+ # @!attribute [rw] backtrace_formatter
128
+ attr_writer :backtrace_formatter
129
+ def backtrace_formatter
130
+ @backtrace_formatter ||= if defined?(::RSpec.configuration.backtrace_formatter)
131
+ ::RSpec.configuration.backtrace_formatter
132
+ else
133
+ NullBacktraceFormatter
134
+ end
135
+ end
136
+
137
+ # Sets if custom matcher descriptions and failure messages
138
+ # should include clauses from methods defined using `chain`.
139
+ # @param value [Boolean]
140
+ attr_writer :include_chain_clauses_in_custom_matcher_descriptions
141
+
142
+ # Indicates whether or not custom matcher descriptions and failure messages
143
+ # should include clauses from methods defined using `chain`. It is
144
+ # false by default for backwards compatibility.
145
+ def include_chain_clauses_in_custom_matcher_descriptions?
146
+ @include_chain_clauses_in_custom_matcher_descriptions ||= false
147
+ end
148
+
149
+ # @private
150
+ def reset_syntaxes_to_default
151
+ self.syntax = [:should, :expect]
152
+ RSpec::Expectations::Syntax.warn_about_should!
153
+ end
154
+
155
+ # @api private
156
+ # Null implementation of a backtrace formatter used by default
157
+ # when rspec-core is not loaded. Does no filtering.
158
+ NullBacktraceFormatter = Module.new do
159
+ def self.format_backtrace(backtrace)
160
+ backtrace
161
+ end
162
+ end
163
+
164
+ # Configures whether RSpec will warn about matcher use which will
165
+ # potentially cause false positives in tests.
166
+ #
167
+ # @param [Boolean] boolean
168
+ def warn_about_potential_false_positives=(boolean)
169
+ if boolean
170
+ self.on_potential_false_positives = :warn
171
+ elsif warn_about_potential_false_positives?
172
+ self.on_potential_false_positives = :nothing
173
+ else
174
+ # no-op, handler is something else
175
+ end
176
+ end
177
+ #
178
+ # Configures what RSpec will do about matcher use which will
179
+ # potentially cause false positives in tests.
180
+ #
181
+ # @param [Symbol] behavior can be set to :warn, :raise or :nothing
182
+ def on_potential_false_positives=(behavior)
183
+ unless FALSE_POSITIVE_BEHAVIOURS.key?(behavior)
184
+ raise ArgumentError, "Supported values are: #{FALSE_POSITIVE_BEHAVIOURS.keys}"
185
+ end
186
+ @on_potential_false_positives = behavior
187
+ end
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
+
203
+ # Indicates what RSpec will do about matcher use which will
204
+ # potentially cause false positives in tests, generally you want to
205
+ # avoid such scenarios so this defaults to `true`.
206
+ attr_reader :on_potential_false_positives
207
+
208
+ # Indicates whether RSpec will warn about matcher use which will
209
+ # potentially cause false positives in tests, generally you want to
210
+ # avoid such scenarios so this defaults to `true`.
211
+ def warn_about_potential_false_positives?
212
+ on_potential_false_positives == :warn
213
+ end
214
+
215
+ # @private
216
+ def false_positives_handler
217
+ FALSE_POSITIVE_BEHAVIOURS.fetch(@on_potential_false_positives)
218
+ end
219
+ end
220
+
221
+ # The configuration object.
222
+ # @return [RSpec::Expectations::Configuration] the configuration object
223
+ def self.configuration
224
+ @configuration ||= Configuration.new
225
+ end
226
+
227
+ # set default syntax
228
+ configuration.reset_syntaxes_to_default
229
+ end
230
+ end
@@ -1,87 +1,163 @@
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
23
+
24
+ # @note this name aligns with `Minitest::Expectation` so that our
25
+ # {InstanceMethods} module can be included in that class when
26
+ # used in a Minitest context.
27
+ # @return [Object] the target of the expectation
28
+ attr_reader :target
17
29
 
18
30
  # @api private
19
- def initialize(target)
20
- @target = target
31
+ def initialize(value)
32
+ @target = value
33
+ end
34
+
35
+ # @private
36
+ def self.for(value, block)
37
+ if UndefinedValue.equal?(value)
38
+ unless block
39
+ raise ArgumentError, "You must pass either an argument or a block to `expect`."
40
+ end
41
+ BlockExpectationTarget.new(block)
42
+ elsif block
43
+ raise ArgumentError, "You cannot pass both an argument and a block to `expect`."
44
+ else
45
+ ValueExpectationTarget.new(value)
46
+ end
47
+ end
48
+
49
+ # Defines instance {ExpectationTarget} instance methods. These are defined
50
+ # in a module so we can include it in `Minitest::Expectation` when
51
+ # `rspec/expectations/minitest_integration` is loaded in order to
52
+ # support usage with Minitest.
53
+ module InstanceMethods
54
+ # Runs the given expectation, passing if `matcher` returns true.
55
+ # @example
56
+ # expect(value).to eq(5)
57
+ # expect { perform }.to raise_error
58
+ # @param [Matcher]
59
+ # matcher
60
+ # @param [String, Proc] message optional message to display when the expectation fails
61
+ # @return [Boolean] true if the expectation succeeds (else raises)
62
+ # @see RSpec::Matchers
63
+ def to(matcher=nil, message=nil, &block)
64
+ prevent_operator_matchers(:to) unless matcher
65
+ RSpec::Expectations::PositiveExpectationHandler.handle_matcher(target, matcher, message, &block)
66
+ end
67
+
68
+ # Runs the given expectation, passing if `matcher` returns false.
69
+ # @example
70
+ # expect(value).not_to eq(5)
71
+ # @param [Matcher]
72
+ # matcher
73
+ # @param [String, Proc] message optional message to display when the expectation fails
74
+ # @return [Boolean] false if the negative expectation succeeds (else raises)
75
+ # @see RSpec::Matchers
76
+ def not_to(matcher=nil, message=nil, &block)
77
+ prevent_operator_matchers(:not_to) unless matcher
78
+ RSpec::Expectations::NegativeExpectationHandler.handle_matcher(target, matcher, message, &block)
79
+ end
80
+ alias to_not not_to
81
+
82
+ private
83
+
84
+ def prevent_operator_matchers(verb)
85
+ raise ArgumentError, "The expect syntax does not support operator matchers, " \
86
+ "so you must pass a matcher to `##{verb}`."
87
+ end
21
88
  end
22
89
 
23
- # Runs the given expectation, passing if `matcher` returns true.
24
- # @example
25
- # expect(value).to eq(5)
26
- # expect { perform }.to raise_error
27
- # @param [Matcher]
28
- # matcher
29
- # @param [String] message optional message to display when the expectation fails
30
- # @return [Boolean] true if the expectation succeeds (else raises)
31
- # @see RSpec::Matchers
90
+ include InstanceMethods
91
+ end
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
32
99
  def to(matcher=nil, message=nil, &block)
33
- prevent_operator_matchers(:to, matcher)
34
- RSpec::Expectations::PositiveExpectationHandler.handle_matcher(@target, matcher, message, &block)
100
+ enforce_value_expectation(matcher)
101
+ super
35
102
  end
36
103
 
37
- # Runs the given expectation, passing if `matcher` returns false.
38
- # @example
39
- # expect(value).not_to eq(5)
40
- # @param [Matcher]
41
- # matcher
42
- # @param [String] message optional message to display when the expectation fails
43
- # @return [Boolean] false if the negative expectation succeeds (else raises)
44
- # @see RSpec::Matchers
45
104
  def not_to(matcher=nil, message=nil, &block)
46
- prevent_operator_matchers(:not_to, matcher)
47
- RSpec::Expectations::NegativeExpectationHandler.handle_matcher(@target, matcher, message, &block)
105
+ enforce_value_expectation(matcher)
106
+ super
48
107
  end
49
- alias to_not not_to
50
-
51
- def self.enable_deprecated_should
52
- return if deprecated_should_enabled?
53
108
 
54
- def should(*args)
55
- RSpec.deprecate "`expect { }.should`", :replacement => "`expect { }.to`"
56
- @target.should(*args)
57
- end
109
+ private
58
110
 
59
- def should_not(*args)
60
- RSpec.deprecate "`expect { }.should_not`", :replacement => "`expect { }.not_to`"
61
- @target.should_not(*args)
62
- end
111
+ def enforce_value_expectation(matcher)
112
+ return if supports_value_expectations?(matcher)
63
113
 
64
- self.deprecated_should_enabled = true
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
+ )
65
124
  end
66
125
 
67
- def self.disable_deprecated_should
68
- return unless deprecated_should_enabled?
126
+ def supports_value_expectations?(matcher)
127
+ !matcher.respond_to?(:supports_value_expectations?) || matcher.supports_value_expectations?
128
+ end
129
+ end
69
130
 
70
- remove_method :should
71
- remove_method :should_not
131
+ # @private
132
+ # Validates the provided matcher to ensure it supports block
133
+ # expectations, in order to avoid user confusion when they
134
+ # use a block thinking the expectation will be on the return
135
+ # value of the block rather than the block itself.
136
+ class BlockExpectationTarget < ExpectationTarget
137
+ def to(matcher, message=nil, &block)
138
+ enforce_block_expectation(matcher)
139
+ super
140
+ end
72
141
 
73
- self.deprecated_should_enabled = false
142
+ def not_to(matcher, message=nil, &block)
143
+ enforce_block_expectation(matcher)
144
+ super
74
145
  end
146
+ alias to_not not_to
75
147
 
76
148
  private
77
149
 
78
- def prevent_operator_matchers(verb, matcher)
79
- return if matcher
150
+ def enforce_block_expectation(matcher)
151
+ return if supports_block_expectations?(matcher)
80
152
 
81
- raise ArgumentError, "The expect syntax does not support operator matchers, " +
82
- "so you must pass a matcher to `##{verb}`."
153
+ raise ExpectationNotMetError, "You must pass an argument rather than a block to `expect` to use the provided " \
154
+ "matcher (#{RSpec::Support::ObjectFormatter.format(matcher)}), or the matcher must implement " \
155
+ "`supports_block_expectations?`."
156
+ end
157
+
158
+ def supports_block_expectations?(matcher)
159
+ matcher.respond_to?(:supports_block_expectations?) && matcher.supports_block_expectations?
83
160
  end
84
161
  end
85
162
  end
86
163
  end
87
-
@@ -1,9 +1,20 @@
1
1
  module RSpec
2
2
  module Expectations
3
3
  class << self
4
+ # @private
5
+ class Differ
6
+ # @private
7
+ OBJECT_PREPARER = lambda do |object|
8
+ RSpec::Matchers::Composable.surface_descriptions_in(object)
9
+ end
10
+ end
11
+
4
12
  # @private
5
13
  def differ
6
- @differ ||= Differ.new
14
+ RSpec::Support::Differ.new(
15
+ :object_preparer => Differ::OBJECT_PREPARER,
16
+ :color => RSpec::Matchers.configuration.color?
17
+ )
7
18
  end
8
19
 
9
20
  # Raises an RSpec::Expectations::ExpectationNotMetError with message.
@@ -14,65 +25,14 @@ module RSpec
14
25
  # Adds a diff to the failure message when `expected` and `actual` are
15
26
  # both present.
16
27
  def fail_with(message, expected=nil, actual=nil)
17
- if !message
18
- 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
28
+ unless message
29
+ raise ArgumentError, "Failure message is nil. Does your matcher define the " \
30
+ "appropriate failure_message[_when_negated] method to return a string?"
30
31
  end
31
32
 
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
33
+ message = ::RSpec::Matchers::MultiMatcherDiff.from(expected, actual).message_with_diff(message, differ)
44
34
 
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
- 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
65
- end
66
- end
67
-
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
35
+ RSpec::Support.notify_failure(RSpec::Expectations::ExpectationNotMetError.new message)
76
36
  end
77
37
  end
78
38
  end