rspec-expectations 2.11.3 → 3.11.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 (152) 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 +1026 -21
  6. data/{License.txt → LICENSE.md} +5 -3
  7. data/README.md +174 -78
  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 +130 -55
  11. data/lib/rspec/expectations/fail_with.rb +17 -33
  12. data/lib/rspec/expectations/failure_aggregator.rb +212 -0
  13. data/lib/rspec/expectations/handler.rb +163 -29
  14. data/lib/rspec/expectations/minitest_integration.rb +58 -0
  15. data/lib/rspec/expectations/syntax.rb +68 -54
  16. data/lib/rspec/expectations/version.rb +1 -1
  17. data/lib/rspec/expectations.rb +59 -24
  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 +150 -20
  21. data/lib/rspec/matchers/built_in/be.rb +115 -109
  22. data/lib/rspec/matchers/built_in/be_between.rb +77 -0
  23. data/lib/rspec/matchers/built_in/be_instance_of.rb +16 -1
  24. data/lib/rspec/matchers/built_in/be_kind_of.rb +10 -1
  25. data/lib/rspec/matchers/built_in/be_within.rb +43 -17
  26. data/lib/rspec/matchers/built_in/change.rb +392 -75
  27. data/lib/rspec/matchers/built_in/compound.rb +290 -0
  28. data/lib/rspec/matchers/built_in/contain_exactly.rb +302 -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 +26 -8
  32. data/lib/rspec/matchers/built_in/eql.rb +19 -8
  33. data/lib/rspec/matchers/built_in/equal.rb +56 -19
  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 +175 -20
  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 +212 -38
  42. data/lib/rspec/matchers/built_in/respond_to.rb +155 -29
  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 +252 -98
  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 +530 -10
  50. data/lib/rspec/matchers/english_phrasing.rb +58 -0
  51. data/lib/rspec/matchers/expecteds_for_multiple_diffs.rb +82 -0
  52. data/lib/rspec/matchers/fail_matchers.rb +42 -0
  53. data/lib/rspec/matchers/generated_descriptions.rb +15 -10
  54. data/lib/rspec/matchers/matcher_delegator.rb +35 -0
  55. data/lib/rspec/matchers/matcher_protocol.rb +105 -0
  56. data/lib/rspec/matchers.rb +604 -252
  57. data.tar.gz.sig +0 -0
  58. metadata +178 -278
  59. metadata.gz.sig +0 -0
  60. data/features/README.md +0 -49
  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 -173
  64. data/features/built_in_matchers/be_within.feature +0 -46
  65. data/features/built_in_matchers/cover.feature +0 -45
  66. data/features/built_in_matchers/end_with.feature +0 -46
  67. data/features/built_in_matchers/equality.feature +0 -145
  68. data/features/built_in_matchers/exist.feature +0 -43
  69. data/features/built_in_matchers/expect_change.feature +0 -59
  70. data/features/built_in_matchers/expect_error.feature +0 -138
  71. data/features/built_in_matchers/have.feature +0 -103
  72. data/features/built_in_matchers/include.feature +0 -121
  73. data/features/built_in_matchers/match.feature +0 -50
  74. data/features/built_in_matchers/operators.feature +0 -221
  75. data/features/built_in_matchers/predicates.feature +0 -128
  76. data/features/built_in_matchers/respond_to.feature +0 -78
  77. data/features/built_in_matchers/satisfy.feature +0 -31
  78. data/features/built_in_matchers/start_with.feature +0 -46
  79. data/features/built_in_matchers/throw_symbol.feature +0 -85
  80. data/features/built_in_matchers/types.feature +0 -114
  81. data/features/built_in_matchers/yield.feature +0 -146
  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 -340
  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 -5
  92. data/features/syntax_configuration.feature +0 -68
  93. data/features/test_frameworks/test_unit.feature +0 -46
  94. data/lib/rspec/expectations/deprecation.rb +0 -38
  95. data/lib/rspec/expectations/differ.rb +0 -81
  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 -39
  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 -108
  102. data/lib/rspec/matchers/built_in/match_array.rb +0 -45
  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 -66
  106. data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
  107. data/lib/rspec/matchers/matcher.rb +0 -299
  108. data/lib/rspec/matchers/method_missing.rb +0 -12
  109. data/lib/rspec/matchers/operator_matcher.rb +0 -84
  110. data/lib/rspec/matchers/pretty.rb +0 -60
  111. data/lib/rspec-expectations.rb +0 -1
  112. data/spec/rspec/expectations/differ_spec.rb +0 -153
  113. data/spec/rspec/expectations/expectation_target_spec.rb +0 -65
  114. data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
  115. data/spec/rspec/expectations/fail_with_spec.rb +0 -70
  116. data/spec/rspec/expectations/handler_spec.rb +0 -206
  117. data/spec/rspec/matchers/base_matcher_spec.rb +0 -60
  118. data/spec/rspec/matchers/be_close_spec.rb +0 -22
  119. data/spec/rspec/matchers/be_instance_of_spec.rb +0 -40
  120. data/spec/rspec/matchers/be_kind_of_spec.rb +0 -37
  121. data/spec/rspec/matchers/be_spec.rb +0 -452
  122. data/spec/rspec/matchers/be_within_spec.rb +0 -80
  123. data/spec/rspec/matchers/change_spec.rb +0 -528
  124. data/spec/rspec/matchers/configuration_spec.rb +0 -202
  125. data/spec/rspec/matchers/cover_spec.rb +0 -69
  126. data/spec/rspec/matchers/description_generation_spec.rb +0 -176
  127. data/spec/rspec/matchers/dsl_spec.rb +0 -57
  128. data/spec/rspec/matchers/eq_spec.rb +0 -54
  129. data/spec/rspec/matchers/eql_spec.rb +0 -41
  130. data/spec/rspec/matchers/equal_spec.rb +0 -60
  131. data/spec/rspec/matchers/exist_spec.rb +0 -110
  132. data/spec/rspec/matchers/has_spec.rb +0 -118
  133. data/spec/rspec/matchers/have_spec.rb +0 -461
  134. data/spec/rspec/matchers/include_spec.rb +0 -367
  135. data/spec/rspec/matchers/match_array_spec.rb +0 -124
  136. data/spec/rspec/matchers/match_spec.rb +0 -61
  137. data/spec/rspec/matchers/matcher_spec.rb +0 -434
  138. data/spec/rspec/matchers/matchers_spec.rb +0 -31
  139. data/spec/rspec/matchers/method_missing_spec.rb +0 -24
  140. data/spec/rspec/matchers/operator_matcher_spec.rb +0 -221
  141. data/spec/rspec/matchers/raise_error_spec.rb +0 -344
  142. data/spec/rspec/matchers/respond_to_spec.rb +0 -295
  143. data/spec/rspec/matchers/satisfy_spec.rb +0 -44
  144. data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -182
  145. data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
  146. data/spec/rspec/matchers/yield_spec.rb +0 -402
  147. data/spec/spec_helper.rb +0 -27
  148. data/spec/support/classes.rb +0 -56
  149. data/spec/support/in_sub_process.rb +0 -31
  150. data/spec/support/matchers.rb +0 -22
  151. data/spec/support/ruby_version.rb +0 -10
  152. 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,88 +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
