rspec-expectations 3.0.0.beta1 → 3.0.0.beta2
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.
- data.tar.gz.sig +2 -2
- data/.yardopts +1 -0
- data/Changelog.md +138 -0
- data/README.md +75 -8
- data/features/README.md +2 -2
- data/features/built_in_matchers/README.md +12 -9
- data/features/built_in_matchers/comparisons.feature +2 -2
- data/features/built_in_matchers/contain_exactly.feature +46 -0
- data/features/built_in_matchers/expect_change.feature +2 -2
- data/features/built_in_matchers/include.feature +0 -48
- data/features/built_in_matchers/output.feature +70 -0
- data/features/composing_matchers.feature +250 -0
- data/features/compound_expectations.feature +45 -0
- data/features/custom_matchers/access_running_example.feature +1 -1
- data/features/custom_matchers/define_matcher.feature +6 -6
- data/features/custom_matchers/define_matcher_outside_rspec.feature +4 -8
- data/features/test_frameworks/{test_unit.feature → minitest.feature} +11 -11
- data/lib/rspec/expectations.rb +31 -42
- data/lib/rspec/expectations/diff_presenter.rb +141 -0
- data/lib/rspec/expectations/differ.rb +22 -132
- data/lib/rspec/expectations/encoded_string.rb +56 -0
- data/lib/rspec/expectations/expectation_target.rb +0 -30
- data/lib/rspec/expectations/fail_with.rb +2 -2
- data/lib/rspec/expectations/handler.rb +128 -31
- data/lib/rspec/expectations/minitest_integration.rb +16 -0
- data/lib/rspec/expectations/syntax.rb +4 -58
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +298 -60
- data/lib/rspec/matchers/aliased_matcher.rb +35 -0
- data/lib/rspec/matchers/built_in.rb +37 -33
- data/lib/rspec/matchers/built_in/base_matcher.rb +25 -15
- data/lib/rspec/matchers/built_in/be.rb +23 -31
- data/lib/rspec/matchers/built_in/be_between.rb +55 -0
- data/lib/rspec/matchers/built_in/be_within.rb +15 -11
- data/lib/rspec/matchers/built_in/change.rb +198 -81
- data/lib/rspec/matchers/built_in/compound.rb +106 -0
- data/lib/rspec/matchers/built_in/contain_exactly.rb +245 -0
- data/lib/rspec/matchers/built_in/eq.rb +43 -4
- data/lib/rspec/matchers/built_in/eql.rb +2 -2
- data/lib/rspec/matchers/built_in/equal.rb +35 -18
- data/lib/rspec/matchers/built_in/has.rb +16 -15
- data/lib/rspec/matchers/built_in/include.rb +45 -23
- data/lib/rspec/matchers/built_in/match.rb +6 -3
- data/lib/rspec/matchers/built_in/operators.rb +103 -0
- data/lib/rspec/matchers/built_in/output.rb +108 -0
- data/lib/rspec/matchers/built_in/raise_error.rb +9 -15
- data/lib/rspec/matchers/built_in/respond_to.rb +5 -4
- data/lib/rspec/matchers/built_in/satisfy.rb +4 -3
- data/lib/rspec/matchers/built_in/start_and_end_with.rb +37 -16
- data/lib/rspec/matchers/built_in/throw_symbol.rb +6 -5
- data/lib/rspec/matchers/built_in/yield.rb +31 -29
- data/lib/rspec/matchers/composable.rb +138 -0
- data/lib/rspec/matchers/dsl.rb +330 -0
- data/lib/rspec/matchers/generated_descriptions.rb +6 -6
- data/lib/rspec/matchers/matcher_delegator.rb +33 -0
- data/lib/rspec/matchers/pretty.rb +13 -2
- data/spec/rspec/expectations/{differ_spec.rb → diff_presenter_spec.rb} +56 -36
- data/spec/rspec/expectations/encoded_string_spec.rb +74 -0
- data/spec/rspec/expectations/extensions/kernel_spec.rb +11 -11
- data/spec/rspec/expectations/fail_with_spec.rb +8 -8
- data/spec/rspec/expectations/handler_spec.rb +27 -49
- data/spec/rspec/expectations/minitest_integration_spec.rb +27 -0
- data/spec/rspec/expectations/syntax_spec.rb +17 -67
- data/spec/rspec/expectations_spec.rb +7 -52
- data/spec/rspec/matchers/aliased_matcher_spec.rb +48 -0
- data/spec/rspec/matchers/aliases_spec.rb +449 -0
- data/spec/rspec/matchers/{base_matcher_spec.rb → built_in/base_matcher_spec.rb} +24 -3
- data/spec/rspec/matchers/built_in/be_between_spec.rb +159 -0
- data/spec/rspec/matchers/{be_instance_of_spec.rb → built_in/be_instance_of_spec.rb} +0 -0
- data/spec/rspec/matchers/{be_kind_of_spec.rb → built_in/be_kind_of_spec.rb} +0 -0
- data/spec/rspec/matchers/{be_spec.rb → built_in/be_spec.rb} +76 -32
- data/spec/rspec/matchers/{be_within_spec.rb → built_in/be_within_spec.rb} +6 -2
- data/spec/rspec/matchers/{change_spec.rb → built_in/change_spec.rb} +310 -69
- data/spec/rspec/matchers/built_in/compound_spec.rb +292 -0
- data/spec/rspec/matchers/built_in/contain_exactly_spec.rb +441 -0
- data/spec/rspec/matchers/{cover_spec.rb → built_in/cover_spec.rb} +0 -0
- data/spec/rspec/matchers/built_in/eq_spec.rb +156 -0
- data/spec/rspec/matchers/{eql_spec.rb → built_in/eql_spec.rb} +2 -2
- data/spec/rspec/matchers/built_in/equal_spec.rb +106 -0
- data/spec/rspec/matchers/{exist_spec.rb → built_in/exist_spec.rb} +1 -1
- data/spec/rspec/matchers/{has_spec.rb → built_in/has_spec.rb} +39 -0
- data/spec/rspec/matchers/{include_spec.rb → built_in/include_spec.rb} +118 -109
- data/spec/rspec/matchers/{match_spec.rb → built_in/match_spec.rb} +30 -2
- data/spec/rspec/matchers/{operator_matcher_spec.rb → built_in/operators_spec.rb} +26 -26
- data/spec/rspec/matchers/built_in/output_spec.rb +165 -0
- data/spec/rspec/matchers/{raise_error_spec.rb → built_in/raise_error_spec.rb} +81 -11
- data/spec/rspec/matchers/{respond_to_spec.rb → built_in/respond_to_spec.rb} +0 -0
- data/spec/rspec/matchers/{satisfy_spec.rb → built_in/satisfy_spec.rb} +0 -0
- data/spec/rspec/matchers/{start_with_end_with_spec.rb → built_in/start_and_end_with_spec.rb} +82 -15
- data/spec/rspec/matchers/{throw_symbol_spec.rb → built_in/throw_symbol_spec.rb} +29 -10
- data/spec/rspec/matchers/{yield_spec.rb → built_in/yield_spec.rb} +90 -0
- data/spec/rspec/matchers/configuration_spec.rb +7 -39
- data/spec/rspec/matchers/description_generation_spec.rb +22 -6
- data/spec/rspec/matchers/dsl_spec.rb +838 -0
- data/spec/rspec/matchers/legacy_spec.rb +101 -0
- data/spec/rspec/matchers_spec.rb +74 -0
- data/spec/spec_helper.rb +35 -21
- data/spec/support/shared_examples.rb +26 -4
- metadata +172 -116
- metadata.gz.sig +3 -4
- checksums.yaml +0 -15
- checksums.yaml.gz.sig +0 -0
- data/features/built_in_matchers/match_array.feature +0 -37
- data/lib/rspec/expectations/errors.rb +0 -9
- data/lib/rspec/expectations/extensions.rb +0 -1
- data/lib/rspec/expectations/extensions/object.rb +0 -29
- data/lib/rspec/matchers/built_in/match_array.rb +0 -51
- data/lib/rspec/matchers/compatibility.rb +0 -14
- data/lib/rspec/matchers/matcher.rb +0 -301
- data/lib/rspec/matchers/method_missing.rb +0 -12
- data/lib/rspec/matchers/operator_matcher.rb +0 -99
- data/lib/rspec/matchers/test_unit_integration.rb +0 -11
- data/spec/rspec/matchers/eq_spec.rb +0 -60
- data/spec/rspec/matchers/equal_spec.rb +0 -78
- data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
- data/spec/rspec/matchers/match_array_spec.rb +0 -194
- data/spec/rspec/matchers/matcher_spec.rb +0 -706
- data/spec/rspec/matchers/matchers_spec.rb +0 -36
- data/spec/rspec/matchers/method_missing_spec.rb +0 -28
- data/spec/support/classes.rb +0 -56
- data/spec/support/in_sub_process.rb +0 -37
- data/spec/support/ruby_version.rb +0 -10
@@ -1,706 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
class UnexpectedError < StandardError; end
|
5
|
-
module MatcherHelperModule
|
6
|
-
def self.included(base)
|
7
|
-
base.module_exec do
|
8
|
-
def included_method; end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.extended(base)
|
13
|
-
base.instance_exec do
|
14
|
-
def extended_method; end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def greeting
|
19
|
-
"Hello, World"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
module RSpec::Matchers::DSL
|
24
|
-
describe Matcher do
|
25
|
-
def new_matcher(name, *expected, &block)
|
26
|
-
RSpec::Matchers::DSL::Matcher.
|
27
|
-
new(name, block, *expected).
|
28
|
-
tap { |m| m.matcher_execution_context = self }
|
29
|
-
end
|
30
|
-
|
31
|
-
it "can be stored aside and used later" do
|
32
|
-
# Supports using rspec-expectation matchers as argument matchers in
|
33
|
-
# rspec-mocks.
|
34
|
-
RSpec::Matchers.define :example_matcher do |expected|
|
35
|
-
match do |actual|
|
36
|
-
actual == expected
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
m1 = example_matcher(1)
|
41
|
-
m2 = example_matcher(2)
|
42
|
-
|
43
|
-
expect(m1.matches?(1)).to be_truthy
|
44
|
-
expect(m2.matches?(2)).to be_truthy
|
45
|
-
end
|
46
|
-
|
47
|
-
context "with an included module" do
|
48
|
-
let(:matcher) do
|
49
|
-
new_matcher(:be_a_greeting) do
|
50
|
-
include MatcherHelperModule
|
51
|
-
match { |actual| actual == greeting }
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
it "has access to the module's methods" do
|
56
|
-
matcher.matches?("Hello, World")
|
57
|
-
end
|
58
|
-
|
59
|
-
it "runs the module's included hook" do
|
60
|
-
expect(matcher).to respond_to(:included_method)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "does not run the module's extended hook" do
|
64
|
-
expect(matcher).not_to respond_to(:extended_method)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'allows multiple modules to be included at once' do
|
68
|
-
m = new_matcher(:multiple_modules) do
|
69
|
-
include Enumerable, Comparable
|
70
|
-
end
|
71
|
-
expect(m).to be_a(Enumerable)
|
72
|
-
expect(m).to be_a(Comparable)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
context "without overrides" do
|
77
|
-
let(:matcher) do
|
78
|
-
new_matcher(:be_a_multiple_of, 3) do |multiple|
|
79
|
-
match do |actual|
|
80
|
-
actual % multiple == 0
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
it "provides a default description" do
|
86
|
-
expect(matcher.description).to eq "be a multiple of 3"
|
87
|
-
end
|
88
|
-
|
89
|
-
it "provides a default failure message for #should" do
|
90
|
-
matcher.matches?(8)
|
91
|
-
expect(matcher.failure_message_for_should).to eq "expected 8 to be a multiple of 3"
|
92
|
-
end
|
93
|
-
|
94
|
-
it "provides a default failure message for #should_not" do
|
95
|
-
matcher.matches?(9)
|
96
|
-
expect(matcher.failure_message_for_should_not).to eq "expected 9 not to be a multiple of 3"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
context "with separate match logic for should and should not" do
|
101
|
-
let(:matcher) do
|
102
|
-
new_matcher(:to_be_composed_of, 7, 11) do |a, b|
|
103
|
-
match_for_should do |actual|
|
104
|
-
actual == a * b
|
105
|
-
end
|
106
|
-
|
107
|
-
match_for_should_not do |actual|
|
108
|
-
actual == a + b
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
it "invokes the match_for_should block for #matches?" do
|
114
|
-
expect(matcher.matches?(77)).to be_truthy
|
115
|
-
expect(matcher.matches?(18)).to be_falsey
|
116
|
-
end
|
117
|
-
|
118
|
-
it "invokes the match_for_should_not block for #does_not_match?" do
|
119
|
-
expect(matcher.does_not_match?(77)).to be_falsey
|
120
|
-
expect(matcher.does_not_match?(18)).to be_truthy
|
121
|
-
end
|
122
|
-
|
123
|
-
it "provides a default failure message for #should_not" do
|
124
|
-
matcher.does_not_match?(77)
|
125
|
-
expect(matcher.failure_message_for_should_not).to eq "expected 77 not to to be composed of 7 and 11"
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'can access helper methods from `match_for_should_not`' do
|
129
|
-
matcher = new_matcher(:be_foo) do
|
130
|
-
def foo
|
131
|
-
:foo
|
132
|
-
end
|
133
|
-
|
134
|
-
match_for_should_not do |actual|
|
135
|
-
actual != foo
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
expect(matcher.does_not_match?(:bar)).to be true
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
it "allows helper methods to be defined with #define_method to have access to matcher parameters" do
|
144
|
-
matcher = new_matcher(:name, 3, 4) do |a, b|
|
145
|
-
define_method(:sum) { a + b }
|
146
|
-
end
|
147
|
-
|
148
|
-
expect(matcher.sum).to eq 7
|
149
|
-
end
|
150
|
-
|
151
|
-
it "is not diffable by default" do
|
152
|
-
matcher = new_matcher(:name) { }
|
153
|
-
expect(matcher).not_to be_diffable
|
154
|
-
end
|
155
|
-
|
156
|
-
it "is diffable when told to be" do
|
157
|
-
matcher = new_matcher(:name) { diffable }
|
158
|
-
expect(matcher).to be_diffable
|
159
|
-
end
|
160
|
-
|
161
|
-
it 'does not confuse the diffability of different matchers' do
|
162
|
-
# Necessary to guard against a regression that involved
|
163
|
-
# using a class variable to store the diffable state,
|
164
|
-
# which had the side effect of causing all custom matchers
|
165
|
-
# to share that state
|
166
|
-
m1 = new_matcher(:m1) { diffable }
|
167
|
-
m2 = new_matcher(:m2) { }
|
168
|
-
m3 = new_matcher(:m3) { diffable }
|
169
|
-
|
170
|
-
expect(m1).to be_diffable
|
171
|
-
expect(m2).not_to be_diffable
|
172
|
-
expect(m3).to be_diffable
|
173
|
-
end
|
174
|
-
|
175
|
-
it "provides expected" do
|
176
|
-
matcher = new_matcher(:name, "expected string") { }
|
177
|
-
expect(matcher.expected).to eq ['expected string']
|
178
|
-
end
|
179
|
-
|
180
|
-
it "provides actual when `match` is used" do
|
181
|
-
matcher = new_matcher(:name, 'expected string') do
|
182
|
-
match {|actual|}
|
183
|
-
end
|
184
|
-
|
185
|
-
matcher.matches?('actual string')
|
186
|
-
|
187
|
-
expect(matcher.actual).to eq 'actual string'
|
188
|
-
end
|
189
|
-
|
190
|
-
it "provides actual when the `match` block accepts splat args" do
|
191
|
-
matcher = new_matcher(:actual) do
|
192
|
-
match { |*actual| actual == [5] }
|
193
|
-
end
|
194
|
-
|
195
|
-
expect(matcher.matches?(5)).to be true
|
196
|
-
expect(matcher.matches?(4)).to be false
|
197
|
-
end
|
198
|
-
|
199
|
-
it 'allows an early `return` to be used from a `match` block' do
|
200
|
-
matcher = new_matcher(:with_return, 5) do |expected|
|
201
|
-
match { |actual| return true if expected == actual }
|
202
|
-
end
|
203
|
-
|
204
|
-
expect(matcher.matches?(5)).to be true
|
205
|
-
expect(matcher.matches?(4)).to be_falsey
|
206
|
-
end
|
207
|
-
|
208
|
-
it 'provides actual when `match_unless_raises` is used' do
|
209
|
-
matcher = new_matcher(:name, 'expected string') do
|
210
|
-
match_unless_raises(SyntaxError) {|actual|}
|
211
|
-
end
|
212
|
-
|
213
|
-
matcher.matches?('actual string')
|
214
|
-
|
215
|
-
expect(matcher.actual).to eq 'actual string'
|
216
|
-
end
|
217
|
-
|
218
|
-
it 'allows an early `return` to be used from a `match_unless_raises` block' do
|
219
|
-
matcher = new_matcher(:with_return) do |expected|
|
220
|
-
match_unless_raises(ArgumentError) do |actual|
|
221
|
-
return actual if [true, false].include?(actual)
|
222
|
-
raise ArgumentError
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
expect(matcher.matches?(true)).to be true
|
227
|
-
# It should match even if it returns false, because no error was raised.
|
228
|
-
expect(matcher.matches?(false)).to be true
|
229
|
-
expect(matcher.matches?(4)).to be_falsey
|
230
|
-
end
|
231
|
-
|
232
|
-
it 'provides actual when `match_for_should_not` is used' do
|
233
|
-
matcher = new_matcher(:name, 'expected string') do
|
234
|
-
match_for_should_not {|actual|}
|
235
|
-
end
|
236
|
-
|
237
|
-
matcher.does_not_match?('actual string')
|
238
|
-
|
239
|
-
expect(matcher.actual).to eq 'actual string'
|
240
|
-
end
|
241
|
-
|
242
|
-
it 'allows an early `return` to be used from a `match_for_should_not` block' do
|
243
|
-
matcher = new_matcher(:with_return, 5) do |expected|
|
244
|
-
match_for_should_not { |actual| return true if expected != actual }
|
245
|
-
end
|
246
|
-
|
247
|
-
expect(matcher.does_not_match?(5)).to be_falsey
|
248
|
-
expect(matcher.does_not_match?(4)).to be true
|
249
|
-
end
|
250
|
-
|
251
|
-
context "wrapping another expectation (expect(...).to eq ...)" do
|
252
|
-
let(:matcher) do
|
253
|
-
new_matcher(:name, "value") do |expected|
|
254
|
-
match do |actual|
|
255
|
-
expect(actual).to eq expected
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
it "returns true if the wrapped expectation passes" do
|
261
|
-
expect(matcher.matches?('value')).to be_truthy
|
262
|
-
end
|
263
|
-
|
264
|
-
it "returns false if the wrapped expectation fails" do
|
265
|
-
expect(matcher.matches?('other value')).to be_falsey
|
266
|
-
end
|
267
|
-
|
268
|
-
it "can use the `include` matcher from a `match` block" do
|
269
|
-
RSpec::Matchers.define(:descend_from) do |mod|
|
270
|
-
match do |klass|
|
271
|
-
expect(klass.ancestors).to include(mod)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
expect(Fixnum).to descend_from(Object)
|
276
|
-
expect(Fixnum).not_to descend_from(Array)
|
277
|
-
|
278
|
-
expect {
|
279
|
-
expect(Fixnum).to descend_from(Array)
|
280
|
-
}.to fail_with(/expected Fixnum to descend from Array/)
|
281
|
-
|
282
|
-
expect {
|
283
|
-
expect(Fixnum).not_to descend_from(Object)
|
284
|
-
}.to fail_with(/expected Fixnum not to descend from Object/)
|
285
|
-
end
|
286
|
-
|
287
|
-
it "can use the `match` matcher from a `match` block" do
|
288
|
-
RSpec::Matchers.define(:be_a_phone_number_string) do
|
289
|
-
match do |string|
|
290
|
-
expect(string).to match(/\A\d{3}\-\d{3}\-\d{4}\z/)
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
expect("206-123-1234").to be_a_phone_number_string
|
295
|
-
expect("foo").not_to be_a_phone_number_string
|
296
|
-
|
297
|
-
expect {
|
298
|
-
expect("foo").to be_a_phone_number_string
|
299
|
-
}.to fail_with(/expected "foo" to be a phone number string/)
|
300
|
-
|
301
|
-
expect {
|
302
|
-
expect("206-123-1234").not_to be_a_phone_number_string
|
303
|
-
}.to fail_with(/expected "206-123-1234" not to be a phone number string/)
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
context "with overrides" do
|
308
|
-
let(:matcher) do
|
309
|
-
new_matcher(:be_boolean, true) do |boolean|
|
310
|
-
match do |actual|
|
311
|
-
actual
|
312
|
-
end
|
313
|
-
description do |actual|
|
314
|
-
"be the boolean #{boolean} (actual was #{actual})"
|
315
|
-
end
|
316
|
-
failure_message_for_should do |actual|
|
317
|
-
"expected #{actual} to be the boolean #{boolean}"
|
318
|
-
end
|
319
|
-
failure_message_for_should_not do |actual|
|
320
|
-
"expected #{actual} not to be the boolean #{boolean}"
|
321
|
-
end
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
it "does not hide result of match block when true" do
|
326
|
-
expect(matcher.matches?(true)).to be_truthy
|
327
|
-
end
|
328
|
-
|
329
|
-
it "does not hide result of match block when false" do
|
330
|
-
expect(matcher.matches?(false)).to be_falsey
|
331
|
-
end
|
332
|
-
|
333
|
-
it "overrides the description (which yields `actual`)" do
|
334
|
-
matcher.matches?(true)
|
335
|
-
expect(matcher.description).to eq "be the boolean true (actual was true)"
|
336
|
-
end
|
337
|
-
|
338
|
-
it "overrides the failure message for #should" do
|
339
|
-
matcher.matches?(false)
|
340
|
-
expect(matcher.failure_message_for_should).to eq "expected false to be the boolean true"
|
341
|
-
end
|
342
|
-
|
343
|
-
it "overrides the failure message for #should_not" do
|
344
|
-
matcher.matches?(true)
|
345
|
-
expect(matcher.failure_message_for_should_not).to eq "expected true not to be the boolean true"
|
346
|
-
end
|
347
|
-
|
348
|
-
it 'can access helper methods from `description`' do
|
349
|
-
matcher = new_matcher(:desc) do
|
350
|
-
def subdesc() "sub description" end
|
351
|
-
description { "Desc (#{subdesc})" }
|
352
|
-
end
|
353
|
-
|
354
|
-
expect(matcher.description).to eq("Desc (sub description)")
|
355
|
-
end
|
356
|
-
|
357
|
-
it 'can access helper methods from `failure_message_for_should`' do
|
358
|
-
matcher = new_matcher(:positive_failure_message) do
|
359
|
-
def helper() "helper" end
|
360
|
-
failure_message_for_should { helper }
|
361
|
-
end
|
362
|
-
|
363
|
-
expect(matcher.failure_message_for_should).to eq("helper")
|
364
|
-
end
|
365
|
-
|
366
|
-
it 'can access helper methods from `failure_message_for_should_not`' do
|
367
|
-
matcher = new_matcher(:negative_failure_message) do
|
368
|
-
def helper() "helper" end
|
369
|
-
failure_message_for_should_not { helper }
|
370
|
-
end
|
371
|
-
|
372
|
-
expect(matcher.failure_message_for_should_not).to eq("helper")
|
373
|
-
end
|
374
|
-
|
375
|
-
it 'can exit early with a `return` from `description` just like in a method' do
|
376
|
-
matcher = new_matcher(:desc) do
|
377
|
-
description { return "Desc" }
|
378
|
-
end
|
379
|
-
|
380
|
-
expect(matcher.description).to eq("Desc")
|
381
|
-
end
|
382
|
-
|
383
|
-
it 'can exit early with a `return` from `failure_message_for_should` just like in a method' do
|
384
|
-
matcher = new_matcher(:positive_failure_message) do
|
385
|
-
failure_message_for_should { return "msg" }
|
386
|
-
end
|
387
|
-
|
388
|
-
expect(matcher.failure_message_for_should).to eq("msg")
|
389
|
-
end
|
390
|
-
|
391
|
-
it 'can exit early with a `return` from `failure_message_for_should_not` just like in a method' do
|
392
|
-
matcher = new_matcher(:negative_failure_message) do
|
393
|
-
failure_message_for_should_not { return "msg" }
|
394
|
-
end
|
395
|
-
|
396
|
-
expect(matcher.failure_message_for_should_not).to eq("msg")
|
397
|
-
end
|
398
|
-
end
|
399
|
-
|
400
|
-
context "#new" do
|
401
|
-
it "passes matches? arg to match block" do
|
402
|
-
matcher = new_matcher(:ignore) do
|
403
|
-
match do |actual|
|
404
|
-
actual == 5
|
405
|
-
end
|
406
|
-
end
|
407
|
-
expect(matcher.matches?(5)).to be_truthy
|
408
|
-
end
|
409
|
-
|
410
|
-
it "exposes arg submitted through #new to matcher block" do
|
411
|
-
matcher = new_matcher(:ignore, 4) do |expected|
|
412
|
-
match do |actual|
|
413
|
-
actual > expected
|
414
|
-
end
|
415
|
-
end
|
416
|
-
expect(matcher.matches?(5)).to be_truthy
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
context "with no args" do
|
421
|
-
let(:matcher) do
|
422
|
-
new_matcher(:matcher_name) do
|
423
|
-
match do |actual|
|
424
|
-
actual == 5
|
425
|
-
end
|
426
|
-
end
|
427
|
-
end
|
428
|
-
|
429
|
-
it "matches" do
|
430
|
-
expect(matcher.matches?(5)).to be_truthy
|
431
|
-
end
|
432
|
-
|
433
|
-
it "describes" do
|
434
|
-
expect(matcher.description).to eq "matcher name"
|
435
|
-
end
|
436
|
-
end
|
437
|
-
|
438
|
-
context "with 1 arg" do
|
439
|
-
let(:matcher) do
|
440
|
-
new_matcher(:matcher_name, 1) do |expected|
|
441
|
-
match do |actual|
|
442
|
-
actual == 5 && expected == 1
|
443
|
-
end
|
444
|
-
end
|
445
|
-
end
|
446
|
-
|
447
|
-
it "matches" do
|
448
|
-
expect(matcher.matches?(5)).to be_truthy
|
449
|
-
end
|
450
|
-
|
451
|
-
it "describes" do
|
452
|
-
expect(matcher.description).to eq "matcher name 1"
|
453
|
-
end
|
454
|
-
end
|
455
|
-
|
456
|
-
context "with multiple args" do
|
457
|
-
let(:matcher) do
|
458
|
-
new_matcher(:matcher_name, 1, 2, 3, 4) do |a, b, c, d|
|
459
|
-
match do |sum|
|
460
|
-
a + b + c + d == sum
|
461
|
-
end
|
462
|
-
end
|
463
|
-
end
|
464
|
-
|
465
|
-
it "matches" do
|
466
|
-
expect(matcher.matches?(10)).to be_truthy
|
467
|
-
end
|
468
|
-
|
469
|
-
it "describes" do
|
470
|
-
expect(matcher.description).to eq "matcher name 1, 2, 3, and 4"
|
471
|
-
end
|
472
|
-
end
|
473
|
-
|
474
|
-
it "supports helper methods" do
|
475
|
-
matcher = new_matcher(:be_similar_to, [1, 2, 3]) do |sample|
|
476
|
-
match do |actual|
|
477
|
-
similar?(sample, actual)
|
478
|
-
end
|
479
|
-
|
480
|
-
def similar?(a, b)
|
481
|
-
a.sort == b.sort
|
482
|
-
end
|
483
|
-
end
|
484
|
-
|
485
|
-
expect(matcher.matches?([2,3,1])).to be_truthy
|
486
|
-
end
|
487
|
-
|
488
|
-
it "supports fluent interface" do
|
489
|
-
matcher = new_matcher(:first_word) do
|
490
|
-
def second_word
|
491
|
-
self
|
492
|
-
end
|
493
|
-
end
|
494
|
-
|
495
|
-
expect(matcher.second_word).to eq matcher
|
496
|
-
end
|
497
|
-
|
498
|
-
it "treats method missing normally for undeclared methods" do
|
499
|
-
matcher = new_matcher(:ignore) { }
|
500
|
-
expect { matcher.non_existent_method }.to raise_error(NoMethodError)
|
501
|
-
end
|
502
|
-
|
503
|
-
it "has access to other matchers" do
|
504
|
-
matcher = new_matcher(:ignore, 3) do |expected|
|
505
|
-
match do |actual|
|
506
|
-
extend RSpec::Matchers
|
507
|
-
expect(actual).to eql(5 + expected)
|
508
|
-
end
|
509
|
-
end
|
510
|
-
|
511
|
-
expect(matcher.matches?(8)).to be_truthy
|
512
|
-
end
|
513
|
-
|
514
|
-
context 'when multiple instances of the same matcher are used in the same example' do
|
515
|
-
RSpec::Matchers.define(:be_like_a) do |expected|
|
516
|
-
match { |actual| actual == expected }
|
517
|
-
description { "be like a #{expected}" }
|
518
|
-
failure_message_for_should { "expected to be like a #{expected}" }
|
519
|
-
failure_message_for_should_not { "expected not to be like a #{expected}" }
|
520
|
-
end
|
521
|
-
|
522
|
-
# Note: these bugs were only exposed when creating both instances
|
523
|
-
# first, then checking their descriptions/failure messages.
|
524
|
-
#
|
525
|
-
# That's why we eager-instantiate them here.
|
526
|
-
let!(:moose) { be_like_a("moose") }
|
527
|
-
let!(:horse) { be_like_a("horse") }
|
528
|
-
|
529
|
-
it 'allows them to use the expected value in the description' do
|
530
|
-
expect(horse.description).to eq("be like a horse")
|
531
|
-
expect(moose.description).to eq("be like a moose")
|
532
|
-
end
|
533
|
-
|
534
|
-
it 'allows them to use the expected value in the positive failure message' do
|
535
|
-
expect(moose.failure_message_for_should).to eq("expected to be like a moose")
|
536
|
-
expect(horse.failure_message_for_should).to eq("expected to be like a horse")
|
537
|
-
end
|
538
|
-
|
539
|
-
it 'allows them to use the expected value in the negative failure message' do
|
540
|
-
expect(moose.failure_message_for_should_not).to eq("expected not to be like a moose")
|
541
|
-
expect(horse.failure_message_for_should_not).to eq("expected not to be like a horse")
|
542
|
-
end
|
543
|
-
|
544
|
-
it 'allows them to match separately' do
|
545
|
-
expect("moose").to moose
|
546
|
-
expect("horse").to horse
|
547
|
-
expect("horse").not_to moose
|
548
|
-
expect("moose").not_to horse
|
549
|
-
end
|
550
|
-
end
|
551
|
-
|
552
|
-
describe "#match_unless_raises" do
|
553
|
-
context "with an assertion" do
|
554
|
-
mod = Module.new do
|
555
|
-
def assert_equal(a,b)
|
556
|
-
raise UnexpectedError.new("#{b} does not equal #{a}") unless a == b
|
557
|
-
end
|
558
|
-
end
|
559
|
-
|
560
|
-
let(:matcher) do
|
561
|
-
new_matcher(:equal, 4) do |expected|
|
562
|
-
include mod
|
563
|
-
match_unless_raises UnexpectedError do
|
564
|
-
assert_equal expected, actual
|
565
|
-
end
|
566
|
-
end
|
567
|
-
end
|
568
|
-
|
569
|
-
context "with passing assertion" do
|
570
|
-
it "passes" do
|
571
|
-
expect(matcher.matches?(4)).to be_truthy
|
572
|
-
end
|
573
|
-
end
|
574
|
-
|
575
|
-
context "with failing assertion" do
|
576
|
-
it "fails" do
|
577
|
-
expect(matcher.matches?(5)).to be_falsey
|
578
|
-
end
|
579
|
-
|
580
|
-
it "provides the raised exception" do
|
581
|
-
matcher.matches?(5)
|
582
|
-
expect(matcher.rescued_exception.message).to eq("5 does not equal 4")
|
583
|
-
end
|
584
|
-
end
|
585
|
-
end
|
586
|
-
|
587
|
-
context "with an unexpected error" do
|
588
|
-
let(:matcher) do
|
589
|
-
new_matcher(:foo, :bar) do |expected|
|
590
|
-
match_unless_raises SyntaxError do |actual|
|
591
|
-
raise "unexpected exception"
|
592
|
-
end
|
593
|
-
end
|
594
|
-
end
|
595
|
-
|
596
|
-
it "raises the error" do
|
597
|
-
expect {
|
598
|
-
matcher.matches?(:bar)
|
599
|
-
}.to raise_error("unexpected exception")
|
600
|
-
end
|
601
|
-
end
|
602
|
-
|
603
|
-
context "without a specified error class" do
|
604
|
-
let(:matcher) do
|
605
|
-
new_matcher(:foo) do
|
606
|
-
match_unless_raises do |actual|
|
607
|
-
raise Exception unless actual == 5
|
608
|
-
end
|
609
|
-
end
|
610
|
-
end
|
611
|
-
|
612
|
-
it 'passes if no error is raised' do
|
613
|
-
expect(matcher.matches?(5)).to be true
|
614
|
-
end
|
615
|
-
|
616
|
-
it 'fails if an exception is raised' do
|
617
|
-
expect(matcher.matches?(4)).to be false
|
618
|
-
end
|
619
|
-
end
|
620
|
-
|
621
|
-
end
|
622
|
-
|
623
|
-
it "can define chainable methods" do
|
624
|
-
matcher = new_matcher(:name) do
|
625
|
-
chain(:expecting) do |expected_value|
|
626
|
-
@expected_value = expected_value
|
627
|
-
end
|
628
|
-
match { |actual| actual == @expected_value }
|
629
|
-
end
|
630
|
-
|
631
|
-
expect(matcher.expecting('value').matches?('value')).to be_truthy
|
632
|
-
expect(matcher.expecting('value').matches?('other value')).to be_falsey
|
633
|
-
end
|
634
|
-
|
635
|
-
it 'can use an early return from a `chain` block' do
|
636
|
-
matcher = new_matcher(:name) do
|
637
|
-
chain(:expecting) do |expected_value|
|
638
|
-
@expected_value = expected_value
|
639
|
-
return
|
640
|
-
end
|
641
|
-
match { |actual| actual == @expected_value }
|
642
|
-
end
|
643
|
-
|
644
|
-
expect(matcher.expecting('value').matches?('value')).to be_truthy
|
645
|
-
expect(matcher.expecting('value').matches?('other value')).to be_falsey
|
646
|
-
end
|
647
|
-
|
648
|
-
it 'allows chainable methods to accept blocks' do
|
649
|
-
matcher = new_matcher(:name) do
|
650
|
-
chain(:for_block) { |&b| @block = b }
|
651
|
-
match { |value| @block.call == value }
|
652
|
-
end
|
653
|
-
|
654
|
-
expect(matcher.for_block { 5 }.matches?(5)).to be true
|
655
|
-
expect(matcher.for_block { 3 }.matches?(4)).to be false
|
656
|
-
end
|
657
|
-
|
658
|
-
it "prevents name collisions on chainable methods from different matchers" do
|
659
|
-
m1 = new_matcher(:m1) { chain(:foo) { raise "foo in m1" } }
|
660
|
-
m2 = new_matcher(:m2) { chain(:foo) { raise "foo in m2" } }
|
661
|
-
|
662
|
-
expect { m1.foo }.to raise_error("foo in m1")
|
663
|
-
expect { m2.foo }.to raise_error("foo in m2")
|
664
|
-
end
|
665
|
-
|
666
|
-
context "defined using the dsl" do
|
667
|
-
def a_method_in_the_example
|
668
|
-
"method defined in the example"
|
669
|
-
end
|
670
|
-
|
671
|
-
it "can access methods in the running example" do |example|
|
672
|
-
RSpec::Matchers.define(:__access_running_example) do
|
673
|
-
match do |actual|
|
674
|
-
a_method_in_the_example == "method defined in the example"
|
675
|
-
end
|
676
|
-
end
|
677
|
-
expect(example).to __access_running_example
|
678
|
-
end
|
679
|
-
|
680
|
-
it 'can get a method object for methods in the running example', :if => (RUBY_VERSION.to_f > 1.8) do
|
681
|
-
matcher = new_matcher(:get_method_object) { }
|
682
|
-
method = matcher.method(:a_method_in_the_example)
|
683
|
-
expect(method.call).to eq("method defined in the example")
|
684
|
-
end
|
685
|
-
|
686
|
-
it 'indicates that it responds to a method from the running example' do
|
687
|
-
matcher = new_matcher(:respond_to) { }
|
688
|
-
expect(matcher).to respond_to(:a_method_in_the_example)
|
689
|
-
expect(matcher).not_to respond_to(:a_method_not_in_the_example)
|
690
|
-
end
|
691
|
-
|
692
|
-
it "raises NoMethodError for methods not in the running_example" do |example|
|
693
|
-
RSpec::Matchers.define(:__raise_no_method_error) do
|
694
|
-
match do |actual|
|
695
|
-
self.a_method_not_in_the_example == "method defined in the example"
|
696
|
-
end
|
697
|
-
end
|
698
|
-
|
699
|
-
expect {
|
700
|
-
expect(example).to __raise_no_method_error
|
701
|
-
}.to raise_error(NoMethodError, /Spec::Matchers::DSL::Matcher __raise_no_method_error/)
|
702
|
-
end
|
703
|
-
end
|
704
|
-
|
705
|
-
end
|
706
|
-
end
|