rspec-expectations 2.5.0 → 2.6.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.travis.yml +7 -0
  2. data/Gemfile +13 -11
  3. data/README.md +2 -0
  4. data/Rakefile +28 -17
  5. data/features/Changelog.md +16 -0
  6. data/features/built_in_matchers/be.feature +4 -4
  7. data/features/built_in_matchers/be_within.feature +1 -1
  8. data/features/built_in_matchers/equality.feature +5 -5
  9. data/features/built_in_matchers/exist.feature +1 -1
  10. data/features/built_in_matchers/expect_change.feature +2 -2
  11. data/features/built_in_matchers/expect_error.feature +7 -7
  12. data/features/built_in_matchers/have.feature +2 -2
  13. data/features/built_in_matchers/include.feature +3 -3
  14. data/features/built_in_matchers/match.feature +2 -2
  15. data/features/built_in_matchers/operators.feature +3 -3
  16. data/features/built_in_matchers/predicates.feature +5 -5
  17. data/features/built_in_matchers/respond_to.feature +2 -2
  18. data/features/built_in_matchers/satisfy.feature +1 -1
  19. data/features/built_in_matchers/throw_symbol.feature +3 -3
  20. data/features/built_in_matchers/types.feature +2 -2
  21. data/features/custom_matchers/access_running_example.feature +2 -2
  22. data/features/custom_matchers/define_diffable_matcher.feature +1 -1
  23. data/features/custom_matchers/define_matcher.feature +40 -11
  24. data/features/custom_matchers/define_matcher_outside_rspec.feature +1 -1
  25. data/features/custom_matchers/define_matcher_with_fluent_interface.feature +1 -1
  26. data/features/customized_message.feature +1 -1
  27. data/features/diffing.feature +4 -4
  28. data/features/implicit_docstrings.feature +2 -2
  29. data/features/step_definitions/additional_cli_steps.rb +2 -2
  30. data/features/support/env.rb +5 -1
  31. data/features/test_frameworks/test_unit.feature +1 -1
  32. data/lib/rspec/expectations/backward_compatibility.rb +22 -1
  33. data/lib/rspec/expectations/version.rb +1 -1
  34. data/lib/rspec/matchers.rb +10 -5
  35. data/lib/rspec/matchers/change.rb +47 -32
  36. data/lib/rspec/matchers/has.rb +15 -11
  37. data/lib/rspec/matchers/matcher.rb +4 -0
  38. data/spec/rspec/matchers/be_spec.rb +0 -4
  39. data/spec/rspec/matchers/change_spec.rb +84 -9
  40. data/spec/rspec/matchers/description_generation_spec.rb +41 -25
  41. data/spec/rspec/matchers/has_spec.rb +2 -2
  42. data/spec/rspec/matchers/have_spec.rb +21 -21
  43. data/spec/rspec/matchers/matcher_spec.rb +46 -0
  44. data/spec/rspec/matchers/matchers_spec.rb +3 -23
  45. data/spec/rspec/matchers/method_missing_spec.rb +23 -0
  46. data/spec/spec_helper.rb +2 -0
  47. metadata +23 -18
  48. data/spec/suite.rb +0 -1
@@ -1,35 +1,39 @@
1
1
  module RSpec
2
2
  module Matchers
3
-
4
3
  class Has
5
-
6
4
  def initialize(expected, *args)
7
5
  @expected, @args = expected, args
8
6
  end
9
-
7
+
10
8
  def matches?(actual)
11
9
  actual.__send__(predicate(@expected), *@args)
12
10
  end
13
-
11
+
14
12
  def failure_message_for_should
15
13
  "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return true, got false"
16
14
  end
17
-
15
+
18
16
  def failure_message_for_should_not
19
17
  "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return false, got true"
20
18
  end
21
-
19
+
22
20
  def description
23
- "have key #{@args[0].inspect}"
21
+ [method_description(@expected), args_description(@args)].compact.join(' ')
24
22
  end
25
-
23
+
26
24
  private
27
-
28
25
  def predicate(sym)
29
26
  "#{sym.to_s.sub("have_","has_")}?".to_sym
30
27
  end
