rspec-expectations 2.10.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. data/Changelog.md +24 -1
  2. data/README.md +36 -2
  3. data/features/built_in_matchers/be.feature +52 -14
  4. data/features/syntax_configuration.feature +68 -0
  5. data/lib/rspec/expectations.rb +2 -0
  6. data/lib/rspec/expectations/expectation_target.rb +52 -0
  7. data/lib/rspec/expectations/extensions.rb +0 -1
  8. data/lib/rspec/expectations/syntax.rb +105 -0
  9. data/lib/rspec/expectations/version.rb +1 -1
  10. data/lib/rspec/matchers.rb +12 -5
  11. data/lib/rspec/matchers/built_in/base_matcher.rb +16 -7
  12. data/lib/rspec/matchers/built_in/be.rb +27 -25
  13. data/lib/rspec/matchers/built_in/be_instance_of.rb +3 -5
  14. data/lib/rspec/matchers/built_in/be_kind_of.rb +3 -5
  15. data/lib/rspec/matchers/built_in/be_within.rb +17 -11
  16. data/lib/rspec/matchers/built_in/cover.rb +5 -6
  17. data/lib/rspec/matchers/built_in/eq.rb +4 -8
  18. data/lib/rspec/matchers/built_in/eql.rb +3 -5
  19. data/lib/rspec/matchers/built_in/equal.rb +6 -10
  20. data/lib/rspec/matchers/built_in/exist.rb +11 -13
  21. data/lib/rspec/matchers/built_in/include.rb +5 -6
  22. data/lib/rspec/matchers/built_in/match.rb +3 -4
  23. data/lib/rspec/matchers/built_in/match_array.rb +7 -14
  24. data/lib/rspec/matchers/built_in/start_and_end_with.rb +1 -3
  25. data/lib/rspec/matchers/built_in/yield.rb +2 -5
  26. data/lib/rspec/matchers/configuration.rb +66 -0
  27. data/spec/rspec/expectations/expectation_target_spec.rb +65 -0
  28. data/spec/rspec/expectations/extensions/kernel_spec.rb +22 -0
  29. data/spec/rspec/matchers/base_matcher_spec.rb +8 -6
  30. data/spec/rspec/matchers/be_spec.rb +2 -2
  31. data/spec/rspec/matchers/be_within_spec.rb +9 -1
  32. data/spec/rspec/matchers/configuration_spec.rb +160 -0
  33. data/spec/rspec/matchers/eq_spec.rb +16 -4
  34. data/spec/rspec/matchers/equal_spec.rb +7 -7
  35. data/spec/rspec/matchers/match_array_spec.rb +12 -0
  36. data/spec/rspec/matchers/yield_spec.rb +3 -3
  37. data/spec/support/in_sub_process.rb +31 -0
  38. metadata +16 -9
  39. data/lib/rspec/expectations/extensions/kernel.rb +0 -26
  40. data/lib/rspec/matchers/block_aliases.rb +0 -21
  41. data/spec/rspec/matchers/compatibility_spec.rb +0 -28
@@ -1,9 +1,7 @@
1
1
  module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
- class StartAndEndWith
5
- include BaseMatcher
6
-
4
+ class StartAndEndWith < BaseMatcher
7
5
  def initialize(*expected)
8
6
  @expected = expected.length == 1 ? expected.first : expected
9
7
  end
@@ -64,9 +64,7 @@ module RSpec
64
64
  end
65
65
  end
66
66
 
67
- class YieldControl
68
- include BaseMatcher
69
-
67
+ class YieldControl < BaseMatcher
70
68
  def matches?(block)
71
69
  probe = YieldProbe.probe(block)
72
70
  probe.yielded_once?(:yield_control)
@@ -81,8 +79,7 @@ module RSpec
81
79
  end
82
80
  end
83
81
 
84
- class YieldWithNoArgs
85
- include BaseMatcher
82
+ class YieldWithNoArgs < BaseMatcher
86
83
 
87
84
  def matches?(block)
88
85
  @probe = YieldProbe.probe(block)
