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
@@ -20,7 +20,7 @@ describe "expect { ... }.to change(actual, message)" do
20
20
  it "fails when actual is not modified by the block" do
21
21
  expect do
22
22
  expect {}.to change(@instance, :some_value)
23
- end.to fail_with("some_value should have changed, but is still 5")
23
+ end.to fail_with("expected #some_value to have changed, but is still 5")
24
24
  end
25
25
 
26
26
  it "provides a #description" do
@@ -55,7 +55,7 @@ describe "expect { ... }.to change(actual, message)" do
55
55
  it "fails when actual is not modified by the block" do
56
56
  expect do
57
57
  expect {}.to change(@instance, :some_value)
58
- end.to fail_with("some_value should have changed, but is still true")
58
+ end.to fail_with("expected #some_value to have changed, but is still true")
59
59
  end
60
60
  end
61
61
 
@@ -72,7 +72,7 @@ describe "expect { ... }.to change(actual, message)" do
72
72
  it "fails when actual is not modified by the block" do
73
73
  expect do
74
74
  expect {}.to change(@instance, :some_value)
75
- end.to fail_with("some_value should have changed, but is still nil")
75
+ end.to fail_with("expected #some_value to have changed, but is still nil")
76
76
  end
77
77
  end
78
78
 
@@ -89,7 +89,7 @@ describe "expect { ... }.to change(actual, message)" do
89
89
  it "fails when a predicate on the actual fails" do
90
90
  expect do
91
91
  expect {@instance.some_value << 1}.to change { @instance.some_value }.to be_empty
92
- end.to fail_with(/result should have been changed to/)
92
+ end.to fail_with(/result to have changed to/)
93
93
  end
94
94
 
95
95
  it "passes when a predicate on the actual passes" do
@@ -100,7 +100,7 @@ describe "expect { ... }.to change(actual, message)" do
100
100
  it "fails when actual is not modified by the block" do
101
101
  expect do
102
102
  expect {}.to change(@instance, :some_value)
103
- end.to fail_with("some_value should have changed, but is still []")
103
+ end.to fail_with("expected #some_value to have changed, but is still []")
104
104
  end
105
105
  end
106
106
 
@@ -131,7 +131,7 @@ describe "expect { ... }.to change(actual, message)" do
131
131
  string = "ab"
132
132
  expect {
133
133
  expect { }.to change { string }
134
- }.to fail_with(/should have changed/)
134
+ }.to fail_with(/to have changed/)
135
135
  end
136
136
  end
137
137
 
@@ -168,7 +168,7 @@ describe "expect { ... }.to change(actual, message)" do
168
168
  it "fails when actual is not modified by the block" do
169
169
  expect do
170
170
  expect {}.to change(@instance, :some_value)