- # # 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
- # @api private
19
- def initialize(target)
20
- @target = target
21
- end
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
22
29
 
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
32
- def to(matcher=nil, message=nil, &block)
33
- prevent_operator_matchers(:to, matcher)
34
- RSpec::Expectations::PositiveExpectationHandler.handle_matcher(@target, matcher, message, &block)
30
+ # @api private
31
+ def initialize(value)
32
+ @target = value
35
33
  end
36
34
 
37
- # Runs the given expectation, passing if `matcher` returns false.
38
- # @example
39
- # expect(value).to_not eq(5)
40
- # expect(value).not_to eq(5)
41
- # @param [Matcher]
42
- # matcher
43
- # @param [String] message optional message to display when the expectation fails
44
- # @return [Boolean] false if the negative expectation succeeds (else raises)
45
- # @see RSpec::Matchers
46
- def to_not(matcher=nil, message=nil, &block)
47
- prevent_operator_matchers(:to_not, matcher)
48
- RSpec::Expectations::NegativeExpectationHandler.handle_matcher(@target, matcher, message, &block)
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
49
47
  end
50
- alias not_to to_not
51
48
 
52
- def self.enable_deprecated_should
53
- return if deprecated_should_enabled?
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
54
67
 
55
- def should(*args)
56
- RSpec.deprecate "`expect { }.should`", "`expect { }.to`", 3
57
- @target.should(*args)
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)
58
79
  end