@@ -0,0 +1,66 @@
1
+ require 'rspec/expectations/syntax'
2
+
3
+ module RSpec
4
+ module Matchers
5
+ # Provides configuration options for rspec-expectations.
6
+ class Configuration
7
+ # Configures the supported syntax.
8
+ # @param [Array<Symbol>, Symbol] values the syntaxes to enable
9
+ # @example
10
+ # RSpec.configure do |rspec|
11
+ # rspec.expect_with :rspec do |c|
12
+ # c.syntax = :should
13
+ # # or
14
+ # c.syntax = :expect
15
+ # # or
16
+ # c.syntax = [:should, :expect]
17
+ # end
18
+ # end
19
+ def syntax=(values)
20
+ if Array(values).include?(:expect)
21
+ Expectations::Syntax.enable_expect
22
+ else
23
+ Expectations::Syntax.disable_expect
24
+ end
25
+
26
+ if Array(values).include?(:should)
27
+ Expectations::Syntax.enable_should
28
+ else
29
+ Expectations::Syntax.disable_should
30
+ end
31
+ end
32
+
33
+ # The list of configured syntaxes.
34
+ # @return [Array<Symbol>] the list of configured syntaxes.
35
+ def syntax
36
+ syntaxes = []
37
+ syntaxes << :should if Expectations::Syntax.should_enabled?
38
+ syntaxes << :expect if Expectations::Syntax.expect_enabled?
39
+ syntaxes
40
+ end
41
+
42
+ # Adds `should` and `should_not` to the given classes
43
+ # or modules. This can be used to ensure `should` works
44
+ # properly on things like proxy objects (particular
45
+ # `Delegator`-subclassed objects on 1.8).
46
+ #
47
+ # @param [Array<Module>] modules the list of classes or modules
48
+ # to add `should` and `should_not` to.
49
+ def add_should_and_should_not_to(*modules)
50
+ modules.each do |mod|
51
+ Expectations::Syntax.enable_should(mod)
52
+ end
53
+ end
54
+ end
55
+
56
+ # The configuration object
57
+ # @return [RSpec::Matchers::Configuration] the configuration object
58
+ def self.configuration
59
+ @configuration ||= Configuration.new
60
+ end
61
+
62
+ # set default syntax
63
+ configuration.syntax = [:expect, :should]
64
+ end
65
+ end
66
+
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ module RSpec
4
+ module Expectations
5
+ # so our examples below can set expectations about the target
6
+ ExpectationTarget.send(:attr_reader, :target)
7
+
8
+ describe ExpectationTarget do
9
+ context 'when constructed via #expect' do
10
+ it 'constructs a new instance targetting the given argument' do
11
+ expect(7).target.should eq(7)
12
+ end
13
+
14
+ it 'constructs a new instance targetting the given block' do
15
+ block = lambda {}
16
+ expect(&block).target.should be(block)
17
+ end
18
+
19
+ it 'raises an ArgumentError when given an argument and a block' do
20
+ lambda { expect(7) { } }.should raise_error(ArgumentError)
21
+ end
22
+
23
+ it 'raises an ArgumentError when given neither an argument nor a block' do
24
+ lambda { expect }.should raise_error(ArgumentError)
25
+ end
26
+
27
+ it 'can be passed nil' do
28
+ expect(nil).target.should be_nil
29
+ end
30
+
31
+ it 'passes a valid positive expectation' do
32
+ expect(5).to eq(5)
33
+ end
34
+
35
+ it 'passes a valid negative expectation' do
36
+ expect(5).to_not eq(4)
37
+ expect(5).not_to eq(4)
38
+ end
39
+
40
+ it 'fails an invalid positive expectation' do
41
+ lambda { expect(5).to eq(4) }.should fail_with(/expected: 4.*got: 5/m)
42
+ end
43
+
44
+ it 'fails an invalid negative expectation' do
45
+ message = /expected 5 not to be a kind of Fixnum/
46
+ lambda { expect(5).to_not be_a(Fixnum) }.should fail_with(message)
47
+ lambda { expect(5).not_to be_a(Fixnum) }.should fail_with(message)
48
+ end
49
+
50
+ it 'does not support operator matchers from #to' do
51
+ expect {
52
+ expect(3).to == 3
53
+ }.to raise_error(ArgumentError)
54
+ end
55
+
56
+ it 'does not support operator matchers from #not_to' do
57
+ expect {
58
+ expect(3).not_to == 4
59
+ }.to raise_error(ArgumentError)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
@@ -20,6 +20,28 @@ describe Object, "#should" do
20
20
  @target.should @matcher
21
21
  }.should fail_with("the failure message")
22
22
  end
23
+
24
+ context "on interpretters that have BasicObject", :if => defined?(BasicObject) do
25
+ let(:proxy_class) do
26
+ Class.new(BasicObject) do
27
+ def initialize(target)
28
+ @target = target
29
+ end
30
+
31
+ def proxied?
32
+ true
33
+ end
34
+
35
+ def method_missing(name, *args)
36
+ @target.send(name, *args)
37
+ end
38
+ end
39
+ end
40
+
41
+ it 'works properly on BasicObject-subclassed proxy objects' do
42
+ proxy_class.new(Object.new).should be_proxied
43
+ end
44
+ end
23
45
  end
24
46
 
25
47
  describe Object, "#should_not" do
