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.
Files changed (122) hide show
  1. data.tar.gz.sig +2 -2
  2. data/.yardopts +1 -0
  3. data/Changelog.md +138 -0
  4. data/README.md +75 -8
  5. data/features/README.md +2 -2
  6. data/features/built_in_matchers/README.md +12 -9
  7. data/features/built_in_matchers/comparisons.feature +2 -2
  8. data/features/built_in_matchers/contain_exactly.feature +46 -0
  9. data/features/built_in_matchers/expect_change.feature +2 -2
  10. data/features/built_in_matchers/include.feature +0 -48
  11. data/features/built_in_matchers/output.feature +70 -0
  12. data/features/composing_matchers.feature +250 -0
  13. data/features/compound_expectations.feature +45 -0
  14. data/features/custom_matchers/access_running_example.feature +1 -1
  15. data/features/custom_matchers/define_matcher.feature +6 -6
  16. data/features/custom_matchers/define_matcher_outside_rspec.feature +4 -8
  17. data/features/test_frameworks/{test_unit.feature → minitest.feature} +11 -11
  18. data/lib/rspec/expectations.rb +31 -42
  19. data/lib/rspec/expectations/diff_presenter.rb +141 -0
  20. data/lib/rspec/expectations/differ.rb +22 -132
  21. data/lib/rspec/expectations/encoded_string.rb +56 -0
  22. data/lib/rspec/expectations/expectation_target.rb +0 -30
  23. data/lib/rspec/expectations/fail_with.rb +2 -2
  24. data/lib/rspec/expectations/handler.rb +128 -31
  25. data/lib/rspec/expectations/minitest_integration.rb +16 -0
  26. data/lib/rspec/expectations/syntax.rb +4 -58
  27. data/lib/rspec/expectations/version.rb +1 -1
  28. data/lib/rspec/matchers.rb +298 -60
  29. data/lib/rspec/matchers/aliased_matcher.rb +35 -0
  30. data/lib/rspec/matchers/built_in.rb +37 -33
  31. data/lib/rspec/matchers/built_in/base_matcher.rb +25 -15
  32. data/lib/rspec/matchers/built_in/be.rb +23 -31
  33. data/lib/rspec/matchers/built_in/be_between.rb +55 -0
  34. data/lib/rspec/matchers/built_in/be_within.rb +15 -11
  35. data/lib/rspec/matchers/built_in/change.rb +198 -81
  36. data/lib/rspec/matchers/built_in/compound.rb +106 -0
  37. data/lib/rspec/matchers/built_in/contain_exactly.rb +245 -0
  38. data/lib/rspec/matchers/built_in/eq.rb +43 -4
  39. data/lib/rspec/matchers/built_in/eql.rb +2 -2
  40. data/lib/rspec/matchers/built_in/equal.rb +35 -18
  41. data/lib/rspec/matchers/built_in/has.rb +16 -15
  42. data/lib/rspec/matchers/built_in/include.rb +45 -23
  43. data/lib/rspec/matchers/built_in/match.rb +6 -3
  44. data/lib/rspec/matchers/built_in/operators.rb +103 -0
  45. data/lib/rspec/matchers/built_in/output.rb +108 -0
  46. data/lib/rspec/matchers/built_in/raise_error.rb +9 -15
  47. data/lib/rspec/matchers/built_in/respond_to.rb +5 -4
  48. data/lib/rspec/matchers/built_in/satisfy.rb +4 -3
  49. data/lib/rspec/matchers/built_in/start_and_end_with.rb +37 -16
  50. data/lib/rspec/matchers/built_in/throw_symbol.rb +6 -5
  51. data/lib/rspec/matchers/built_in/yield.rb +31 -29
  52. data/lib/rspec/matchers/composable.rb +138 -0
  53. data/lib/rspec/matchers/dsl.rb +330 -0
  54. data/lib/rspec/matchers/generated_descriptions.rb +6 -6
  55. data/lib/rspec/matchers/matcher_delegator.rb +33 -0
  56. data/lib/rspec/matchers/pretty.rb +13 -2
  57. data/spec/rspec/expectations/{differ_spec.rb → diff_presenter_spec.rb} +56 -36
  58. data/spec/rspec/expectations/encoded_string_spec.rb +74 -0
  59. data/spec/rspec/expectations/extensions/kernel_spec.rb +11 -11
  60. data/spec/rspec/expectations/fail_with_spec.rb +8 -8
  61. data/spec/rspec/expectations/handler_spec.rb +27 -49
  62. data/spec/rspec/expectations/minitest_integration_spec.rb +27 -0
  63. data/spec/rspec/expectations/syntax_spec.rb +17 -67
  64. data/spec/rspec/expectations_spec.rb +7 -52
  65. data/spec/rspec/matchers/aliased_matcher_spec.rb +48 -0
  66. data/spec/rspec/matchers/aliases_spec.rb +449 -0
  67. data/spec/rspec/matchers/{base_matcher_spec.rb → built_in/base_matcher_spec.rb} +24 -3
  68. data/spec/rspec/matchers/built_in/be_between_spec.rb +159 -0
  69. data/spec/rspec/matchers/{be_instance_of_spec.rb → built_in/be_instance_of_spec.rb} +0 -0
  70. data/spec/rspec/matchers/{be_kind_of_spec.rb → built_in/be_kind_of_spec.rb} +0 -0
  71. data/spec/rspec/matchers/{be_spec.rb → built_in/be_spec.rb} +76 -32
  72. data/spec/rspec/matchers/{be_within_spec.rb → built_in/be_within_spec.rb} +6 -2
  73. data/spec/rspec/matchers/{change_spec.rb → built_in/change_spec.rb} +310 -69
  74. data/spec/rspec/matchers/built_in/compound_spec.rb +292 -0
  75. data/spec/rspec/matchers/built_in/contain_exactly_spec.rb +441 -0
  76. data/spec/rspec/matchers/{cover_spec.rb → built_in/cover_spec.rb} +0 -0
  77. data/spec/rspec/matchers/built_in/eq_spec.rb +156 -0
  78. data/spec/rspec/matchers/{eql_spec.rb → built_in/eql_spec.rb} +2 -2
  79. data/spec/rspec/matchers/built_in/equal_spec.rb +106 -0
  80. data/spec/rspec/matchers/{exist_spec.rb → built_in/exist_spec.rb} +1 -1
  81. data/spec/rspec/matchers/{has_spec.rb → built_in/has_spec.rb} +39 -0
  82. data/spec/rspec/matchers/{include_spec.rb → built_in/include_spec.rb} +118 -109
  83. data/spec/rspec/matchers/{match_spec.rb → built_in/match_spec.rb} +30 -2
  84. data/spec/rspec/matchers/{operator_matcher_spec.rb → built_in/operators_spec.rb} +26 -26
  85. data/spec/rspec/matchers/built_in/output_spec.rb +165 -0
  86. data/spec/rspec/matchers/{raise_error_spec.rb → built_in/raise_error_spec.rb} +81 -11
  87. data/spec/rspec/matchers/{respond_to_spec.rb → built_in/respond_to_spec.rb} +0 -0
  88. data/spec/rspec/matchers/{satisfy_spec.rb → built_in/satisfy_spec.rb} +0 -0
  89. data/spec/rspec/matchers/{start_with_end_with_spec.rb → built_in/start_and_end_with_spec.rb} +82 -15
  90. data/spec/rspec/matchers/{throw_symbol_spec.rb → built_in/throw_symbol_spec.rb} +29 -10
  91. data/spec/rspec/matchers/{yield_spec.rb → built_in/yield_spec.rb} +90 -0
  92. data/spec/rspec/matchers/configuration_spec.rb +7 -39
  93. data/spec/rspec/matchers/description_generation_spec.rb +22 -6
  94. data/spec/rspec/matchers/dsl_spec.rb +838 -0
  95. data/spec/rspec/matchers/legacy_spec.rb +101 -0
  96. data/spec/rspec/matchers_spec.rb +74 -0
  97. data/spec/spec_helper.rb +35 -21
  98. data/spec/support/shared_examples.rb +26 -4
  99. metadata +172 -116
  100. metadata.gz.sig +3 -4
  101. checksums.yaml +0 -15
  102. checksums.yaml.gz.sig +0 -0
  103. data/features/built_in_matchers/match_array.feature +0 -37
  104. data/lib/rspec/expectations/errors.rb +0 -9
  105. data/lib/rspec/expectations/extensions.rb +0 -1
  106. data/lib/rspec/expectations/extensions/object.rb +0 -29
  107. data/lib/rspec/matchers/built_in/match_array.rb +0 -51
  108. data/lib/rspec/matchers/compatibility.rb +0 -14
  109. data/lib/rspec/matchers/matcher.rb +0 -301
  110. data/lib/rspec/matchers/method_missing.rb +0 -12
  111. data/lib/rspec/matchers/operator_matcher.rb +0 -99
  112. data/lib/rspec/matchers/test_unit_integration.rb +0 -11
  113. data/spec/rspec/matchers/eq_spec.rb +0 -60
  114. data/spec/rspec/matchers/equal_spec.rb +0 -78
  115. data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
  116. data/spec/rspec/matchers/match_array_spec.rb +0 -194
  117. data/spec/rspec/matchers/matcher_spec.rb +0 -706
  118. data/spec/rspec/matchers/matchers_spec.rb +0 -36
  119. data/spec/rspec/matchers/method_missing_spec.rb +0 -28
  120. data/spec/support/classes.rb +0 -56
  121. data/spec/support/in_sub_process.rb +0 -37
  122. 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