171
- end.to fail_with(/^some_value should have changed, but is still/)
171
+ end.to fail_with(/^expected #some_value to have changed, but is still/)
172
172
  end
173
173
 
174
174
  end
@@ -187,16 +187,11 @@ describe "expect { ... }.not_to change(actual, message)" do
187
187
  it "fails when actual is not modified by the block" do
188
188
  expect do
189
189
  expect {@instance.some_value = 6}.not_to change(@instance, :some_value)
190
- end.to fail_with("some_value should not have changed, but did change from 5 to 6")
190
+ end.to fail_with("expected #some_value not to have changed, but did change from 5 to 6")
191
191
  end
192
192
  end
193
193
 
194
194
  describe "expect { ... }.to change { block }" do
195
- o = SomethingExpected.new
196
- it_behaves_like "an RSpec matcher", :valid_value => lambda { o.some_value = 5 },
197
- :invalid_value => lambda { } do
198
- let(:matcher) { change { o.some_value } }
199
- end
200
195
 
201
196
  before(:each) do
202
197
  @instance = SomethingExpected.new
@@ -210,17 +205,17 @@ describe "expect { ... }.to change { block }" do
210
205
  it "fails when actual is not modified by the block" do
211
206
  expect do
212
207
  expect {}.to change{ @instance.some_value }
213
- end.to fail_with("result should have changed, but is still 5")
208
+ end.to fail_with("expected result to have changed, but is still 5")
214
209
  end
215
210
 
216
211
  it "warns if passed a block using do/end instead of {}" do
217
212
  expect do
218
213
  expect {}.to change do; end
219
- end.to raise_error(SyntaxError, /block passed to should or should_not/)
214
+ end.to raise_error(SyntaxError, /block passed to the `change` matcher/)
220
215
  end
221
216
 
222
217
  it "provides a #description" do
223
- expect(change { @instance.some_value }.description).to eq "change #result"
218
+ expect(change { @instance.some_value }.description).to eq "change result"
224
219
  end
225
220
  end
226
221
 
@@ -237,13 +232,84 @@ describe "expect { ... }.not_to change { block }" do
237
232
  it "fails when actual is not modified by the block" do
238
233
  expect do
239
234
  expect {@instance.some_value = 6}.not_to change { @instance.some_value }
240
- end.to fail_with("result should not have changed, but did change from 5 to 6")
235
+ end.to fail_with("expected result not to have changed, but did change from 5 to 6")
241
236
  end
242
237
 
243
238
  it "warns if passed a block using do/end instead of {}" do
244
239
  expect do
245
240
  expect {}.not_to change do; end
246
- end.to raise_error(SyntaxError, /block passed to should or should_not/)
241
+ end.to raise_error(SyntaxError, /block passed to the `change` matcher/)
242
+ end
243
+ end
244
+
245
+
246
+ describe "expect { ... }.not_to change { }.from" do
247
+ context 'when the value starts at the from value' do
248
+ it 'passes when the value does not change' do
249
+ k = 5
250
+ expect { }.not_to change { k }.from(5)
251
+ end
252
+
253
+ it 'fails when the value does change' do
254
+ expect {
255
+ k = 5
256
+ expect { k += 1 }.not_to change { k }.from(5)
257
+ }.to fail_with(/but did change from 5 to 6/)
258
+ end
259
+ end
260
+
261
+ context 'when the value starts at a different value' do
262
+ it 'fails when the value does not change' do
263
+ expect {
264
+ k = 6
265
+ expect { }.not_to change { k }.from(5)
266
+ }.to fail_with(/expected result to have initially been 5/)
267
+ end
268
+
269
+ it 'fails when the value does change' do
270
+ expect {
271
+ k = 6
272
+ expect { k += 1 }.not_to change { k }.from(5)
273
+ }.to fail_with(/expected result to have initially been 5/)
274
+ end
275
+ end
276
+ end
277
+
278
+ describe "expect { ... }.not_to change { }.to" do
279
+ it 'is not supported' do
280
+ expect {
281
+ expect { }.not_to change { }.to(3)
282
+ }.to raise_error(NotImplementedError)
283
+ end
284
+
285
+ it 'is not supported when it comes after `from`' do
286
+ expect {
287
+ expect { }.not_to change { }.from(nil).to(3)
288
+ }.to raise_error(NotImplementedError)
289
+ end
290
+ end
291
+
292
+ describe "expect { ... }.not_to change { }.by" do
293
+ it 'is not supported' do
294
+ expect {
295
+ expect { }.not_to change { }.by(3)
296
+ }.to raise_error(NotImplementedError)
297
+ end
298
+ end
299
+
300
+ describe "expect { ... }.not_to change { }.by_at_least" do
301
+ it 'is not supported' do
302
+ expect {
303
+ expect { }.not_to change { }.by_at_least(3)
304
+ }.to raise_error(NotImplementedError)
305
+ end
306
+ end
307
+
308
+ describe "expect { ... }.not_to change { }.by_at_most" do
309
+ it 'is not supported' do
310
+ expect {
311
+ expect { }.not_to change { }.by_at_most(3)
312
+ }.to raise_error(NotImplementedError)
247
313
  end
248
314
  end
249
315
 
@@ -264,13 +330,17 @@ describe "expect { ... }.to change(actual, message).by(expected)" do
264
330
  it "fails when the attribute is changed by unexpected amount" do
265
331
  expect do
266
332
  expect { @instance.some_value += 2 }.to change(@instance, :some_value).by(1)
267
- end.to fail_with("some_value should have been changed by 1, but was changed by 2")
333
+ end.to fail_with("expected #some_value to have changed by 1, but was changed by 2")
268
334
  end
269
335
 
270
336
  it "fails when the attribute is changed by unexpected amount in the opposite direction" do
271
337
  expect do
272
338
  expect { @instance.some_value -= 1 }.to change(@instance, :some_value).by(1)
273
- end.to fail_with("some_value should have been changed by 1, but was changed by -1")
339
+ end.to fail_with("expected #some_value to have changed by 1, but was changed by -1")
340
+ end
341
+
342
+ it "provides a #description" do
343
+ expect(change(@instance, :some_value).by(3).description).to eq "change #some_value by 3"
274
344
  end
275
345
  end
276
346
 
@@ -287,13 +357,17 @@ describe "expect { ... }.to change { block }.by(expected)" do
287
357
  it "fails when the attribute is changed by unexpected amount" do
288
358
  expect do
289
359
  expect { @instance.some_value += 2 }.to change{@instance.some_value}.by(1)
290
- end.to fail_with("result should have been changed by 1, but was changed by 2")
360
+ end.to fail_with("expected result to have changed by 1, but was changed by 2")
291
361
  end
292
362
 
293
363
  it "fails when the attribute is changed by unexpected amount in the opposite direction" do
294
364
  expect do
295
365
  expect { @instance.some_value -= 1 }.to change{@instance.some_value}.by(1)
296
- end.to fail_with("result should have been changed by 1, but was changed by -1")
366
+ end.to fail_with("expected result to have changed by 1, but was changed by -1")
367
+ end
368
+
369
+ it "provides a #description" do
370
+ expect(change { @instance.some_value }.by(3).description).to eq "change result by 3"
297
371
  end
298
372
  end
299
373
 
@@ -314,9 +388,12 @@ describe "expect { ... }.to change(actual, message).by_at_least(expected)" do
314
388
  it "fails when the attribute is changed by less than the expected amount" do
315
389
  expect do
316
390
  expect { @instance.some_value += 1 }.to change(@instance, :some_value).by_at_least(2)
317
- end.to fail_with("some_value should have been changed by at least 2, but was changed by 1")
391
+ end.to fail_with("expected #some_value to have changed by at least 2, but was changed by 1")
318
392
  end
319
393
 
394
+ it "provides a #description" do
395
+ expect(change(@instance, :some_value).by_at_least(3).description).to eq "change #some_value by at least 3"
396
+ end
320
397
  end
321
398
 
322
399
  describe "expect { ... }.to change { block }.by_at_least(expected)" do
@@ -336,7 +413,11 @@ describe "expect { ... }.to change { block }.by_at_least(expected)" do
336
413
  it "fails when the attribute is changed by less than the unexpected amount" do
337
414
  expect do
338
415
  expect { @instance.some_value += 1 }.to change{@instance.some_value}.by_at_least(2)
339
- end.to fail_with("result should have been changed by at least 2, but was changed by 1")
416
+ end.to fail_with("expected result to have changed by at least 2, but was changed by 1")
417
+ end
418
+
419
+ it "provides a #description" do
420
+ expect(change { @instance.some_value }.by_at_least(3).description).to eq "change result by at least 3"
340
421
  end
341
422
  end
342
423
 
@@ -358,9 +439,12 @@ describe "expect { ... }.to change(actual, message).by_at_most(expected)" do
358
439
  it "fails when the attribute is changed by greater than the expected amount" do
359
440
  expect do
360
441
  expect { @instance.some_value += 2 }.to change(@instance, :some_value).by_at_most(1)
361
- end.to fail_with("some_value should have been changed by at most 1, but was changed by 2")
442
+ end.to fail_with("expected #some_value to have changed by at most 1, but was changed by 2")
362
443
  end
363
444
 
445
+ it "provides a #description" do
446
+ expect(change(@instance, :some_value).by_at_most(3).description).to eq "change #some_value by at most 3"
447
+ end
364
448
  end
365
449
 
366
450
  describe "expect { ... }.to change { block }.by_at_most(expected)" do
@@ -380,7 +464,11 @@ describe "expect { ... }.to change { block }.by_at_most(expected)" do
380
464
  it "fails when the attribute is changed by greater than the unexpected amount" do
381
465
  expect do
382
466
  expect { @instance.some_value += 2 }.to change{@instance.some_value}.by_at_most(1)
383
- end.to fail_with("result should have been changed by at most 1, but was changed by 2")
467
+ end.to fail_with("expected result to have changed by at most 1, but was changed by 2")
468
+ end
469
+
470
+ it "provides a #description" do
471
+ expect(change { @instance.some_value }.by_at_most(3).description).to eq "change result by at most 3"
384
472
  end
385
473
  end
386
474
 
@@ -398,7 +486,7 @@ describe "expect { ... }.to change(actual, message).from(old)" do
398
486
  it "fails when attribute is not == to expected value before executing block" do
399
487
  expect do
400
488
  expect { @instance.some_value = 'foo' }.to change(@instance, :some_value).from(false)
401
- end.to fail_with("some_value should have initially been false, but was true")
489
+ end.to fail_with("expected #some_value to have initially been false, but was true")
402
490
  end
403
491
  end
404
492
  context "with non-boolean values" do
@@ -407,20 +495,18 @@ describe "expect { ... }.to change(actual, message).from(old)" do
407
495
  @instance.some_value = 'string'
408
496
  end
409
497
 
410
- it "passes when attribute is === to expected value before executing block" do
498
+ it "passes when attribute matches expected value before executing block" do
411
499
  expect { @instance.some_value = "astring" }.to change(@instance, :some_value).from("string")
412
500
  end
413
501
 
414
- it "compares the expected and actual values with ===" do
415
- expected = "string"
416
- expected.should_receive(:===).and_return true
417
- expect { @instance.some_value = "astring" }.to change(@instance, :some_value).from(expected)
418
- end
419
-
420
- it "fails when attribute is not === to expected value before executing block" do
502
+ it "fails when attribute does not match expected value before executing block" do
421
503
  expect do
422
504
  expect { @instance.some_value = "knot" }.to change(@instance, :some_value).from("cat")
423
- end.to fail_with("some_value should have initially been \"cat\", but was \"string\"")
505
+ end.to fail_with("expected #some_value to have initially been \"cat\", but was \"string\"")
506
+ end
507
+
508
+ it "provides a #description" do
509
+ expect(change(@instance, :some_value).from(3).description).to eq "change #some_value from 3"
424
510
  end
425
511
  end
426
512
  end
@@ -431,20 +517,24 @@ describe "expect { ... }.to change { block }.from(old)" do
431
517
  @instance.some_value = 'string'
432
518
  end
433
519
 
434
- it "passes when attribute is === to expected value before executing block" do
520
+ it "passes when attribute matches expected value before executing block" do
435
521
  expect { @instance.some_value = "astring" }.to change{@instance.some_value}.from("string")
436
522
  end
437
523
 
438
- it "compares the expected and actual values with ===" do
439
- expected = "string"
440
- expected.should_receive(:===).and_return true
441
- expect { @instance.some_value = "astring" }.to change{@instance.some_value}.from(expected)
524
+ it "fails when attribute does not match expected value before executing block" do
525
+ expect do
526
+ expect { @instance.some_value = "knot" }.to change{@instance.some_value}.from("cat")
527
+ end.to fail_with("expected result to have initially been \"cat\", but was \"string\"")
442
528
  end
443
529
 
444
- it "fails when attribute is not === to expected value before executing block" do
530
+ it "fails when attribute does not change" do
445
531
  expect do
446
- expect { @instance.some_value = "knot" }.to change{@instance.some_value}.from("cat")
447
- end.to fail_with("result should have initially been \"cat\", but was \"string\"")
532
+ expect { }.to change { @instance.some_value }.from("string")
533
+ end.to fail_with('expected result to have changed from "string", but did not change')
534
+ end
535
+
536
+ it "provides a #description" do
537
+ expect(change { }.from(3).description).to eq "change result from 3"
448
538
  end
449
539
  end
450
540
 
@@ -462,29 +552,30 @@ describe "expect { ... }.to change(actual, message).to(new)" do
462
552
  it "fails when attribute is not == to expected value after executing block" do
463
553
  expect do
464
554
  expect { @instance.some_value = 1 }.to change(@instance, :some_value).from(true).to(false)
465
- end.to fail_with("some_value should have been changed to false, but is now 1")
555
+ end.to fail_with("expected #some_value to have changed to false, but is now 1")
466
556
  end
467
557
  end
558
+
468
559
  context "with non-boolean values" do
469
560
  before(:each) do
470
561
  @instance = SomethingExpected.new
471
562
  @instance.some_value = 'string'
472
563
  end
473
564
 
474
- it "passes when attribute is === to expected value after executing block" do
565
+ it "passes when attribute matches expected value after executing block" do
475
566
  expect { @instance.some_value = "cat" }.to change(@instance, :some_value).to("cat")
476
567
  end
477
568
 
478
- it "compares the expected and actual values with ===" do
479
- expected = "cat"
480
- expected.should_receive(:===).and_return true
481
- expect { @instance.some_value = "cat" }.to change(@instance, :some_value).to(expected)
482
- end
483
-
484
- it "fails when attribute is not === to expected value after executing block" do
569
+ it "fails when attribute does not match expected value after executing block" do
485
570
  expect do
486
571
  expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("string").to("dog")
487
- end.to fail_with("some_value should have been changed to \"dog\", but is now \"cat\"")
572
+ end.to fail_with("expected #some_value to have changed to \"dog\", but is now \"cat\"")
573
+ end
574
+
575
+ it "fails with a clear message when it ends with the right value but did not change" do
576
+ expect {
577
+ expect { }.to change(@instance, :some_value).to("string")
578
+ }.to fail_with('expected #some_value to have changed to "string", but did not change')
488
579
  end
489
580
  end
490
581
  end
@@ -495,20 +586,18 @@ describe "expect { ... }.to change { block }.to(new)" do
495
586
  @instance.some_value = 'string'
496
587
  end
497
588
 
498
- it "passes when attribute is === to expected value after executing block" do
589
+ it "passes when attribute matches expected value after executing block" do
499
590
  expect { @instance.some_value = "cat" }.to change{@instance.some_value}.to("cat")
500
591
  end
501
592
 
502
- it "compares the expected and actual values with ===" do
503
- expected = "cat"
504
- expected.should_receive(:===).and_return true
505
- expect { @instance.some_value = "cat" }.to change{@instance.some_value}.to(expected)
506
- end
507
-
508
- it "fails when attribute is not === to expected value after executing block" do
593
+ it "fails when attribute does not match expected value after executing block" do
509
594
  expect do
510
595
  expect { @instance.some_value = "cat" }.to change{@instance.some_value}.from("string").to("dog")
511
- end.to fail_with("result should have been changed to \"dog\", but is now \"cat\"")
596
+ end.to fail_with("expected result to have changed to \"dog\", but is now \"cat\"")
597
+ end
598
+
599
+ it "provides a #description" do
600
+ expect(change { }.to(3).description).to eq "change result to 3"
512
601
  end
513
602
  end
514
603
 
@@ -529,13 +618,13 @@ describe "expect { ... }.to change(actual, message).from(old).to(new)" do
529
618
  it "shows the correct messaging when #after and #to are different" do
530
619
  expect do
531
620
  expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("string").to("dog")
532
- end.to fail_with("some_value should have been changed to \"dog\", but is now \"cat\"")
621
+ end.to fail_with("expected #some_value to have changed to \"dog\", but is now \"cat\"")
533
622
  end
534
623
 
535
624
  it "shows the correct messaging when #before and #from are different" do
536
625
  expect do
537
626
  expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("not_string").to("cat")
538
- end.to fail_with("some_value should have initially been \"not_string\", but was \"string\"")
627
+ end.to fail_with("expected #some_value to have initially been \"not_string\", but was \"string\"")
539
628
  end
540
629
  end
541
630
 
@@ -545,12 +634,130 @@ describe "expect { ... }.to change { block }.from(old).to(new)" do
545
634
  @instance.some_value = 'string'
546
635
  end
547
636
 
548
- it "passes when #to comes before #from" do
549
- expect { @instance.some_value = "cat" }.to change{@instance.some_value}.to("cat").from("string")
637
+ context "when #to comes before #from" do
638
+ it "passes" do
639
+ expect { @instance.some_value = "cat" }.to change{@instance.some_value}.to("cat").from("string")
640
+ end
641
+
642
+ it "provides a #description" do
643
+ expect(change { }.to(1).from(3).description).to eq "change result to 1 from 3"
644
+ end
550
645
  end
551
646
 
552
- it "passes when #from comes before #to" do
553
- expect { @instance.some_value = "cat" }.to change{@instance.some_value}.from("string").to("cat")
647
+ context "when #from comes before #to" do
648
+ it "passes" do
649
+ expect { @instance.some_value = "cat" }.to change{@instance.some_value}.from("string").to("cat")
650
+ end
651
+
652
+ it "provides a #description" do
653
+ expect(change { }.from(1).to(3).description).to eq "change result from 1 to 3"
654
+ end
655
+ end
656
+ end
657
+
658
+ describe "Composing a matcher with `change`" do
659
+ describe "expect { ... }.to change { ... }" do
660
+ context ".from(matcher).to(matcher)" do
661
+ it 'passes when the matchers match the from and to values' do
662
+ k = 0.51
663
+ expect { k += 1 }.to change { k }.
664
+ from( a_value_within(0.1).of(0.5) ).
665
+ to( a_value_within(0.1).of(1.5) )
666
+ end
667
+
668
+ it 'fails with a clear message when the `from` does not match' do
669
+ expect {
670
+ k = 0.51
671
+ expect { k += 1 }.to change { k }.
672
+ from( a_value_within(0.1).of(0.7) ).
673
+ to( a_value_within(0.1).of(1.5) )
674
+ }.to fail_with(/expected result to have initially been a value within 0.1 of 0.7, but was 0.51/)
675
+ end
676
+
677
+ it 'fails with a clear message when the `to` does not match' do
678
+ expect {
679
+ k = 0.51
680
+ expect { k += 1 }.to change { k }.
681
+ from( a_value_within(0.1).of(0.5) ).
682
+ to( a_value_within(0.1).of(2.5) )
683
+ }.to fail_with(/expected result to have changed to a value within 0.1 of 2.5, but is now 1.51/)
684
+ end
685
+
686
+ it 'provides a description' do
687
+ expect(change(nil, :foo).
688
+ from( a_value_within(0.1).of(0.5) ).
689
+ to( a_value_within(0.1).of(1.5) ).description
690
+ ).to eq("change #foo from a value within 0.1 of 0.5 to a value within 0.1 of 1.5")
691
+ end
692
+ end
693
+
694
+ context ".to(matcher).from(matcher)" do
695
+ it 'passes when the matchers match the from and to values' do
696
+ k = 0.51
697
+ expect { k += 1 }.to change { k }.
698
+ to( a_value_within(0.1).of(1.5) ).
699
+ from( a_value_within(0.1).of(0.5) )
700
+ end
701
+
702
+ it 'fails with a clear message when the `from` does not match' do
703
+ expect {
704
+ k = 0.51
705
+ expect { k += 1 }.to change { k }.
706
+ to( a_value_within(0.1).of(1.5) ).
707
+ from( a_value_within(0.1).of(0.7) )
708
+ }.to fail_with(/expected result to have initially been a value within 0.1 of 0.7, but was 0.51/)
709
+ end
710
+
711
+ it 'fails with a clear message when the `to` does not match' do
712
+ expect {
713
+ k = 0.51
714
+ expect { k += 1 }.to change { k }.
715
+ to( a_value_within(0.1).of(2.5) ).
716
+ from( a_value_within(0.1).of(0.5) )
717
+ }.to fail_with(/expected result to have changed to a value within 0.1 of 2.5, but is now 1.51/)
718
+ end
719
+
720
+ it 'provides a description' do
721
+ expect(change(nil, :foo).
722
+ to( a_value_within(0.1).of(0.5) ).
723
+ from( a_value_within(0.1).of(1.5) ).description
724
+ ).to eq("change #foo to a value within 0.1 of 0.5 from a value within 0.1 of 1.5")
725
+ end
726
+ end
727
+
728
+ context ".by(matcher)" do
729
+ it "passes when the matcher matches" do
730
+ k = 0.5
731
+ expect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(1) )
732
+ end
733
+
734
+ it 'fails with a clear message when the `by` does not match' do
735
+ expect {
736
+ k = 0.5
737
+ expect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(0.5) )
738
+ }.to fail_with(/expected result to have changed by a value within 0.1 of 0.5, but was changed by 1.05/)
739
+ end
740
+
741
+ it 'provides a description' do
742
+ expect(change(nil, :foo).
743
+ by( a_value_within(0.1).of(0.5) ).description
744
+ ).to eq("change #foo by a value within 0.1 of 0.5")
745
+ end
746
+ end
747
+ end
748
+
749
+ describe "expect { ... }.not_to change { ... }.from(matcher).to(matcher)" do
750
+ it 'passes when the matcher matches the `from` value and it does not change' do
751
+ k = 0.51
752
+ expect { }.not_to change { k }.from( a_value_within(0.1).of(0.5) )
753
+ end
754
+
755
+ it 'fails with a clear message when the `from` matcher does not match' do
756
+ expect {
757
+ k = 0.51
758
+ expect { }.not_to change { k }.from( a_value_within(0.1).of(1.5) )
759
+ }.to fail_with(/expected result to have initially been a value within 0.1 of 1.5, but was 0.51/)
760
+ end
554
761
  end