@@ -2,9 +2,7 @@ module RSpec::Matchers::BuiltIn
2
2
  describe BaseMatcher do
3
3
  describe "#match_unless_raises" do
4
4
  let(:matcher) do
5
- Class.new do
6
- include BaseMatcher
7
- end.new
5
+ Class.new(BaseMatcher).new
8
6
  end
9
7
 
10
8
  it "returns true if there are no errors" do
@@ -41,12 +39,16 @@ module RSpec::Matchers::BuiltIn
41
39
 
42
40
  describe "#==" do
43
41
  it "responds the same way as matches?" do
44
- matcher = Class.new do
45
- include BaseMatcher
42
+ matcher = Class.new(BaseMatcher) do
43
+ def initialize(expected)
44
+ @expected = expected
45
+ end
46
+
46
47
  def matches?(actual)
47
- actual == expected
48
+ (@actual = actual) == @expected
48
49
  end
49
50
  end
51
+
50
52
  matcher.new(3).matches?(3).should be_true
51
53
  matcher.new(3).should eq(3)
52
54
 
@@ -237,7 +237,7 @@ describe "should be_true" do
237
237
  it "fails when actual equal?(false)" do
238
238
  lambda {
239
239
  false.should be_true
240
- }.should fail_with("expected false to be true")
240
+ }.should fail_with("expected: true value\n got: false")
241
241
  end
242
242
  end
243
243
 
@@ -253,7 +253,7 @@ describe "should be_false" do
253
253
  it "fails when actual equal?(true)" do
254
254
  lambda {
255
255
  true.should be_false
256
- }.should fail_with("expected true to be false")
256
+ }.should fail_with("expected: false value\n got: true")
257
257
  end
258
258
  end
259
259
 
@@ -57,7 +57,15 @@ module RSpec
57
57
 
58
58
  it "raises an error if no expected value is given" do
59
59
  matcher = be_within(0.5)
