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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.document +1 -1
- data/.yardopts +1 -1
- data/Changelog.md +976 -25
- data/{License.txt → LICENSE.md} +5 -3
- data/README.md +162 -26
- data/lib/rspec/expectations/block_snippet_extractor.rb +253 -0
- data/lib/rspec/expectations/configuration.rb +230 -0
- data/lib/rspec/expectations/expectation_target.rb +127 -51
- data/lib/rspec/expectations/fail_with.rb +17 -57
- data/lib/rspec/expectations/failure_aggregator.rb +229 -0
- data/lib/rspec/expectations/handler.rb +146 -32
- data/lib/rspec/expectations/minitest_integration.rb +58 -0
- data/lib/rspec/expectations/syntax.rb +68 -100
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/expectations.rb +58 -23
- data/lib/rspec/matchers/aliased_matcher.rb +116 -0
- data/lib/rspec/matchers/built_in/all.rb +86 -0
- data/lib/rspec/matchers/built_in/base_matcher.rb +191 -20
- data/lib/rspec/matchers/built_in/be.rb +114 -114
- data/lib/rspec/matchers/built_in/be_between.rb +77 -0
- data/lib/rspec/matchers/built_in/be_instance_of.rb +15 -4
- data/lib/rspec/matchers/built_in/be_kind_of.rb +10 -1
- data/lib/rspec/matchers/built_in/be_within.rb +35 -18
- data/lib/rspec/matchers/built_in/change.rb +389 -80
- data/lib/rspec/matchers/built_in/compound.rb +290 -0
- data/lib/rspec/matchers/built_in/contain_exactly.rb +310 -0
- data/lib/rspec/matchers/built_in/count_expectation.rb +169 -0
- data/lib/rspec/matchers/built_in/cover.rb +3 -0
- data/lib/rspec/matchers/built_in/eq.rb +30 -8
- data/lib/rspec/matchers/built_in/eql.rb +23 -8
- data/lib/rspec/matchers/built_in/equal.rb +55 -22
- data/lib/rspec/matchers/built_in/exist.rb +74 -10
- data/lib/rspec/matchers/built_in/has.rb +141 -22
- data/lib/rspec/matchers/built_in/have_attributes.rb +114 -0
- data/lib/rspec/matchers/built_in/include.rb +184 -32
- data/lib/rspec/matchers/built_in/match.rb +95 -1
- data/lib/rspec/matchers/built_in/operators.rb +128 -0
- data/lib/rspec/matchers/built_in/output.rb +207 -0
- data/lib/rspec/matchers/built_in/raise_error.rb +192 -44
- data/lib/rspec/matchers/built_in/respond_to.rb +154 -28
- data/lib/rspec/matchers/built_in/satisfy.rb +39 -9
- data/lib/rspec/matchers/built_in/start_or_end_with.rb +94 -0
- data/lib/rspec/matchers/built_in/throw_symbol.rb +58 -14
- data/lib/rspec/matchers/built_in/yield.rb +240 -161
- data/lib/rspec/matchers/built_in.rb +47 -33
- data/lib/rspec/matchers/composable.rb +171 -0
- data/lib/rspec/matchers/dsl.rb +531 -10
- data/lib/rspec/matchers/english_phrasing.rb +58 -0
- data/lib/rspec/matchers/fail_matchers.rb +42 -0
- data/lib/rspec/matchers/generated_descriptions.rb +14 -8
- data/lib/rspec/matchers/matcher_delegator.rb +61 -0
- data/lib/rspec/matchers/matcher_protocol.rb +105 -0
- data/lib/rspec/matchers/multi_matcher_diff.rb +82 -0
- data/lib/rspec/matchers.rb +520 -173
- data.tar.gz.sig +0 -0
- metadata +141 -242
- metadata.gz.sig +2 -0
- data/features/README.md +0 -48
- data/features/Upgrade.md +0 -53
- data/features/built_in_matchers/README.md +0 -90
- data/features/built_in_matchers/be.feature +0 -175
- data/features/built_in_matchers/be_within.feature +0 -48
- data/features/built_in_matchers/cover.feature +0 -47
- data/features/built_in_matchers/end_with.feature +0 -48
- data/features/built_in_matchers/equality.feature +0 -139
- data/features/built_in_matchers/exist.feature +0 -45
- data/features/built_in_matchers/expect_change.feature +0 -59
- data/features/built_in_matchers/expect_error.feature +0 -144
- data/features/built_in_matchers/have.feature +0 -109
- data/features/built_in_matchers/include.feature +0 -174
- data/features/built_in_matchers/match.feature +0 -52
- data/features/built_in_matchers/operators.feature +0 -227
- data/features/built_in_matchers/predicates.feature +0 -137
- data/features/built_in_matchers/respond_to.feature +0 -84
- data/features/built_in_matchers/satisfy.feature +0 -33
- data/features/built_in_matchers/start_with.feature +0 -48
- data/features/built_in_matchers/throw_symbol.feature +0 -91
- data/features/built_in_matchers/types.feature +0 -116
- data/features/built_in_matchers/yield.feature +0 -161
- data/features/custom_matchers/access_running_example.feature +0 -53
- data/features/custom_matchers/define_diffable_matcher.feature +0 -27
- data/features/custom_matchers/define_matcher.feature +0 -368
- data/features/custom_matchers/define_matcher_outside_rspec.feature +0 -38
- data/features/custom_matchers/define_matcher_with_fluent_interface.feature +0 -24
- data/features/customized_message.feature +0 -22
- data/features/diffing.feature +0 -85
- data/features/implicit_docstrings.feature +0 -52
- data/features/step_definitions/additional_cli_steps.rb +0 -22
- data/features/support/env.rb +0 -14
- data/features/syntax_configuration.feature +0 -71
- data/features/test_frameworks/test_unit.feature +0 -44
- data/lib/rspec/expectations/deprecation.rb +0 -17
- data/lib/rspec/expectations/differ.rb +0 -133
- data/lib/rspec/expectations/errors.rb +0 -9
- data/lib/rspec/expectations/extensions/array.rb +0 -9
- data/lib/rspec/expectations/extensions/object.rb +0 -29
- data/lib/rspec/expectations/extensions.rb +0 -2
- data/lib/rspec/matchers/be_close.rb +0 -9
- data/lib/rspec/matchers/built_in/have.rb +0 -124
- data/lib/rspec/matchers/built_in/match_array.rb +0 -51
- data/lib/rspec/matchers/built_in/start_and_end_with.rb +0 -48
- data/lib/rspec/matchers/compatibility.rb +0 -14
- data/lib/rspec/matchers/configuration.rb +0 -108
- data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
- data/lib/rspec/matchers/matcher.rb +0 -300
- data/lib/rspec/matchers/method_missing.rb +0 -12
- data/lib/rspec/matchers/operator_matcher.rb +0 -109
- data/lib/rspec/matchers/pretty.rb +0 -70
- data/lib/rspec/matchers/test_unit_integration.rb +0 -11
- data/lib/rspec-expectations.rb +0 -1
- data/spec/rspec/expectations/differ_spec.rb +0 -192
- data/spec/rspec/expectations/expectation_target_spec.rb +0 -82
- data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
- data/spec/rspec/expectations/fail_with_spec.rb +0 -114
- data/spec/rspec/expectations/handler_spec.rb +0 -227
- data/spec/rspec/expectations/syntax_spec.rb +0 -139
- data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
- data/spec/rspec/matchers/be_close_spec.rb +0 -22
- data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
- data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
- data/spec/rspec/matchers/be_spec.rb +0 -516
- data/spec/rspec/matchers/be_within_spec.rb +0 -137
- data/spec/rspec/matchers/change_spec.rb +0 -553
- data/spec/rspec/matchers/configuration_spec.rb +0 -206
- data/spec/rspec/matchers/cover_spec.rb +0 -69
- data/spec/rspec/matchers/description_generation_spec.rb +0 -190
- data/spec/rspec/matchers/dsl_spec.rb +0 -57
- data/spec/rspec/matchers/eq_spec.rb +0 -60
- data/spec/rspec/matchers/eql_spec.rb +0 -41
- data/spec/rspec/matchers/equal_spec.rb +0 -78
- data/spec/rspec/matchers/exist_spec.rb +0 -124
- data/spec/rspec/matchers/has_spec.rb +0 -122
- data/spec/rspec/matchers/have_spec.rb +0 -455
- data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
- data/spec/rspec/matchers/include_spec.rb +0 -531
- data/spec/rspec/matchers/match_array_spec.rb +0 -194
- data/spec/rspec/matchers/match_spec.rb +0 -61
- data/spec/rspec/matchers/matcher_spec.rb +0 -471
- data/spec/rspec/matchers/matchers_spec.rb +0 -37
- data/spec/rspec/matchers/method_missing_spec.rb +0 -28
- data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
- data/spec/rspec/matchers/raise_error_spec.rb +0 -485
- data/spec/rspec/matchers/respond_to_spec.rb +0 -292
- data/spec/rspec/matchers/satisfy_spec.rb +0 -44
- data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
- data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
- data/spec/rspec/matchers/yield_spec.rb +0 -514
- data/spec/spec_helper.rb +0 -54
- data/spec/support/classes.rb +0 -56
- data/spec/support/in_sub_process.rb +0 -38
- data/spec/support/matchers.rb +0 -22
- data/spec/support/ruby_version.rb +0 -10
- data/spec/support/shared_examples.rb +0 -13
@@ -1,300 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module RSpec
|
4
|
-
module Matchers
|
5
|
-
module DSL
|
6
|
-
# Provides the context in which the block passed to RSpec::Matchers.define
|
7
|
-
# will be evaluated.
|
8
|
-
class Matcher
|
9
|
-
include RSpec::Matchers::Extensions::InstanceEvalWithArgs
|
10
|
-
include RSpec::Matchers::Pretty
|
11
|
-
include RSpec::Matchers
|
12
|
-
|
13
|
-
attr_reader :expected, :actual, :rescued_exception
|
14
|
-
attr_accessor :matcher_execution_context
|
15
|
-
|
16
|
-
# @api private
|
17
|
-
def initialize(name, &declarations)
|
18
|
-
@name = name
|
19
|
-
@declarations = declarations
|
20
|
-
@actual = nil
|
21
|
-
@diffable = false
|
22
|
-
@expected_exception, @rescued_exception = nil, nil
|
23
|
-
@match_for_should_not_block = nil
|
24
|
-
@messages = {}
|
25
|
-
end
|
26
|
-
|
27
|
-
PERSISTENT_INSTANCE_VARIABLES = [
|
28
|
-
:@name, :@declarations, :@diffable,
|
29
|
-
:@match_block, :@match_for_should_not_block,
|
30
|
-
:@expected_exception
|
31
|
-
].to_set
|
32
|
-
|
33
|
-
# @api private
|
34
|
-
def for_expected(*expected)
|
35
|
-
@expected = expected
|
36
|
-
dup.instance_eval do
|
37
|
-
instance_variables.map {|ivar| ivar.intern}.each do |ivar|
|
38
|
-
instance_variable_set(ivar, nil) unless (PERSISTENT_INSTANCE_VARIABLES + [:@expected]).include?(ivar)
|
39
|
-
end
|
40
|
-
@messages = {}
|
41
|
-
making_declared_methods_public do
|
42
|
-
instance_eval_with_args(*@expected, &@declarations)
|
43
|
-
end
|
44
|
-
self
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# @api private
|
49
|
-
# Used internally by +should+ and +should_not+.
|
50
|
-
def matches?(actual)
|
51
|
-
@actual = actual
|
52
|
-
if @expected_exception
|
53
|
-
begin
|
54
|
-
instance_eval_with_args(actual, &@match_block)
|
55
|
-
true
|
56
|
-
rescue @expected_exception => @rescued_exception
|
57
|
-
false
|
58
|
-
end
|
59
|
-
else
|
60
|
-
begin
|
61
|
-
instance_eval_with_args(actual, &@match_block)
|
62
|
-
rescue RSpec::Expectations::ExpectationNotMetError
|
63
|
-
false
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Stores the block that is used to determine whether this matcher passes
|
69
|
-
# or fails. The block should return a boolean value. When the matcher is
|
70
|
-
# passed to `should` and the block returns `true`, then the expectation
|
71
|
-
# passes. Similarly, when the matcher is passed to `should_not` and the
|
72
|
-
# block returns `false`, then the expectation passes.
|
73
|
-
#
|
74
|
-
# Use `match_for_should` when used in conjuntion with
|
75
|
-
# `match_for_should_not`.
|
76
|
-
#
|
77
|
-
# @example
|
78
|
-
#
|
79
|
-
# RSpec::Matchers.define :be_even do
|
80
|
-
# match do |actual|
|
81
|
-
# actual.even?
|
82
|
-
# end
|
83
|
-
# end
|
84
|
-
#
|
85
|
-
# 4.should be_even # passes
|
86
|
-
# 3.should_not be_even # passes
|
87
|
-
# 3.should be_even # fails
|
88
|
-
# 4.should_not be_even # fails
|
89
|
-
#
|
90
|
-
# @yield [Object] actual the actual value (or receiver of should)
|
91
|
-
def match(&block)
|
92
|
-
@match_block = block
|
93
|
-
end
|
94
|
-
|
95
|
-
alias_method :match_for_should, :match
|
96
|
-
|
97
|
-
# Use this to define the block for a negative expectation (`should_not`)
|
98
|
-
# when the positive and negative forms require different handling. This
|
99
|
-
# is rarely necessary, but can be helpful, for example, when specifying
|
100
|
-
# asynchronous processes that require different timeouts.
|
101
|
-
#
|
102
|
-
# @yield [Object] actual the actual value (or receiver of should)
|
103
|
-
def match_for_should_not(&block)
|
104
|
-
@match_for_should_not_block = block
|
105
|
-
end
|
106
|
-
|
107
|
-
# Use this instead of `match` when the block will raise an exception
|
108
|
-
# rather than returning false to indicate a failure.
|
109
|
-
#
|
110
|
-
# @example
|
111
|
-
#
|
112
|
-
# RSpec::Matchers.define :accept_as_valid do |candidate_address|
|
113
|
-
# match_unless_raises ValidationException do |validator|
|
114
|
-
# validator.validate(candidate_address)
|
115
|
-
# end
|
116
|
-
# end
|
117
|
-
#
|
118
|
-
# email_validator.should accept_as_valid("person@company.com")
|
119
|
-
def match_unless_raises(exception=Exception, &block)
|
120
|
-
@expected_exception = exception
|
121
|
-
match(&block)
|
122
|
-
end
|
123
|
-
|
124
|
-
# Customize the failure messsage to use when this matcher is invoked with
|
125
|
-
# `should`. Only use this when the message generated by default doesn't
|
126
|
-
# suit your needs.
|
127
|
-
#
|
128
|
-
# @example
|
129
|
-
#
|
130
|
-
# RSpec::Matchers.define :have_strength do |expected|
|
131
|
-
# match { ... }
|
132
|
-
#
|
133
|
-
# failure_message_for_should do |actual|
|
134
|
-
# "Expected strength of #{expected}, but had #{actual.strength}"
|
135
|
-
# end
|
136
|
-
# end
|
137
|
-
#
|
138
|
-
# @yield [Object] actual the actual object
|
139
|
-
def failure_message_for_should(&block)
|
140
|
-
cache_or_call_cached(:failure_message_for_should, &block)
|
141
|
-
end
|
142
|
-
|
143
|
-
# Customize the failure messsage to use when this matcher is invoked with
|
144
|
-
# `should_not`. Only use this when the message generated by default
|
145
|
-
# doesn't suit your needs.
|
146
|
-
#
|
147
|
-
# @example
|
148
|
-
#
|
149
|
-
# RSpec::Matchers.define :have_strength do |expected|
|
150
|
-
# match { ... }
|
151
|
-
#
|
152
|
-
# failure_message_for_should_not do |actual|
|
153
|
-
# "Expected not to have strength of #{expected}, but did"
|
154
|
-
# end
|
155
|
-
# end
|
156
|
-
#
|
157
|
-
# @yield [Object] actual the actual object
|
158
|
-
# @yield [Object] actual the actual object
|
159
|
-
def failure_message_for_should_not(&block)
|
160
|
-
cache_or_call_cached(:failure_message_for_should_not, &block)
|
161
|
-
end
|
162
|
-
|
163
|
-
|
164
|
-
# Customize the description to use for one-liners. Only use this when
|
165
|
-
# the description generated by default doesn't suit your needs.
|
166
|
-
#
|
167
|
-
# @example
|
168
|
-
#
|
169
|
-
# RSpec::Matchers.define :qualify_for do |expected|
|
170
|
-
# match { ... }
|
171
|
-
#
|
172
|
-
# description do
|
173
|
-
# "qualify for #{expected}"
|
174
|
-
# end
|
175
|
-
# end
|
176
|
-
def description(&block)
|
177
|
-
cache_or_call_cached(:description, &block)
|
178
|
-
end
|
179
|
-
|
180
|
-
# Tells the matcher to diff the actual and expected values in the failure
|
181
|
-
# message.
|
182
|
-
def diffable
|
183
|
-
@diffable = true
|
184
|
-
end
|
185
|
-
|
186
|
-
# Convenience for defining methods on this matcher to create a fluent
|
187
|
-
# interface. The trick about fluent interfaces is that each method must
|
188
|
-
# return self in order to chain methods together. `chain` handles that
|
189
|
-
# for you.
|
190
|
-
#
|
191
|
-
# @example
|
192
|
-
#
|
193
|
-
# RSpec::Matchers.define :have_errors_on do |key|
|
194
|
-
# chain :with do |message|
|
195
|
-
# @message = message
|
196
|
-
# end
|
197
|
-
#
|
198
|
-
# match do |actual|
|
199
|
-
# actual.errors[key] == @message
|
200
|
-
# end
|
201
|
-
# end
|
202
|
-
#
|
203
|
-
# minor.should have_errors_on(:age).with("Not old enough to participate")
|
204
|
-
def chain(method, &block)
|
205
|
-
define_method method do |*args|
|
206
|
-
block.call(*args)
|
207
|
-
self
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
# @api private
|
212
|
-
# Used internally by objects returns by +should+ and +should_not+.
|
213
|
-
def diffable?
|
214
|
-
@diffable
|
215
|
-
end
|
216
|
-
|
217
|
-
# @api private
|
218
|
-
# Used internally by +should_not+
|
219
|
-
def does_not_match?(actual)
|
220
|
-
@actual = actual
|
221
|
-
@match_for_should_not_block ?
|
222
|
-
instance_eval_with_args(actual, &@match_for_should_not_block) :
|
223
|
-
!matches?(actual)
|
224
|
-
end
|
225
|
-
|
226
|
-
def respond_to?(method, include_private=false)
|
227
|
-
super || matcher_execution_context.respond_to?(method, include_private)
|
228
|
-
end
|
229
|
-
|
230
|
-
private
|
231
|
-
|
232
|
-
def method_missing(method, *args, &block)
|
233
|
-
if matcher_execution_context.respond_to?(method)
|
234
|
-
matcher_execution_context.__send__ method, *args, &block
|
235
|
-
else
|
236
|
-
super(method, *args, &block)
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
def include(*args)
|
241
|
-
singleton_class.__send__(:include, *args)
|
242
|
-
end
|
243
|
-
|
244
|
-
def define_method(name, &block)
|
245
|
-
singleton_class.__send__(:define_method, name, &block)
|
246
|
-
end
|
247
|
-
|
248
|
-
def making_declared_methods_public
|
249
|
-
# Our home-grown instance_exec in ruby 1.8.6 results in any methods
|
250
|
-
# declared in the block eval'd by instance_exec in the block to which we
|
251
|
-
# are yielding here are scoped private. This is NOT the case for Ruby
|
252
|
-
# 1.8.7 or 1.9.
|
253
|
-
#
|
254
|
-
# Also, due some crazy scoping that I don't understand, these methods
|
255
|
-
# are actually available in the specs (something about the matcher being
|
256
|
-
# defined in the scope of RSpec::Matchers or within an example), so not
|
257
|
-
# doing the following will not cause specs to fail, but they *will*
|
258
|
-
# cause features to fail and that will make users unhappy. So don't.
|
259
|
-
orig_private_methods = private_methods
|
260
|
-
yield
|
261
|
-
(private_methods - orig_private_methods).each {|m| singleton_class.__send__ :public, m}
|
262
|
-
end
|
263
|
-
|
264
|
-
def cache_or_call_cached(key, &block)
|
265
|
-
block ? cache(key, &block) : call_cached(key)
|
266
|
-
end
|
267
|
-
|
268
|
-
def cache(key, &block)
|
269
|
-
@messages[key] = block
|
270
|
-
end
|
271
|
-
|
272
|
-
def call_cached(key)
|
273
|
-
if @messages.has_key?(key)
|
274
|
-
@messages[key].arity == 1 ? @messages[key].call(@actual) : @messages[key].call
|
275
|
-
else
|
276
|
-
__send__("default_#{key}")
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
def default_description
|
281
|
-
"#{name_to_sentence}#{expected_to_sentence}"
|
282
|
-
end
|
283
|
-
|
284
|
-
def default_failure_message_for_should
|
285
|
-
"expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"
|
286
|
-
end
|
287
|
-
|
288
|
-
def default_failure_message_for_should_not
|
289
|
-
"expected #{actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"
|
290
|
-
end
|
291
|
-
|
292
|
-
unless method_defined?(:singleton_class)
|
293
|
-
def singleton_class
|
294
|
-
class << self; self; end
|
295
|
-
end
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
module RSpec
|
2
|
-
module Matchers
|
3
|
-
|
4
|
-
private
|
5
|
-
|
6
|
-
def method_missing(method, *args, &block)
|
7
|
-
return Matchers::BuiltIn::BePredicate.new(method, *args, &block) if method.to_s =~ /^be_/
|
8
|
-
return Matchers::BuiltIn::Has.new(method, *args, &block) if method.to_s =~ /^have_/
|
9
|
-
super
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
@@ -1,109 +0,0 @@
|
|
1
|
-
module RSpec
|
2
|
-
module Matchers
|
3
|
-
class OperatorMatcher
|
4
|
-
class << self
|
5
|
-
def registry
|
6
|
-
@registry ||= {}
|
7
|
-
end
|
8
|
-
|
9
|
-
def register(klass, operator, matcher)
|
10
|
-
registry[klass] ||= {}
|
11
|
-
registry[klass][operator] = matcher
|
12
|
-
end
|
13
|
-
|
14
|
-
def unregister(klass, operator)
|
15
|
-
registry[klass] && registry[klass].delete(operator)
|
16
|
-
end
|
17
|
-
|
18
|
-
def get(klass, operator)
|
19
|
-
klass.ancestors.each { |ancestor|
|
20
|
-
matcher = registry[ancestor] && registry[ancestor][operator]
|
21
|
-
return matcher if matcher
|
22
|
-
}
|
23
|
-
|
24
|
-
nil
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize(actual)
|
29
|
-
@actual = actual
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.use_custom_matcher_or_delegate(operator)
|
33
|
-
define_method(operator) do |expected|
|
34
|
-
if uses_generic_implementation_of?(operator) && matcher = OperatorMatcher.get(@actual.class, operator)
|
35
|
-
@actual.__send__(::RSpec::Matchers.last_should, matcher.new(expected))
|
36
|
-
else
|
37
|
-
eval_match(@actual, operator, expected)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
negative_operator = operator.sub(/^=/, '!')
|
42
|
-
if negative_operator != operator && respond_to?(negative_operator)
|
43
|
-
define_method(negative_operator) do |expected|
|
44
|
-
opposite_should = ::RSpec::Matchers.last_should == :should ? :should_not : :should
|
45
|
-
raise "RSpec does not support `#{::RSpec::Matchers.last_should} #{negative_operator} expected`. " +
|
46
|
-
"Use `#{opposite_should} #{operator} expected` instead."
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
['==', '===', '=~', '>', '>=', '<', '<='].each do |operator|
|
52
|
-
use_custom_matcher_or_delegate operator
|
53
|
-
end
|
54
|
-
|
55
|
-
def fail_with_message(message)
|
56
|
-
RSpec::Expectations.fail_with(message, @expected, @actual)
|
57
|
-
end
|
58
|
-
|
59
|
-
def description
|
60
|
-
"#{@operator} #{@expected.inspect}"
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
if Method.method_defined?(:owner) # 1.8.6 lacks Method#owner :-(
|
66
|
-
def uses_generic_implementation_of?(op)
|
67
|
-
@actual.method(op).owner == ::Kernel
|
68
|
-
end
|
69
|
-
else
|
70
|
-
def uses_generic_implementation_of?(op)
|
71
|
-
# This is a bit of a hack, but:
|
72
|
-
#
|
73
|
-
# {}.method(:=~).to_s # => "#<Method: Hash(Kernel)#=~>"
|
74
|
-
#
|
75
|
-
# In the absence of Method#owner, this is the best we
|
76
|
-
# can do to see if the method comes from Kernel.
|
77
|
-
@actual.method(op).to_s.include?('(Kernel)')
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def eval_match(actual, operator, expected)
|
82
|
-
::RSpec::Matchers.last_matcher = self
|
83
|
-
@operator, @expected = operator, expected
|
84
|
-
__delegate_operator(actual, operator, expected)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
module BuiltIn
|
89
|
-
class PositiveOperatorMatcher < OperatorMatcher
|
90
|
-
def __delegate_operator(actual, operator, expected)
|
91
|
-
if actual.__send__(operator, expected)
|
92
|
-
true
|
93
|
-
elsif ['==','===', '=~'].include?(operator)
|
94
|
-
fail_with_message("expected: #{expected.inspect}\n got: #{actual.inspect} (using #{operator})")
|
95
|
-
else
|
96
|
-
fail_with_message("expected: #{operator} #{expected.inspect}\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}")
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
class NegativeOperatorMatcher < OperatorMatcher
|
102
|
-
def __delegate_operator(actual, operator, expected)
|
103
|
-
return false unless actual.__send__(operator, expected)
|
104
|
-
return fail_with_message("expected not: #{operator} #{expected.inspect}\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}")
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
module RSpec
|
2
|
-
module Matchers
|
3
|
-
module Pretty
|
4
|
-
def split_words(sym)
|
5
|
-
sym.to_s.gsub(/_/,' ')
|
6
|
-
end
|
7
|
-
|
8
|
-
def to_sentence(words)
|
9
|
-
return "" unless words
|
10
|
-
words = Array(words).map { |w| to_word(w) }
|
11
|
-
case words.length
|
12
|
-
when 0
|
13
|
-
""
|
14
|
-
when 1
|
15
|
-
" #{words[0]}"
|
16
|
-
when 2
|
17
|
-
" #{words[0]} and #{words[1]}"
|
18
|
-
else
|
19
|
-
" #{words[0...-1].join(', ')}, and #{words[-1]}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
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
|
-
|
37
|
-
def to_word(item)
|
38
|
-
is_matcher_with_description?(item) ? item.description : item.inspect
|
39
|
-
end
|
40
|
-
|
41
|
-
def name_to_sentence
|
42
|
-
split_words(name)
|
43
|
-
end
|
44
|
-
|
45
|
-
def expected_to_sentence
|
46
|
-
to_sentence(@expected) if defined?(@expected)
|
47
|
-
end
|
48
|
-
|
49
|
-
def name
|
50
|
-
defined?(@name) ? @name : underscore(self.class.name.split("::").last)
|
51
|
-
end
|
52
|
-
|
53
|
-
# Borrowed from ActiveSupport
|
54
|
-
def underscore(camel_cased_word)
|
55
|
-
word = camel_cased_word.to_s.dup
|
56
|
-
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
57
|
-
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
58
|
-
word.tr!("-", "_")
|
59
|
-
word.downcase!
|
60
|
-
word
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def is_matcher_with_description?(object)
|
66
|
-
RSpec::Matchers.is_a_matcher?(object) && object.respond_to?(:description)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
# Include Matchers for other test frameworks. Note that MiniTest _must_
|
2
|
-
# come before TU because on ruby 1.9, T::U::TC is a subclass of MT::U::TC
|
3
|
-
# and a 1.9 bug can lead to infinite recursion from the `super` call in our
|
4
|
-
# method_missing hook. See this gist for more info:
|
5
|
-
# https://gist.github.com/845896
|
6
|
-
if defined?(MiniTest::Unit::TestCase)
|
7
|
-
MiniTest::Unit::TestCase.send(:include, RSpec::Matchers)
|
8
|
-
end
|
9
|
-
if defined?(Test::Unit::TestCase)
|
10
|
-
Test::Unit::TestCase.send(:include, RSpec::Matchers)
|
11
|
-
end
|
data/lib/rspec-expectations.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "rspec/expectations"
|
@@ -1,192 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'spec_helper'
|
3
|
-
require 'ostruct'
|
4
|
-
|
5
|
-
module RSpec
|
6
|
-
module Expectations
|
7
|
-
describe Differ do
|
8
|
-
context "without --color" do
|
9
|
-
|
10
|
-
before { RSpec::Matchers.configuration.stub(:color? => false) }
|
11
|
-
|
12
|
-
let(:differ) { RSpec::Expectations::Differ.new }
|
13
|
-
|
14
|
-
# color disabled context
|
15
|
-
|
16
|
-
describe '#diff_as_string' do
|
17
|
-
subject { differ.diff_as_string(@expected, @actual) }
|
18
|
-
it "outputs unified diff of two strings" do
|
19
|
-
@expected="foo\nbar\nzap\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nline\n"
|
20
|
-
@actual="foo\nzap\nbar\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nanother\nline\n"
|
21
|
-
expect(subject).to eql(<<-'EOD')
|
22
|
-
|
23
|
-
|
24
|
-
@@ -1,6 +1,6 @@
|
25
|
-
foo
|
26
|
-
-zap
|
27
|
-
bar
|
28
|
-
+zap
|
29
|
-
this
|
30
|
-
is
|
31
|
-
soo
|
32
|
-
@@ -9,6 +9,5 @@
|
33
|
-
equal
|
34
|
-
insert
|
35
|
-
a
|
36
|
-
-another
|
37
|
-
line
|
38
|
-
EOD
|
39
|
-
|
40
|
-
end
|
41
|
-
if RUBY_VERSION.to_f > 1.9
|
42
|
-
it 'copes with encoded strings', :pending => (Diff::LCS::VERSION < '1.2.2') do
|
43
|
-
@expected="Tu avec carté {count} itém has".encode('UTF-16LE')
|
44
|
-
@actual="Tu avec carte {count} item has".encode('UTF-16LE')
|
45
|
-
expect(subject).to eql(<<-EOD.encode('UTF-16LE'))
|
46
|
-
|
47
|
-
@@ -1,2 +1,2 @@
|
48
|
-
-Tu avec carte {count} item has
|
49
|
-
+Tu avec carté {count} itém has
|
50
|
-
EOD
|
51
|
-
end
|
52
|
-
it 'copes with encoded strings', :pending => (Diff::LCS::VERSION >= '1.2.2') do
|
53
|
-
@expected="Tu avec carté {count} itém has".encode('UTF-16LE')
|
54
|
-
@actual="Tu avec carte {count} item has".encode('UTF-16LE')
|
55
|
-
expect(subject).to eql 'Could not produce a diff because of the encoding of the string (UTF-16LE)'
|
56
|
-
end
|
57
|
-
it 'ouputs a message when encountering differently encoded strings' do
|
58
|
-
@expected="Tu avec carté {count} itém has".encode('UTF-16LE')
|
59
|
-
@actual="Tu avec carte {count} item has"
|
60
|
-
expect(subject).to eql 'Could not produce a diff because the encoding of the actual string (UTF-8) differs from the encoding of the expected string (UTF-16LE)'
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe '#diff_as_object' do
|
66
|
-
it "outputs unified diff message of two objects" do
|
67
|
-
animal_class = Class.new do
|
68
|
-
def initialize(name, species)
|
69
|
-
@name, @species = name, species
|
70
|
-
end
|
71
|
-
|
72
|
-
def inspect
|
73
|
-
<<-EOA
|
74
|
-
<Animal
|
75
|
-
name=#{@name},
|
76
|
-
species=#{@species}
|
77
|
-
>
|
78
|
-
EOA
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
expected = animal_class.new "bob", "giraffe"
|
83
|
-
actual = animal_class.new "bob", "tortoise"
|
84
|
-
|
85
|
-
expected_diff = <<'EOD'
|
86
|
-
|
87
|
-
@@ -1,5 +1,5 @@
|
88
|
-
<Animal
|
89
|
-
name=bob,
|
90
|
-
- species=tortoise
|
91
|
-
+ species=giraffe
|
92
|
-
>
|
93
|
-
EOD
|
94
|
-
|
95
|
-
diff = differ.diff_as_object(expected,actual)
|
96
|
-
expect(diff).to eq expected_diff
|
97
|
-
end
|
98
|
-
|
99
|
-
it "outputs unified diff message of two arrays" do
|
100
|
-
expected = [ :foo, 'bar', :baz, 'quux', :metasyntactic, 'variable', :delta, 'charlie', :width, 'quite wide' ]
|
101
|
-
actual = [ :foo, 'bar', :baz, 'quux', :metasyntactic, 'variable', :delta, 'tango' , :width, 'very wide' ]
|
102
|
-
|
103
|
-
expected_diff = <<'EOD'
|
104
|
-
|
105
|
-
|
106
|
-
@@ -5,7 +5,7 @@
|
107
|
-
:metasyntactic,
|
108
|
-
"variable",
|
109
|
-
:delta,
|
110
|
-
- "tango",
|
111
|
-
+ "charlie",
|
112
|
-
:width,
|
113
|
-
- "very wide"]
|
114
|
-
+ "quite wide"]
|
115
|
-
EOD
|
116
|
-
|
117
|
-
diff = differ.diff_as_object(expected,actual)
|
118
|
-
expect(diff).to eq expected_diff
|
119
|
-
end
|
120
|
-
|
121
|
-
it "outputs unified diff message of two hashes" do
|
122
|
-
expected = { :foo => 'bar', :baz => 'quux', :metasyntactic => 'variable', :delta => 'charlie', :width =>'quite wide' }
|
123
|
-
actual = { :foo => 'bar', :metasyntactic => 'variable', :delta => 'charlotte', :width =>'quite wide' }
|
124
|
-
|
125
|
-
expected_diff = <<'EOD'
|
126
|
-
|
127
|
-
@@ -1,4 +1,5 @@
|
128
|
-
-:delta => "charlotte",
|
129
|
-
+:baz => "quux",
|
130
|
-
+:delta => "charlie",
|
131
|
-
:foo => "bar",
|
132
|
-
:metasyntactic => "variable",
|
133
|
-
:width => "quite wide"
|
134
|
-
EOD
|
135
|
-
|
136
|
-
diff = differ.diff_as_object(expected,actual)
|
137
|
-
expect(diff).to eq expected_diff
|
138
|
-
end
|
139
|
-
|
140
|
-
it "outputs unified diff of single line strings" do
|
141
|
-
expected = "this is one string"
|
142
|
-
actual = "this is another string"
|
143
|
-
|
144
|
-
expected_diff = <<'EOD'
|
145
|
-
|
146
|
-
@@ -1,2 +1,2 @@
|
147
|
-
-"this is another string"
|
148
|
-
+"this is one string"
|
149
|
-
EOD
|
150
|
-
|
151
|
-
diff = differ.diff_as_object(expected,actual)
|
152
|
-
expect(diff).to eq expected_diff
|
153
|
-
end
|
154
|
-
|
155
|
-
it "outputs unified diff of multi line strings" do
|
156
|
-
expected = "this is:\n one string"
|
157
|
-
actual = "this is:\n another string"
|
158
|
-
|
159
|
-
expected_diff = <<'EOD'
|
160
|
-
|
161
|
-
@@ -1,3 +1,3 @@
|
162
|
-
this is:
|
163
|
-
- another string
|
164
|
-
+ one string
|
165
|
-
EOD
|
166
|
-
|
167
|
-
diff = differ.diff_as_object(expected,actual)
|
168
|
-
expect(diff).to eq expected_diff
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
context "with --color" do
|
174
|
-
before { RSpec::Matchers.configuration.stub(:color? => true) }
|
175
|
-
|
176
|
-
let(:differ) { RSpec::Expectations::Differ.new }
|
177
|
-
|
178
|
-
it "outputs colored diffs" do
|
179
|
-
expected = "foo bar baz"
|
180
|
-
actual = "foo bang baz"
|
181
|
-
expected_diff = "\n\e[34m@@ -1,2 +1,2 @@\n\e[0m\e[31m-foo bang baz\n\e[0m\e[32m+foo bar baz\n\e[0m"
|
182
|
-
|
183
|
-
|
184
|
-
diff = differ.diff_as_string(expected,actual)
|
185
|
-
expect(diff).to eq expected_diff
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|