vcr 1.1.0 → 1.1.1

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 (84) hide show
  1. data/.document +5 -0
  2. data/.gitignore +27 -0
  3. data/CHANGELOG.md +13 -0
  4. data/Gemfile +24 -0
  5. data/Gemfile.lock +119 -0
  6. data/README.md +3 -6
  7. data/Rakefile +70 -0
  8. data/benchmarks/http_stubbing_libraries.rb +59 -0
  9. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/regex_cassette.yml +43 -0
  10. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette1.yml +43 -0
  11. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette2.yml +63 -0
  12. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette3.yml +85 -0
  13. data/features/fixtures/vcr_cassettes/1.9.1/erb_cassette.yml +36 -0
  14. data/features/fixtures/vcr_cassettes/1.9.1/match_requests_on.yml +35 -0
  15. data/features/fixtures/vcr_cassettes/1.9.1/nested_replay_cassette.yml +32 -0
  16. data/features/fixtures/vcr_cassettes/1.9.1/not_the_real_response.yml +43 -0
  17. data/features/fixtures/vcr_cassettes/1.9.1/replay_localhost_cassette.yml +32 -0
  18. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/regex_cassette.yml +43 -0
  19. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette1.yml +43 -0
  20. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette2.yml +47 -0
  21. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette3.yml +85 -0
  22. data/features/fixtures/vcr_cassettes/not_1.9.1/erb_cassette.yml +36 -0
  23. data/features/fixtures/vcr_cassettes/not_1.9.1/match_requests_on.yml +35 -0
  24. data/features/fixtures/vcr_cassettes/not_1.9.1/nested_replay_cassette.yml +24 -0
  25. data/features/fixtures/vcr_cassettes/not_1.9.1/not_the_real_response.yml +43 -0
  26. data/features/fixtures/vcr_cassettes/not_1.9.1/replay_localhost_cassette.yml +32 -0
  27. data/features/http_client.feature +16 -0
  28. data/features/net_http.feature +27 -0
  29. data/features/record_response.feature +66 -0
  30. data/features/replay_recorded_response.feature +96 -0
  31. data/features/step_definitions/http_client_steps.rb +7 -0
  32. data/features/step_definitions/net_http_steps.rb +37 -0
  33. data/features/step_definitions/vcr_steps.rb +240 -0
  34. data/features/support/env.rb +104 -0
  35. data/features/webmock.feature +26 -0
  36. data/lib/vcr.rb +2 -2
  37. data/lib/vcr/extensions/net_http.rb +0 -8
  38. data/lib/vcr/http_stubbing_adapters/common.rb +39 -0
  39. data/lib/vcr/http_stubbing_adapters/fakeweb.rb +74 -70
  40. data/lib/vcr/http_stubbing_adapters/webmock.rb +61 -62
  41. data/lib/vcr/version.rb +1 -1
  42. data/spec/cassette_spec.rb +280 -0
  43. data/spec/config_spec.rb +76 -0
  44. data/spec/cucumber_tags_spec.rb +55 -0
  45. data/spec/deprecations_spec.rb +52 -0
  46. data/spec/extensions/net_http_response_spec.rb +85 -0
  47. data/spec/extensions/net_http_spec.rb +77 -0
  48. data/spec/fixtures/1.9.1/0_3_1_cassette.yml +29 -0
  49. data/spec/fixtures/1.9.1/cassette_spec/erb_with_no_vars.yml +32 -0
  50. data/spec/fixtures/1.9.1/cassette_spec/erb_with_vars.yml +32 -0
  51. data/spec/fixtures/1.9.1/cassette_spec/example.yml +110 -0
  52. data/spec/fixtures/1.9.1/cassette_spec/with_localhost_requests.yml +86 -0
  53. data/spec/fixtures/1.9.1/example_net_http.yml +14 -0
  54. data/spec/fixtures/1.9.1/example_net_http_request.yml +12 -0
  55. data/spec/fixtures/1.9.1/example_net_http_response.yml +25 -0
  56. data/spec/fixtures/1.9.1/fake_example.com_responses.yml +106 -0
  57. data/spec/fixtures/1.9.1/match_requests_on.yml +185 -0
  58. data/spec/fixtures/not_1.9.1/0_3_1_cassette.yml +29 -0
  59. data/spec/fixtures/not_1.9.1/cassette_spec/erb_with_no_vars.yml +32 -0
  60. data/spec/fixtures/not_1.9.1/cassette_spec/erb_with_vars.yml +32 -0
  61. data/spec/fixtures/not_1.9.1/cassette_spec/example.yml +110 -0
  62. data/spec/fixtures/not_1.9.1/cassette_spec/with_localhost_requests.yml +86 -0
  63. data/spec/fixtures/not_1.9.1/example_net_http.yml +14 -0
  64. data/spec/fixtures/not_1.9.1/example_net_http_request.yml +12 -0
  65. data/spec/fixtures/not_1.9.1/example_net_http_response.yml +25 -0
  66. data/spec/fixtures/not_1.9.1/fake_example.com_responses.yml +106 -0
  67. data/spec/fixtures/not_1.9.1/match_requests_on.yml +185 -0
  68. data/spec/http_stubbing_adapters/fakeweb_spec.rb +35 -0
  69. data/spec/http_stubbing_adapters/webmock_spec.rb +35 -0
  70. data/spec/request_matcher_spec.rb +194 -0
  71. data/spec/spec_helper.rb +40 -0
  72. data/spec/structs_spec.rb +121 -0
  73. data/spec/support/disable_warnings.rb +12 -0
  74. data/spec/support/http_library_adapters.rb +272 -0
  75. data/spec/support/http_stubbing_adapter.rb +100 -0
  76. data/spec/support/pending_on_heroku.rb +14 -0
  77. data/spec/support/temp_cassette_library_dir.rb +16 -0
  78. data/spec/support/vcr_localhost_server.rb +53 -0
  79. data/spec/vcr_spec.rb +198 -0
  80. data/spec/version_spec.rb +11 -0
  81. data/vcr.gemspec +43 -0
  82. metadata +134 -73
  83. data/lib/vcr/http_stubbing_adapters/base.rb +0 -36
  84. data/lib/vcr/version.rbc +0 -572