80
+ alias to_not not_to
59
81
 
60
- def should_not(*args)
61
- RSpec.deprecate "`expect { }.should_not`", "`expect { }.to_not`", 3
62
- @target.should_not(*args)
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}`."
63
87
  end
88
+ end
64
89
 
65
- self.deprecated_should_enabled = true
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
99
+ def to(matcher=nil, message=nil, &block)
100
+ enforce_value_expectation(matcher)
101
+ super
66
102
  end
67
103
 
68
- def self.disable_deprecated_should
69
- return unless deprecated_should_enabled?
104
+ def not_to(matcher=nil, message=nil, &block)
105
+ enforce_value_expectation(matcher)
106
+ super
107
+ end
108
+
109
+ private
70
110
 
71
- remove_method :should
72
- remove_method :should_not
111
+ def enforce_value_expectation(matcher)
112
+ return if supports_value_expectations?(matcher)
73
113
 
74
- self.deprecated_should_enabled = false
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
+ )
75
124
  end
76
125
 
126
+ def supports_value_expectations?(matcher)
127
+ !matcher.respond_to?(:supports_value_expectations?) || matcher.supports_value_expectations?
128
+ end
129
+ end
130
+
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
141
+
142
+ def not_to(matcher, message=nil, &block)
143
+ enforce_block_expectation(matcher)
144
+ super
145
+ end
146
+ alias to_not not_to
147
+
77
148
  private
78
149
 
79
- def prevent_operator_matchers(verb, matcher)
80
- return if matcher
150
+ def enforce_block_expectation(matcher)
151
+ return if supports_block_expectations?(matcher)
81
152
 
82
- raise ArgumentError, "The expect syntax does not support operator matchers, " +
83
- "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?
84
160
  end
85
161
  end
86
162
  end
87
163
  end
88
-
@@ -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,41 +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?"
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?"
20
31
  end
21
32
 
22
- if actual && expected
23
- if all_strings?(actual, expected)
24
- if any_multiline_strings?(actual, expected)
25
- expected = expected.join(',') if Array === expected
26
- message << "\nDiff:" << differ.diff_as_string(actual, expected)
27
- end
28
- elsif no_procs?(actual, expected) && no_numbers?(actual, expected)
29
- message << "\nDiff:" << differ.diff_as_object(actual, expected)
30
- end
31
- end
32
-
33
- raise(RSpec::Expectations::ExpectationNotMetError.new(message))
34
- end
35
-
36
- private
37
-
38
- def no_procs?(*args)
39
- args.flatten.none? {|a| Proc === a}
40
- end
41
-
42
- def all_strings?(*args)
43
- args.flatten.all? {|a| String === a}
44
- end
45
-
46
- def any_multiline_strings?(*args)
47
- all_strings?(*args) && args.any? {|a| a =~ /\n/}
48
- end
33
+ message = ::RSpec::Matchers::ExpectedsForMultipleDiffs.from(expected).message_with_diff(message, differ, actual)
49
34
 
50
- def no_numbers?(*args)
51
- args.flatten.none? {|a| Numeric === a}
35
+ RSpec::Support.notify_failure(RSpec::Expectations::ExpectationNotMetError.new message)
52
36
  end
53
37
  end
54
38
  end