555
762
  end
556
763
 
@@ -564,4 +771,38 @@ describe RSpec::Matchers::BuiltIn::Change do
564
771
  expect { @instance.some_value = "cat" }.to change(@instance, :some_value)
565
772
  }.not_to raise_error
566
773
  end
774
+
775
+ k = 1
776
+ before { k = 1 }
777
+ it_behaves_like "an RSpec matcher", :valid_value => lambda { k += 1 },
778
+ :invalid_value => lambda { } do
779
+ let(:matcher) { change { k } }
780
+ end
781
+ end
782
+
783
+ describe RSpec::Matchers::BuiltIn::ChangeRelatively do
784
+ k = 0
785
+ before { k = 0 }
786
+ it_behaves_like "an RSpec matcher", :valid_value => lambda { k += 1 },
787
+ :invalid_value => lambda { k += 2 } do
788
+ let(:matcher) { change { k }.by(1) }
789
+ end
790
+ end
791
+
792
+ describe RSpec::Matchers::BuiltIn::ChangeFromValue do
793
+ k = 0
794
+ before { k = 0 }
795
+ it_behaves_like "an RSpec matcher", :valid_value => lambda { k += 1 },
796
+ :invalid_value => lambda { } do
797
+ let(:matcher) { change { k }.from(0) }
798
+ end
799
+ end
800
+
801
+ describe RSpec::Matchers::BuiltIn::ChangeToValue do
802
+ k = 0
803
+ before { k = 0 }
804
+ it_behaves_like "an RSpec matcher", :valid_value => lambda { k = 2 },
805
+ :invalid_value => lambda { k = 3 } do
806
+ let(:matcher) { change { k }.to(2) }
807
+ end
567
808
  end