31
-
28
+
29
+ def method_description(method)
30
+ method.to_s.gsub('_', ' ')
31
+ end
32
+
33
+ def args_description(args)
34
+ return nil if args.empty?
35
+ args.map { |arg| arg.inspect }.join(', ')
36
+ end
32
37
  end
33
-
34
38
  end
35
39
  end
@@ -51,6 +51,10 @@ module RSpec
51
51
  !matches?(actual)
52
52
  end
53
53
 
54
+ def include(*args)
55
+ singleton_class.__send__(:include, *args)
56
+ end
57
+
54
58
  def define_method(name, &block) # :nodoc:
55
59
  singleton_class.__send__(:define_method, name, &block)
56
60
  end
@@ -1,10 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "should be_predicate" do
4
- it "allows other undefined methods to raise errors as normal" do
5
- expect { some_undefined_method }.to raise_error(NameError)
6
- end
7
-
8
4
  it "passes when actual returns true for :predicate?" do
9
5
  actual = stub("actual", :happy? => true)
10
6
  actual.should be_happy
@@ -14,7 +14,7 @@ describe "should change(actual, message)" do
14
14
  end
15
15
 
16
16
  it "passes when actual is modified by the block" do
17
- expect {@instance.some_value = 6}.to change(@instance, :some_value)
17
+ expect {@instance.some_value = 6.0}.to change(@instance, :some_value)
18
18
  end
19
19
 
20
20
  it "fails when actual is not modified by the block" do
@@ -44,6 +44,57 @@ describe "should change(actual, message)" do
44
44
  end.to fail_with("some_value should have changed, but is still true")
45
45
  end
46
46
  end
47
+
48
+ context "with nil value" do
49
+ before(:each) do
50
+ @instance = SomethingExpected.new
51
+ @instance.some_value = nil
52
+ end
53
+
54
+ it "passes when actual is modified by the block" do
55
+ expect {@instance.some_value = false}.to change(@instance, :some_value)
56
+ end
57
+
58
+ it "fails when actual is not modified by the block" do
59
+ expect do
60
+ expect {}.to change(@instance, :some_value)
61
+ end.to fail_with("some_value should have changed, but is still nil")
62
+ end
63
+ end
64
+
65
+ context "with an array" do
66
+ before(:each) do
67
+ @instance = SomethingExpected.new
68
+ @instance.some_value = []
69
+ end
70
+
71
+ it "passes when actual is modified by the block" do
72
+ expect {@instance.some_value << 1}.to change(@instance, :some_value)
73
+ end
74
+
75
+ it "fails when actual is not modified by the block" do
76
+ expect do
77
+ expect {}.to change(@instance, :some_value)
78
+ end.to fail_with("some_value should have changed, but is still []")
79
+ end
80
+ end
81
+
82
+ context "with a hash" do
83
+ before(:each) do
84
+ @instance = SomethingExpected.new
85
+ @instance.some_value = {:a => 'a'}
86
+ end
87
+
88
+ it "passes when actual is modified by the block" do
89
+ expect {@instance.some_value[:a] = 'A'}.to change(@instance, :some_value)
90
+ end
91
+
92
+ it "fails when actual is not modified by the block" do
93
+ expect do
94
+ expect {}.to change(@instance, :some_value)
95
+ end.to fail
96
+ end
97
+ end
47
98
  end
48
99
 
49
100
  describe "should_not change(actual, message)" do
@@ -273,11 +324,17 @@ describe "should change(actual, message).from(old)" do
273
324
  @instance.some_value = 'string'
274
325
  end
275
326
 
276
- it "passes when attribute is == to expected value before executing block" do
327
+ it "passes when attribute is === to expected value before executing block" do
277
328
  expect { @instance.some_value = "astring" }.to change(@instance, :some_value).from("string")
278
329
  end
279
330
 
280
- it "fails when attribute is not == to expected value before executing block" do
331
+ it "compares the expected and actual values with ===" do
332
+ expected = "string"
333
+ expected.should_receive(:===).and_return true
334
+ expect { @instance.some_value = "astring" }.to change(@instance, :some_value).from(expected)
335
+ end
336
+
337
+ it "fails when attribute is not === to expected value before executing block" do
281
338
  expect do
282
339
  expect { @instance.some_value = "knot" }.to change(@instance, :some_value).from("cat")