60
- expect { matcher.matches?(5.1) }.to raise_error(ArgumentError, /must set an expected value using #of/)
60
+ expect { matcher.matches?(5.1) }.to raise_error(
61
+ ArgumentError, /must set an expected value using #of/
62
+ )
63
+ end
64
+
65
+ it "raises an error if the actual value is not of a Numeric type" do
66
+ expect { be_within(0.1).of(0).matches?(nil) }.to raise_error(
67
+ ArgumentError, /The actual value \(nil\) must be of a `Numeric` type/
68
+ )
61
69
  end
62
70
  end
63
71
  end
@@ -0,0 +1,160 @@
1
+ require 'spec_helper'
2
+ require 'delegate'
3
+
4
+ module RSpec
5
+ module Matchers
6
+ describe ".configuration" do
7
+ it 'returns a memoized configuration instance' do
8
+ RSpec::Matchers.configuration.should be_a(RSpec::Matchers::Configuration)
9
+ RSpec::Matchers.configuration.should be(RSpec::Matchers.configuration)
10
+ end
11
+
12
+ context 'on an interpreter that does not provide BasicObject', :unless => defined?(::BasicObject) do
13
+ before { RSpec::Expectations::Syntax.disable_should(Delegator) }
14
+
15
+ let(:klass) do
16
+ Class.new(SimpleDelegator) do
17
+ def delegated?; true; end
18
+ end
19
+ end
20
+
21
+ let(:instance) { klass.new(Object.new) }
22
+
23
+ it 'provides a means to manually add it Delegator' do
24
+ instance.should_not respond_to(:delegated?) # because #should is being delegated...
25
+ RSpec::Matchers.configuration.add_should_and_should_not_to Delegator
26
+ instance.should respond_to(:delegated?) # now it should work!
27
+ end
28
+ end
29
+ end
30
+
31
+ shared_examples_for "configuring the expectation syntax" do
32
+ # We want a sandboxed method that ensures that we wind up with
33
+ # both syntaxes properly enabled when the example ends.
34
+ #
35
+ # On platforms that fork, using a sub process is the easiest,
36
+ # most robust way to achieve that.
37
+ #
38
+ # On jRuby we just re-enable both syntaxes at the end of the example;
39
+ # however, this is a generally inferior approach because it depends on
40
+ # the code-under-test working properly; if it doesn't work properly,
41
+ # it could leave things in a "broken" state where tons of other examples fail.
42
+ if RUBY_PLATFORM == "java"
43
+ def sandboxed
44
+ yield
45
+ ensure
46
+ configure_syntax([:should, :expect])
47
+ end
48
+ else
49
+ include InSubProcess
50
+ alias sandboxed in_sub_process
51
+ end
52
+
53
+ it 'is configured to :should and :expect by default' do
54
+ configured_syntax.should eq([:should, :expect])
55
+
56
+ 3.should eq(3)
57
+ 3.should_not eq(4)
58
+ expect(3).to eq(3)
59
+ end
60
+
61
+ it 'can limit the syntax to :should' do
62
+ sandboxed do
63
+ configure_syntax :should
64
+ configured_syntax.should eq([:should])
65
+
66
+ 3.should eq(3)
67
+ 3.should_not eq(4)
68
+ lambda { expect(6).to eq(6) }.should raise_error(NameError)
69
+ end
70
+ end
71
+
72
+ it 'is a no-op when configured to :should twice' do
73
+ sandboxed do
74
+ ::Kernel.stub(:method_added).and_raise("no methods should be added here")
75
+
76
+ configure_syntax :should
77
+ configure_syntax :should
78
+ end
79
+ end
80
+
81
+ it 'can limit the syntax to :expect' do
82
+ sandboxed do
83
+ configure_syntax :expect
84
+ expect(configured_syntax).to eq([:expect])
85
+
86
+ expect(3).to eq(3)
87
+ expect { 3.should eq(3) }.to raise_error(NameError)
88
+ expect { 3.should_not eq(3) }.to raise_error(NameError)
89
+ end
90
+ end
91
+
92
+ it 'is a no-op when configured to :expect twice' do
93
+ sandboxed do
94
+ RSpec::Matchers.stub(:method_added).and_raise("no methods should be added here")
95
+
96
+ configure_syntax :expect
97
+ configure_syntax :expect
98
+ end
99
+ end
100
+
101
+ it 'can re-enable the :should syntax' do
102
+ sandboxed do
103
+ configure_syntax :expect
104
+ configure_syntax [:should, :expect]
105
+ configured_syntax.should eq([:should, :expect])
106
+
107
+ 3.should eq(3)
108
+ 3.should_not eq(4)
109
+ expect(3).to eq(3)
110
+ end
111
+ end
112
+
113
+ it 'can re-enable the :expect syntax' do
114
+ sandboxed do
115
+ configure_syntax :should
116
+ configure_syntax [:should, :expect]
117
+ configured_syntax.should eq([:should, :expect])
118
+
119
+ 3.should eq(3)
120
+ 3.should_not eq(4)
121
+ expect(3).to eq(3)
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "configuring rspec-expectations directly" do
127
+ it_behaves_like "configuring the expectation syntax" do
128
+ def configure_syntax(syntax)
129
+ RSpec::Matchers.configuration.syntax = syntax
130
+ end
131
+
132
+ def configured_syntax
133
+ RSpec::Matchers.configuration.syntax
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "configuring using the rspec-core config API" do
139
+ it_behaves_like "configuring the expectation syntax" do
140
+ def configure_syntax(syntax)
141
+ RSpec.configure do |rspec|
142
+ rspec.expect_with :rspec do |c|
143
+ c.syntax = syntax
144
+ end
145
+ end
146
+ end
147
+
148
+ def configured_syntax
149
+ RSpec.configure do |rspec|
150
+ rspec.expect_with :rspec do |c|
151
+ return c.syntax
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ end
159
+ end
160
+
@@ -14,23 +14,35 @@ module RSpec
14
14
  it "does not match when actual != expected" do
15
15
  1.should_not eq(2)
16
16
  end
17
-
17
+
18
+ it "compares by sending == to actual (not expected)" do
19
+ called = false
20
+ actual = Class.new do
21
+ define_method :== do |other|
22
+ called = true
23
+ end
24
+ end.new
25
+
26
+ actual.should eq :anything # to trigger the matches? method
27
+ called.should be_true
28
+ end
29
+
18
30
  it "describes itself" do
19
31
  matcher = eq(1)
20
32
  matcher.matches?(1)
21
- matcher.description.should == "eq 1"
33
+ matcher.description.should eq "eq 1"
22
34
  end
23
35
 
24
36
  it "provides message, expected and actual on #failure_message" do
25
37
  matcher = eq("1")
26
38
  matcher.matches?(1)
27
- matcher.failure_message_for_should.should == "\nexpected: \"1\"\n got: 1\n\n(compared using ==)\n"
39
+ matcher.failure_message_for_should.should eq "\nexpected: \"1\"\n got: 1\n\n(compared using ==)\n"
28
40
  end
29
41
 
30
42
  it "provides message, expected and actual on #negative_failure_message" do
31
43
  matcher = eq(1)
32
44
  matcher.matches?(1)
33
- matcher.failure_message_for_should_not.should == "\nexpected: value != 1\n got: 1\n\n(compared using ==)\n"
45
+ matcher.failure_message_for_should_not.should eq "\nexpected: value != 1\n got: 1\n\n(compared using ==)\n"
34
46
  end
35
47
  end
36
48
  end