@@ -0,0 +1,185 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :post
5
+ uri: http://example.com:80/method
6
+ body:
7
+ headers:
8
+ response: !ruby/struct:VCR::Response
9
+ status: !ruby/struct:VCR::ResponseStatus
10
+ code: 200
11
+ message: OK
12
+ headers:
13
+ etag:
14
+ - "\"24ec5-1b6-4059a80bfd280\""
15
+ body: post method response
16
+ http_version: "1.1"
17
+ - !ruby/struct:VCR::HTTPInteraction
18
+ request: !ruby/struct:VCR::Request
19
+ method: :get
20
+ uri: http://example.com:80/method
21
+ body:
22
+ headers:
23
+ response: !ruby/struct:VCR::Response
24
+ status: !ruby/struct:VCR::ResponseStatus
25
+ code: 200
26
+ message: OK
27
+ headers:
28
+ etag:
29
+ - "\"24ec5-1b6-4059a80bfd280\""
30
+ body: get method response
31
+ http_version: "1.1"
32
+ - !ruby/struct:VCR::HTTPInteraction
33
+ request: !ruby/struct:VCR::Request
34
+ method: :post
35
+ uri: http://example1.com:80/host
36
+ body:
37
+ headers:
38
+ response: !ruby/struct:VCR::Response
39
+ status: !ruby/struct:VCR::ResponseStatus
40
+ code: 200
41
+ message: OK
42
+ headers:
43
+ etag:
44
+ - "\"24ec5-1b6-4059a80bfd280\""
45
+ body: example1.com host response
46
+ http_version: "1.1"
47
+ - !ruby/struct:VCR::HTTPInteraction
48
+ request: !ruby/struct:VCR::Request
49
+ method: :post
50
+ uri: http://example2.com:80/host
51
+ body:
52
+ headers:
53
+ response: !ruby/struct:VCR::Response
54
+ status: !ruby/struct:VCR::ResponseStatus
55
+ code: 200
56
+ message: OK
57
+ headers:
58
+ etag:
59
+ - "\"24ec5-1b6-4059a80bfd280\""
60
+ body: example2.com host response
61
+ http_version: "1.1"
62
+ - !ruby/struct:VCR::HTTPInteraction
63
+ request: !ruby/struct:VCR::Request
64
+ method: :post
65
+ uri: http://example.com:80/path1
66
+ body:
67
+ headers:
68
+ response: !ruby/struct:VCR::Response
69
+ status: !ruby/struct:VCR::ResponseStatus
70
+ code: 200
71
+ message: OK
72
+ headers:
73
+ etag:
74
+ - "\"24ec5-1b6-4059a80bfd280\""
75
+ body: path1 response
76
+ http_version: "1.1"
77
+ - !ruby/struct:VCR::HTTPInteraction
78
+ request: !ruby/struct:VCR::Request
79
+ method: :post
80
+ uri: http://example.com:80/path2
81
+ body:
82
+ headers:
83
+ response: !ruby/struct:VCR::Response
84
+ status: !ruby/struct:VCR::ResponseStatus
85
+ code: 200
86
+ message: OK
87
+ headers:
88
+ etag:
89
+ - "\"24ec5-1b6-4059a80bfd280\""
90
+ body: path2 response
91
+ http_version: "1.1"
92
+ - !ruby/struct:VCR::HTTPInteraction
93
+ request: !ruby/struct:VCR::Request
94
+ method: :post
95
+ uri: http://example.com:80/uri1
96
+ body:
97
+ headers:
98
+ response: !ruby/struct:VCR::Response
99
+ status: !ruby/struct:VCR::ResponseStatus
100
+ code: 200
101
+ message: OK
102
+ headers:
103
+ etag:
104
+ - "\"24ec5-1b6-4059a80bfd280\""
105
+ body: uri1 response
106
+ http_version: "1.1"
107
+ - !ruby/struct:VCR::HTTPInteraction
108
+ request: !ruby/struct:VCR::Request
109
+ method: :post
110
+ uri: http://example.com:80/uri2
111
+ body:
112
+ headers:
113
+ response: !ruby/struct:VCR::Response
114
+ status: !ruby/struct:VCR::ResponseStatus
115
+ code: 200
116
+ message: OK
117
+ headers:
118
+ etag:
119
+ - "\"24ec5-1b6-4059a80bfd280\""
120
+ body: uri2 response
121
+ http_version: "1.1"
122
+ - !ruby/struct:VCR::HTTPInteraction
123
+ request: !ruby/struct:VCR::Request
124
+ method: :post
125
+ uri: http://example.com:80/
126
+ body: param=val1
127
+ headers:
128
+ response: !ruby/struct:VCR::Response
129
+ status: !ruby/struct:VCR::ResponseStatus
130
+ code: 200
131
+ message: OK
132
+ headers:
133
+ etag:
134
+ - "\"24ec5-1b6-4059a80bfd280\""
135
+ body: val1 body response
136
+ http_version: "1.1"
137
+ - !ruby/struct:VCR::HTTPInteraction
138
+ request: !ruby/struct:VCR::Request
139
+ method: :post
140
+ uri: http://example.com:80/
141
+ body: param=val2
142
+ headers:
143
+ response: !ruby/struct:VCR::Response
144
+ status: !ruby/struct:VCR::ResponseStatus
145
+ code: 200
146
+ message: OK
147
+ headers:
148
+ etag:
149
+ - "\"24ec5-1b6-4059a80bfd280\""
150
+ body: val2 body response
151
+ http_version: "1.1"
152
+ - !ruby/struct:VCR::HTTPInteraction
153
+ request: !ruby/struct:VCR::Request
154
+ method: :post
155
+ uri: http://example.com:80/
156
+ body:
157
+ headers:
158
+ x-http-header1:
159
+ - val1
160
+ response: !ruby/struct:VCR::Response
161
+ status: !ruby/struct:VCR::ResponseStatus
162
+ code: 200
163
+ message: OK
164
+ headers:
165
+ etag:
166
+ - "\"24ec5-1b6-4059a80bfd280\""
167
+ body: val1 header response
168
+ http_version: "1.1"
169
+ - !ruby/struct:VCR::HTTPInteraction
170
+ request: !ruby/struct:VCR::Request
171
+ method: :post
172
+ uri: http://example.com:80/
173
+ body:
174
+ headers:
175
+ x-http-header1:
176
+ - val2
177
+ response: !ruby/struct:VCR::Response
178
+ status: !ruby/struct:VCR::ResponseStatus
179
+ code: 200
180
+ message: OK
181
+ headers:
182
+ etag:
183
+ - "\"24ec5-1b6-4059a80bfd280\""
184
+ body: val2 header response
185
+ http_version: "1.1"
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe VCR::HttpStubbingAdapters::FakeWeb do
4
+ it_should_behave_like 'an http stubbing adapter', ['net/http'], [:method, :uri, :host, :path]
5
+
6
+ describe '#check_version!' do
7
+ disable_warnings
8
+ before(:each) { @orig_version = FakeWeb::VERSION }
9
+ after(:each) { FakeWeb::VERSION = @orig_version }
10
+
11
+ %w( 1.2.8 1.1.30 0.30.30 ).each do |version|
12
+ it "raises an error when FakeWeb's version is #{version}" do
13
+ FakeWeb::VERSION = version
14
+ described_class.should_not_receive(:warn)
15
+ expect { described_class.check_version! }.to raise_error(/You are using FakeWeb #{version}. VCR requires version .* or greater/)
16
+ end
17
+ end
18
+
19
+ %w( 1.3.0 1.3.1 1.3.99 ).each do |version|
20
+ it "does nothing when FakeWeb's version is #{version}" do
21
+ FakeWeb::VERSION = version
22
+ described_class.should_not_receive(:warn)
23
+ expect { described_class.check_version! }.to_not raise_error
24
+ end
25
+ end
26
+
27
+ %w( 1.4.0 1.10.0 2.0.0 ).each do |version|
28
+ it "prints a warning when FakeWeb's version is #{version}" do
29
+ FakeWeb::VERSION = version
30
+ described_class.should_receive(:warn).with(/VCR is known to work with FakeWeb ~> .*\./)
31
+ expect { described_class.check_version! }.to_not raise_error
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe VCR::HttpStubbingAdapters::WebMock do
4
+ it_should_behave_like 'an http stubbing adapter',
5
+ %w[net/http patron httpclient em-http-request],
6
+ [:method, :uri, :host, :path, :body, :headers]
7
+
8
+ describe '#check_version!' do
9
+ before(:each) { WebMock.should respond_to(:version) }
10
+
11
+ %w( 0.9.9 0.9.10 0.1.30 1.0.30 1.2.9 1.3.2 ).each do |version|
12
+ it "raises an error when WebMock's version is #{version}" do
13
+ WebMock.stub!(:version).and_return(version)
14
+ described_class.should_not_receive(:warn)
15
+ expect { described_class.check_version! }.to raise_error(/You are using WebMock #{version}. VCR requires version .* or greater/)
16
+ end
17
+ end
18
+
19
+ %w( 1.3.3 1.3.10 1.3.99 ).each do |version|
20
+ it "does nothing when WebMock's version is #{version}" do
21
+ WebMock.stub!(:version).and_return(version)
22
+ described_class.should_not_receive(:warn)
23
+ expect { described_class.check_version! }.to_not raise_error
24
+ end
25
+ end
26
+
27
+ %w( 1.4.0 1.10.0 2.0.0 ).each do |version|
28
+ it "does nothing when WebMock's version is #{version}" do
29
+ WebMock.stub!(:version).and_return(version)
30
+ described_class.should_receive(:warn).with(/VCR is known to work with WebMock ~> .*\./)
31
+ expect { described_class.check_version! }.to_not raise_error
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,194 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe VCR::RequestMatcher do
4
+ it 'raises an error when given invalid match attributes' do
5
+ expect {
6
+ VCR::RequestMatcher.new(VCR::Request.new, [:not, :valid, :options])
7
+ }.to raise_error(ArgumentError)
8
+ end
9
+
10
+ describe '#uri' do
11
+ def self.for_matcher(*attributes, &block)
12
+ context "for match_attributes = #{attributes.inspect}" do
13
+ subject { matcher = VCR::RequestMatcher.new(stub(:uri => uri), attributes).uri }
14
+ module_eval(&block)
15
+ end
16
+ end
17
+
18
+ let(:uri) { 'http://foo.example.com/path/to/something?param=value' }
19
+
20
+ for_matcher do
21
+ it("returns a regex that matches any URI") { should == /.*/ }
22
+ end
23
+
24
+ for_matcher :uri do
25
+ it("returns the exact uri") { should == uri }
26
+ end
27
+
28
+ for_matcher :host do
29
+ it("matches a basic URL for the same host") { should =~ 'http://foo.example.com/some/path' }
30
+ it("matches an https URL") { should =~ 'https://foo.example.com/some/path' }
31
+ it("ignores the case of the URL") { should =~ 'HTTP://FOO.EXAMPLE.COM/SOME/PATH' }
32
+ it("matches when the URL has the normal port") { should =~ 'http://foo.example.com:80/some/path' }
33
+ it("matches when the URL has another port") { should =~ 'http://foo.example.com:3750/some/path' }
34
+ it("matches when the URL has a username") { should =~ 'http://someone@foo.example.com/some/path' }
35
+ it("matches when the URL has a username and password") { should =~ 'http://admin:s3cr3t@foo.example.com/some/path' }
36
+
37
+ it("does not match when the host is wrong") { should_not =~ 'http://fof.example.com/path/to/something?param=value' }
38
+ it("does not match when the host includes some additional parts") { should_not =~ 'http://foo.example.com.more.domain.parts/path/to/something?param=value' }
39
+ end
40
+
41
+ for_matcher :path do
42
+ it("matches a basic URL for the same path") { should =~ 'http://domain.tld/path/to/something?p=v&q=r' }
43
+ it("matches an https URL") { should =~ 'http://domain.tld/path/to/something?p=v&q=r' }
44
+ it("ignores the case of the URL") { should =~ 'HTTP://DOMAIN.TLD/PATH/TO/SOMETHING?P=V&Q=R' }
45
+ it("matches with a trailing slash") { should =~ 'http://domain.tld/path/to/something/' }
46
+ it("matches without a trailing slash") { should =~ 'http://domain.tld/path/to/something' }
47
+ it("matches when the URL has the normal port") { should =~ 'http://domain.tld:80/path/to/something' }
48
+ it("matches when the URL has another port") { should =~ 'http://domain.tld:3750/path/to/something' }
49
+ it("matches when the URL has a username") { should =~ 'http://someone@domain.tld/path/to/something' }
50
+ it("matches when the URL has a username and password") { should =~ 'http://admin:s3cr3t@domain.tld/path/to/something' }
51
+
52
+ it("does not match when the path is wrong") { should_not =~ 'http://foo.example.com/some/other/path?param=value' }
53
+ it("does not match when the path includes some additional parts") { should_not =~ 'http://foo.example.com/path/to/something/else?param=value' }
54
+ end
55
+
56
+ for_matcher :host, :path do
57
+ it("matches a basic URL for the same host and path") { should =~ 'http://foo.example.com/path/to/something?p=v' }
58
+ it("matches an https URL") { should =~ 'https://foo.example.com/path/to/something?p=v&q=r' }
59
+ it("ignores the case of the URL") { should =~ 'HTTP://FOO.EXAMPLE.COM/PATH/TO/SOMETHING?P=V&Q=R' }
60
+ it("matches with a trailing slash and some query params") { should =~ 'http://foo.example.com/path/to/something/?p=v&q=r' }
61
+ it("matches with a trailing slash and no query params") { should =~ 'http://foo.example.com/path/to/something/' }
62
+ it("matches without a trailing slash and some query params") { should =~ 'http://foo.example.com/path/to/something?p=v&q=r' }
63
+ it("matches without a trailing slash and no query params") { should =~ 'http://foo.example.com/path/to/something' }
64
+ it("matches when the URL has the normal port") { should =~ 'http://foo.example.com:80/path/to/something?p=v' }
65
+ it("matches when the URL has another port") { should =~ 'http://foo.example.com:3750/path/to/something?p=v' }
66
+ it("matches when the URL has a username") { should =~ 'http://someone@foo.example.com/path/to/something?p=v' }
67
+ it("matches when the URL has a username and password") { should =~ 'http://admin:s3r3t@foo.example.com/path/to/something?p=v' }
68
+
69
+ it("does not match when the host is wrong") { should_not =~ 'http://fof.example.com/path/to/something?p=v' }
70
+ it("does not match when the path is wrong") { should_not =~ 'http://foo.example.com/pth/to/something?p=v' }
71
+ it("does not match when the host includes some additional parts") { should_not =~ 'http://foo.example.com.and.more.parts/path/to/something?p=v' }
72
+ it("does not match when the path includes some additional parts") { should_not =~ 'http://foo.example.com/path/to/something/else?p=v' }
73
+ end
74
+
75
+ [[:uri, :host], [:uri, :path], [:uri, :host, :path]].each do |attributes|
76
+ for_matcher *attributes do
77
+ it "raises an appropriate error" do
78
+ expect { subject }.to raise_error(/match_attributes cannot include/)
79
+ end
80
+ end
81
+ end
82
+
83
+ it "returns the request's URI when it is a regex, regardless of the match attributes" do
84
+ [:uri, :host, :path].each do |attribute|
85
+ matcher = VCR::RequestMatcher.new(stub(:uri => /some regex/), [attribute])
86
+ matcher.uri.should == /some regex/
87
+ end
88
+ end
89
+ end
90
+
91
+ describe '#method' do
92
+ it 'returns the request method when the match attributes include :method' do
93
+ matcher = VCR::RequestMatcher.new(stub(:method => :get), [:method])
94
+ matcher.method.should == :get
95
+ end
96
+
97
+ it 'returns nil when the match attributes do not include :method' do
98
+ matcher = VCR::RequestMatcher.new(stub(:method => :get), [])
99
+ matcher.method.should be_nil
100
+ end
101
+ end
102
+
103
+ describe '#body' do
104
+ it 'returns the request body when the match attributes include :body' do
105
+ matcher = VCR::RequestMatcher.new(stub(:body => 'id=7'), [:body])
106
+ matcher.body.should == 'id=7'
107
+ end
108
+
109
+ it 'returns nil when the match attributes do not include :body' do
110
+ matcher = VCR::RequestMatcher.new(stub(:body => 'id=7'), [])
111
+ matcher.method.should be_nil
112
+ end
113
+ end
114
+
115
+ describe '#headers' do
116
+ it 'returns the request headers when the match attributes include :headers' do
117
+ matcher = VCR::RequestMatcher.new(stub(:headers => { 'key' => 'value' }), [:headers])
118
+ matcher.headers.should == { 'key' => 'value' }
119
+ end
120
+
121
+ it 'returns nil when the match attributes do not include :headers' do
122
+ matcher = VCR::RequestMatcher.new(stub(:headers => { 'key' => 'value' }), [])
123
+ matcher.headers.should be_nil
124
+ end
125
+ end
126
+
127
+ def matcher(*different_values)
128
+ match_attributes = [:method, :uri, :body, :headers]
129
+ if different_values.include?(:match_attributes)
130
+ match_attributes -= [:body]
131
+ end
132
+
133
+ request_object = different_values.include?(:request) ? 'request2' : 'request'
134
+ m = VCR::RequestMatcher.new(request_object, match_attributes)
135
+
136
+ %w( uri method body headers ).each do |attr|
137
+ m.should respond_to(attr)
138
+ m.stub!(attr).and_return(different_values.include?(attr.to_sym) ? attr.next : attr)
139
+ end
140
+
141
+ m
142
+ end
143
+
144
+ def matchers_varying_on(attribute)
145
+ return matcher, matcher(attribute)
146
+ end
147
+
148
+ describe '#hash' do
149
+ it 'returns the same code for two objects when #match_attributes, #method, #uri, #body and #headers are the same, even when the request object is different' do
150
+ m1, m2 = matchers_varying_on(:request)
151
+ m1.hash.should == m2.hash
152
+ end
153
+
154
+ it 'returns the same code for two objects when the matchers are the same, but #match_attributes has its elements in a different order' do
155
+ m1, m2 = matcher, matcher
156
+ m1.match_attributes = [:method, :uri, :body, :headers]
157
+ m2.match_attributes = [:method, :body, :uri, :headers]
158
+ m1.hash.should == m2.hash
159
+ end
160
+
161
+ [:match_attributes, :method, :uri, :body, :headers].each do |different_attr|
162
+ it "returns different codes for two objects when ##{different_attr} is different, even when the request object is the same" do
163
+ m1, m2 = matchers_varying_on(different_attr)
164
+ m1.hash.should_not == m2.hash
165
+ end
166
+ end
167
+ end
168
+
169
+ [:eql?, :==].each do |equality_method|
170
+ describe "##{equality_method.to_s}" do
171
+ it 'returns true when #match_attributes, #method, #uri, #body and #headers are the same, even when the request object is different' do
172
+ m1, m2 = matchers_varying_on(:request)
173
+ m1.send(equality_method, m2).should be_true
174
+ m2.send(equality_method, m1).should be_true
175
+ end
176
+
177
+ it 'returns true when the matchers are the same, but #match_attributes has its elements in a different order' do
178
+ m1, m2 = matcher, matcher
179
+ m1.match_attributes = [:method, :uri, :body, :headers]
180
+ m2.match_attributes = [:method, :body, :uri, :headers]
181
+ m1.send(equality_method, m2).should be_true
182
+ m2.send(equality_method, m1).should be_true
183
+ end
184
+
185
+ [:match_attributes, :method, :uri, :body, :headers].each do |different_attr|
186
+ it "returns false when ##{different_attr} is different, even when the request object is the same" do
187
+ m1, m2 = matchers_varying_on(different_attr)
188
+ m1.send(equality_method, m2).should be_false
189
+ m2.send(equality_method, m1).should be_false
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end