283
340
  end.to fail_with("some_value should have initially been \"cat\", but was \"string\"")
@@ -291,11 +348,17 @@ describe "should change{ block }.from(old)" do
291
348
  @instance.some_value = 'string'
292
349
  end
293
350
 
294
- it "passes when attribute is == to expected value before executing block" do
351
+ it "passes when attribute is === to expected value before executing block" do
295
352
  expect { @instance.some_value = "astring" }.to change{@instance.some_value}.from("string")
296
353
  end
297
354
 
298
- it "fails when attribute is not == to expected value before executing block" do
355
+ it "compares the expected and actual values with ===" do
356
+ expected = "string"
357
+ expected.should_receive(:===).and_return true
358
+ expect { @instance.some_value = "astring" }.to change{@instance.some_value}.from(expected)
359
+ end
360
+
361
+ it "fails when attribute is not === to expected value before executing block" do
299
362
  expect do
300
363
  expect { @instance.some_value = "knot" }.to change{@instance.some_value}.from("cat")
301
364
  end.to fail_with("result should have initially been \"cat\", but was \"string\"")
@@ -325,11 +388,17 @@ describe "should change(actual, message).to(new)" do
325
388
  @instance.some_value = 'string'
326
389
  end
327
390
 
328
- it "passes when attribute is == to expected value after executing block" do
391
+ it "passes when attribute is === to expected value after executing block" do
329
392
  expect { @instance.some_value = "cat" }.to change(@instance, :some_value).to("cat")
330
393
  end
331
394
 
332
- it "fails when attribute is not == to expected value after executing block" do
395
+ it "compares the expected and actual values with ===" do
396
+ expected = "cat"
397
+ expected.should_receive(:===).and_return true
398
+ expect { @instance.some_value = "cat" }.to change(@instance, :some_value).to(expected)
399
+ end
400
+
401
+ it "fails when attribute is not === to expected value after executing block" do
333
402
  expect do
334
403
  expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("string").to("dog")
335
404
  end.to fail_with("some_value should have been changed to \"dog\", but is now \"cat\"")
@@ -343,11 +412,17 @@ describe "should change{ block }.to(new)" do
343
412
  @instance.some_value = 'string'
344
413
  end
345
414
 
346
- it "passes when attribute is == to expected value after executing block" do
415
+ it "passes when attribute is === to expected value after executing block" do
347
416
  expect { @instance.some_value = "cat" }.to change{@instance.some_value}.to("cat")
348
417
  end
349
418
 
350
- it "fails when attribute is not == to expected value after executing block" do
419
+ it "compares the expected and actual values with ===" do
420
+ expected = "cat"
421
+ expected.should_receive(:===).and_return true
422
+ expect { @instance.some_value = "cat" }.to change{@instance.some_value}.to(expected)
423
+ end
424
+
425
+ it "fails when attribute is not === to expected value after executing block" do
351
426
  expect do
352
427
  expect { @instance.some_value = "cat" }.to change{@instance.some_value}.from("string").to("dog")
353
428
  end.to fail_with("result should have been changed to \"dog\", but is now \"cat\"")
@@ -9,42 +9,42 @@ describe "Matchers should be able to generate their own descriptions" do
9
9
  "this".should == "this"
10
10
  RSpec::Matchers.generated_description.should == "should == \"this\""
11
11
  end
12
-
12
+
13
13
  it "should not == expected" do
14
14
  "this".should_not == "that"
15
15
  RSpec::Matchers.generated_description.should == "should not == \"that\""
16
16
  end
17
-
17
+
18
18
  it "should be empty (arbitrary predicate)" do
19
19
  [].should be_empty
20
20
  RSpec::Matchers.generated_description.should == "should be empty"
21
21
  end
22
-
22
+
23
23
  it "should not be empty (arbitrary predicate)" do
24
24
  [1].should_not be_empty
25
25
  RSpec::Matchers.generated_description.should == "should not be empty"
26
26
  end
27
-
27
+
28
28
  it "should be true" do
29
29
  true.should be_true
30
30
  RSpec::Matchers.generated_description.should == "should be true"
31
31
  end
32
-
32
+
33
33
  it "should be false" do
34
34
  false.should be_false
35
35
  RSpec::Matchers.generated_description.should == "should be false"
36
36
  end
37
-
37
+
38
38
  it "should be nil" do
39
39
  nil.should be_nil
40
40
  RSpec::Matchers.generated_description.should == "should be nil"
41
41
  end
42
-
42
+
43
43
  it "should be > n" do
44
44
  5.should be > 3
45
45
  RSpec::Matchers.generated_description.should == "should be > 3"
46
46
  end
47
-
47
+
48
48
  it "should be predicate arg1, arg2 and arg3" do
49
49
  5.0.should be_between(0,10)
50
50
  RSpec::Matchers.generated_description.should == "should be between 0 and 10"
@@ -55,42 +55,58 @@ describe "Matchers should be able to generate their own descriptions" do
55
55
  expected.should equal(expected)
56
56
  RSpec::Matchers.generated_description.should == "should equal \"expected\""
57
57
  end
58
-
58
+
59
59
  it "should_not equal" do
60
60
  5.should_not equal(37)
61
61
  RSpec::Matchers.generated_description.should == "should not equal 37"
62
62
  end
63
-
63
+
64
64
  it "should eql" do
65
65
  "string".should eql("string")
66
66
  RSpec::Matchers.generated_description.should == "should eql \"string\""
67
67
  end
68
-
68
+
69
69
  it "should not eql" do
70
70
  "a".should_not eql(:a)
71
71
  RSpec::Matchers.generated_description.should == "should not eql :a"
72
72
  end
73
-
73
+
74
74
  it "should have_key" do
75
75
  {:a => "a"}.should have_key(:a)
76
76
  RSpec::Matchers.generated_description.should == "should have key :a"
77
77
  end
78
-
78
+
79
+ it "should have_some_method" do
80
+ object = Object.new
81
+ def object.has_eyes_closed?; true; end
82
+
83
+ object.should have_eyes_closed
84
+ RSpec::Matchers.generated_description.should == 'should have eyes closed'
85
+ end
86
+
87
+ it "should have_some_method(args*)" do
88
+ object = Object.new
89
+ def object.has_taste_for?(*args); true; end
90
+
91
+ object.should have_taste_for("wine", "cheese")
92
+ RSpec::Matchers.generated_description.should == 'should have taste for "wine", "cheese"'
93
+ end
94
+
79
95
  it "should have n items" do
80
96
  team.should have(3).players
81
97
  RSpec::Matchers.generated_description.should == "should have 3 players"
82
98
  end
83
-
99
+
84
100
  it "should have at least n items" do
85
101
  team.should have_at_least(2).players
86
102
  RSpec::Matchers.generated_description.should == "should have at least 2 players"
87
103
  end
88
-
104
+
89
105
  it "should have at most n items" do
90
106
  team.should have_at_most(4).players
91
107
  RSpec::Matchers.generated_description.should == "should have at most 4 players"
92
108
  end
93
-
109
+
94
110
  it "should include" do
95
111
  [1,2,3].should include(3)
96
112
  RSpec::Matchers.generated_description.should == "should include 3"
@@ -100,42 +116,42 @@ describe "Matchers should be able to generate their own descriptions" do
100
116
  [1,2,3].should =~ [1,2,3]
101
117
  RSpec::Matchers.generated_description.should == "should contain exactly 1, 2 and 3"
102
118
  end
103
-
119
+
104
120
  it "should match" do
105
121
  "this string".should match(/this string/)
106
122
  RSpec::Matchers.generated_description.should == "should match /this string/"
107
123
  end
108
-
124
+
109
125
  it "should raise_error" do
110
126
  lambda { raise }.should raise_error
111
127
  RSpec::Matchers.generated_description.should == "should raise Exception"
112
128
  end
113
-
129
+
114
130
  it "should raise_error with type" do
115
131
  lambda { raise }.should raise_error(RuntimeError)
116
132
  RSpec::Matchers.generated_description.should == "should raise RuntimeError"
117
133
  end
118
-
134
+
119
135
  it "should raise_error with type and message" do
120
136
  lambda { raise "there was an error" }.should raise_error(RuntimeError, "there was an error")
121
137
  RSpec::Matchers.generated_description.should == "should raise RuntimeError with \"there was an error\""
122
138
  end
123
-
139
+
124
140
  it "should respond_to" do
125
141
  [].should respond_to(:insert)
126
142
  RSpec::Matchers.generated_description.should == "should respond to #insert"
127
143
  end
128
-
144
+
129
145
  it "should throw symbol" do
130
146
  lambda { throw :what_a_mess }.should throw_symbol
131
147
  RSpec::Matchers.generated_description.should == "should throw a Symbol"
132
148
  end
133
-
149
+
134
150
  it "should throw symbol (with named symbol)" do
135
151
  lambda { throw :what_a_mess }.should throw_symbol(:what_a_mess)
136
152
  RSpec::Matchers.generated_description.should == "should throw :what_a_mess"
137
153
  end
138
-
154
+
139
155
  def team
140
156
  Class.new do
141
157
  def players
@@ -152,7 +168,7 @@ describe "a Matcher with no description" do
152
168
  def failure_message; ""; end
153
169
  end.new
154
170
  end
155
-
171
+
156
172
  it "provides a helpful message when used in a string-less example block" do
157
173
  5.should matcher
158
174
  RSpec::Matchers.generated_description.should =~ /When you call.*description method/m
@@ -26,7 +26,7 @@ describe "should have_sym(*args)" do
26
26
  Object.new.should have_key(:a)
27
27
  }.should raise_error(NoMethodError)
28
28
  end
29
-
29
+
30
30
  it "reraises an exception thrown in #has_sym?(*args)" do
31
31
  o = Object.new
32
32
  def o.has_sym?(*args)
@@ -60,7 +60,7 @@ describe "should_not have_sym(*args)" do
60
60
  Object.new.should have_key(:a)
61
61
  }.should raise_error(NoMethodError)
62
62
  end
63
-
63
+
64
64
  it "reraises an exception thrown in #has_sym?(*args)" do
65
65
  o = Object.new
66
66
  def o.has_sym?(*args)
@@ -50,7 +50,7 @@ describe "have matcher" do
50
50
  owner.should have(4).items_in_collection_with_size_method
51
51
  }.should fail_with("expected 4 items_in_collection_with_size_method, got 3")
52
52
  end
53
-
53
+
54
54
  it "fails if target has a collection of items with > n members" do
55
55
  owner = create_collection_owner_with(3)
56
56
  lambda {
@@ -63,7 +63,7 @@ describe "have matcher" do
63
63
  end
64
64
 
65
65
  describe 'should have(1).item when ActiveSupport::Inflector is defined' do
66
-
66
+
67
67
  it 'pluralizes the collection name' do
68
68
  owner = create_collection_owner_with(1)
69
69
  owner.should have(1).item
@@ -78,7 +78,7 @@ describe "have matcher" do
78
78
  end
79
79
 
80
80
  end
81
-
81
+
82
82
  after(:each) do
83
83
  unless @active_support_was_defined
84
84
  Object.__send__ :remove_const, :ActiveSupport
@@ -87,7 +87,7 @@ describe "have matcher" do
87
87
  end
88
88
 
89
89
  describe 'should have(1).item when Inflector is defined' do
90
-
90
+
91
91
  before(:each) do
92
92
  if defined?(Inflector)
93
93
  @inflector_was_defined = true
@@ -100,7 +100,7 @@ describe "have matcher" do
100
100
  end
101
101
  end
102
102
  end
103
-
103
+
104
104
  it 'pluralizes the collection name' do
105
105
  owner = create_collection_owner_with(1)
106
106
  owner.should have(1).item
@@ -133,7 +133,7 @@ describe "have matcher" do
133
133
  owner.should_not have(4).items_in_collection_with_length_method
134
134
  owner.should_not have(4).items_in_collection_with_size_method
135
135
  end
136
-
136
+
137
137
  it "passes if target has a collection of items with > n members" do
138
138
  owner = create_collection_owner_with(3)
139
139
  owner.should_not have(2).items_in_collection_with_length_method
@@ -174,7 +174,7 @@ describe "have matcher" do
174
174
  owner.should have_exactly(4).items_in_collection_with_size_method
175
175
  }.should fail_with("expected 4 items_in_collection_with_size_method, got 3")
176
176
  end
177
-
177
+
178
178
  it "fails if target has a collection of items with > n members" do
179
179
  owner = create_collection_owner_with(3)
180
180
  lambda {
@@ -193,7 +193,7 @@ describe "have matcher" do
193
193
  owner.should have_at_least(3).items_in_collection_with_length_method
194
194
  owner.should have_at_least(3).items_in_collection_with_size_method
195
195
  end
196
-
196
+
197
197
  it "passes if target has a collection of items with > n members" do
198
198
  owner = create_collection_owner_with(3)
199
199
  owner.should have_at_least(2).items_in_collection_with_length_method
@@ -209,17 +209,17 @@ describe "have matcher" do
209
209
  owner.should have_at_least(4).items_in_collection_with_size_method
210
210
  }.should fail_with("expected at least 4 items_in_collection_with_size_method, got 3")
211
211
  end
212
-
212
+
213
213
  it "provides educational negative failure messages" do
214
214
  #given
215
215
  owner = create_collection_owner_with(3)
216
216
  length_matcher = have_at_least(3).items_in_collection_with_length_method
217
217
  size_matcher = have_at_least(3).items_in_collection_with_size_method
218
-
218
+
219
219
  #when
220
220
  length_matcher.matches?(owner)
221
221
  size_matcher.matches?(owner)
222
-
222
+
223
223
  #then
224
224
  length_matcher.failure_message_for_should_not.should == <<-EOF
225
225
  Isn't life confusing enough?
@@ -255,7 +255,7 @@ EOF
255
255
  owner.should have_at_most(2).items_in_collection_with_size_method
256
256
  }.should fail_with("expected at most 2 items_in_collection_with_size_method, got 3")
257
257
  end
258
-
258
+
259
259
  it "passes if target has a collection of items with < n members" do
260
260
  owner = create_collection_owner_with(3)
261
261
  owner.should have_at_most(4).items_in_collection_with_length_method
@@ -267,11 +267,11 @@ EOF
267
267
  owner = create_collection_owner_with(3)
268
268
  length_matcher = have_at_most(3).items_in_collection_with_length_method
269
269
  size_matcher = have_at_most(3).items_in_collection_with_size_method
270
-
270
+
271
271
  #when
272
272
  length_matcher.matches?(owner)
273
273
  size_matcher.matches?(owner)
274
-
274
+
275
275
  #then
276
276
  length_matcher.failure_message_for_should_not.should == <<-EOF
277
277
  Isn't life confusing enough?
@@ -280,7 +280,7 @@ Instead of having to figure out the meaning of this:
280
280
  We recommend that you use this instead:
281
281
  should have_at_least(4).items_in_collection_with_length_method
282
282
  EOF
283
-
283
+
284
284
  size_matcher.failure_message_for_should_not.should == <<-EOF
285
285
  Isn't life confusing enough?
286
286
  Instead of having to figure out the meaning of this:
@@ -338,7 +338,7 @@ EOF
338
338
  def @collection.floozles; [1,2] end
339
339
  def @collection.send(*args); raise "DOH! Library developers shouldn't use #send!" end
340
340
  end
341
-
341
+
342
342
  it "works in the straightforward case" do
343
343
  lambda {
344
344
  @collection.should have(2).floozles
@@ -374,24 +374,24 @@ EOF
374
374
  @a_method_which_have_defines = described_class.instance_methods.first
375
375
  @a_method_which_object_defines = Object.instance_methods.first
376
376
  end
377
-
377
+
378
378
  it "is true for a method which Have defines" do
379
379
  @have.should respond_to(@a_method_which_have_defines)
380
380
  end
381
-
381
+
382
382
  it "is true for a method that it's superclass (Object) defines" do
383
383
  @have.should respond_to(@a_method_which_object_defines)
384
384
  end
385
-
385
+
386
386
  it "is false for a method which neither Object nor nor Have defines" do
387
387
  @have.should_not respond_to(:foo_bar_baz)
388
388
  end
389
-
389
+
390
390
  it "is false if the owner doesn't respond to the method" do
391
391
  have = described_class.new(99)
392
392
  have.should_not respond_to(:problems)
393
393
  end
394
-
394
+
395
395
  it "is true if the owner responds to the method" do
396
396
  have = described_class.new(:a_symbol)
397
397
  have.should respond_to(:to_sym)