vcr 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  #Changelog
2
2
 
3
+ ## 0.4.1 May 11, 2010
4
+ * Fixed a bug: when `Net::HTTPResponse#read_body` was called after VCR had read the body to record a new request,
5
+ it raised an error (`IOError: Net::HTTPResponse#read_body called twice`). My fix extends Net::HTTPResponse
6
+ so that it no longer raises this error.
7
+
3
8
  ## 0.4.0 April 28, 2010
4
9
  * Added support for webmock. All the fakeweb-specific code is now in an adapter (as is the webmock code).
5
10
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.4.1
@@ -32,6 +32,9 @@ VCR.module_eval do
32
32
  end
33
33
 
34
34
  After do |scenario|
35
+ if raised_error = (@http_requests || {}).values.flatten.detect { |result| result.is_a?(Exception) && result.message !~ /VCR/ }
36
+ raise raised_error
37
+ end
35
38
  VCR.completed_cucumber_scenarios << scenario
36
39
  end
37
40
 
data/lib/vcr.rb CHANGED
@@ -4,6 +4,7 @@ require 'vcr/cucumber_tags'
4
4
  require 'vcr/deprecations'
5
5
  require 'vcr/structs'
6
6
 
7
+ require 'vcr/extensions/net_http_response'
7
8
  require 'vcr/extensions/net_read_adapter'
8
9
 
9
10
  require 'vcr/http_stubbing_adapters/base'
@@ -28,6 +28,7 @@ module Net
28
28
 
29
29
  unless VCR.http_stubbing_adapter.request_stubbed?(method, uri)
30
30
  cassette.record_http_interaction(VCR::HTTPInteraction.from_net_http_objects(self, request, response))
31
+ response.extend VCR::Net::HTTPResponse
31
32
  end
32
33
  end
33
34
  end
@@ -0,0 +1,48 @@
1
+ # A Net::HTTP response that has already been read raises an IOError when #read_body
2
+ # is called with a destination string or block.
3
+ #
4
+ # This causes a problem when VCR records a response--it reads the body before yielding
5
+ # the response, and if the code that is consuming the HTTP requests uses #read_body, it
6
+ # can cause an error.
7
+ #
8
+ # This is a bit of a hack, but it allows a Net::HTTP response to be "re-read"
9
+ # after it has aleady been read. This attemps to preserve the behavior of
10
+ # #read_body, acting just as if it had never been read.
11
+
12
+ module VCR
13
+ module Net
14
+ module HTTPResponse
15
+ def self.extended(object)
16
+ body_object = object.instance_variable_get(:@body)
17
+ object.instance_variable_set(:@__orig_body__,
18
+ case body_object
19
+ when String then body_object
20
+ when ::Net::ReadAdapter then body_object.instance_variable_get(:@__body_for_vcr__)
21
+ else raise ArgumentError.new("Unexpected body object: #{body_object}")
22
+ end
23
+ )
24
+ end
25
+
26
+ def read_body(dest = nil, &block)
27
+ if @__orig_body__
28
+ if dest && block
29
+ raise ArgumentError.new("both arg and block given for HTTP method")
30
+ elsif dest
31
+ dest << @__orig_body__
32
+ elsif block
33
+ @body = ::Net::ReadAdapter.new(block)
34
+ @body << @__orig_body__
35
+ @body
36
+ else
37
+ @body = @__orig_body__
38
+ end
39
+ else
40
+ super
41
+ end
42
+ ensure
43
+ # allow subsequent calls to #read_body to proceed as normal, without our hack...
44
+ @__orig_body__ = nil
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,86 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Net::HTTP Response extensions" do
4
+ context 'extending an already read response' do
5
+ # disable VCR for this spec...
6
+ before(:each) { VCR.insert_cassette('response_extension', :allow_real_http => lambda { |uri| true }) }
7
+ after(:each) { VCR.eject_cassette }
8
+
9
+ def self.it_allows_the_body_to_be_read_again
10
+ let(:expected_regex) { /You have reached this web page by typing.*example\.com/ }
11
+
12
+ it 'allows the body to be read using #body' do
13
+ subject.body.to_s.should =~ expected_regex
14
+ end
15
+
16
+ it 'allows the body to be read using #read_body' do
17
+ subject.read_body.to_s.should =~ expected_regex
18
+ end
19
+
20
+ it 'allows the body to be read using #read_body with a block' do
21
+ yielded_body = ''
22
+ ret_val = subject.read_body { |s| yielded_body << s }
23
+ yielded_body.should =~ expected_regex
24
+ ret_val.should be_instance_of(Net::ReadAdapter)
25
+ end
26
+
27
+ it 'allows the body to be read by passing a destination string to #read_body' do
28
+ dest = ''
29
+ ret_val = subject.read_body(dest)
30
+ dest.should =~ expected_regex
31
+ ret_val.should == dest
32
+ end
33
+
34
+ it 'raises an ArgumentError if both a destination string and a block is given to #read_body' do
35
+ dest = ''
36
+ expect { subject.read_body(dest) { |s| } }.should raise_error(ArgumentError, 'both arg and block given for HTTP method')
37
+ end
38
+
39
+ it 'raises an IOError when #read_body is called twice with a block' do
40
+ subject.read_body { |s| }
41
+ expect { subject.read_body { |s| } }.to raise_error(IOError, /read_body called twice/)
42
+ end
43
+
44
+ it 'raises an IOError when #read_body is called twice with a destination string' do
45
+ dest = ''
46
+ subject.read_body(dest)
47
+ expect { subject.read_body(dest) }.to raise_error(IOError, /read_body called twice/)
48
+ end
49
+ end
50
+
51
+ context 'when the body has already been read using #read_body and a block' do
52
+ subject do
53
+ http = Net::HTTP.new('example.com', 80)
54
+ response = http.request_get('/') { |res| res.read_body { |s| } }
55
+ response.extend VCR::Net::HTTPResponse
56
+ response
57
+ end
58
+
59
+ it_allows_the_body_to_be_read_again
60
+ end
61
+
62
+ context 'when the body has already been read using #read_body and a dest string' do
63
+ subject do
64
+ http = Net::HTTP.new('example.com', 80)
65
+ dest = ''
66
+ response = http.request_get('/') { |res| res.read_body(dest) }
67
+ response.extend VCR::Net::HTTPResponse
68
+ response
69
+ end
70
+
71
+ it_allows_the_body_to_be_read_again
72
+ end
73
+
74
+ context 'when the body has already been read using #body' do
75
+ subject do
76
+ http = Net::HTTP.new('example.com', 80)
77
+ response = http.request_get('/')
78
+ response.body
79
+ response.extend VCR::Net::HTTPResponse
80
+ response
81
+ end
82
+
83
+ it_allows_the_body_to_be_read_again
84
+ end
85
+ end
86
+ end
data/vcr.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{vcr}
8
- s.version = "0.4.0"
8
+ s.version = "0.4.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Myron Marston"]
12
- s.date = %q{2010-04-28}
12
+ s.date = %q{2010-05-11}
13
13
  s.description = %q{VCR provides helpers to record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests. It works with any ruby testing framework, and provides built-in support for cucumber.}
14
14
  s.email = %q{myron.marston@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -51,6 +51,7 @@ Gem::Specification.new do |s|
51
51
  "lib/vcr/deprecations.rb",
52
52
  "lib/vcr/extensions/fake_web.rb",
53
53
  "lib/vcr/extensions/net_http.rb",
54
+ "lib/vcr/extensions/net_http_response.rb",
54
55
  "lib/vcr/extensions/net_read_adapter.rb",
55
56
  "lib/vcr/http_stubbing_adapters/base.rb",
56
57
  "lib/vcr/http_stubbing_adapters/fakeweb.rb",
@@ -62,6 +63,7 @@ Gem::Specification.new do |s|
62
63
  "spec/config_spec.rb",
63
64
  "spec/cucumber_tags_spec.rb",
64
65
  "spec/deprecations_spec.rb",
66
+ "spec/extensions/net_http_response_spec.rb",
65
67
  "spec/extensions/net_http_spec.rb",
66
68
  "spec/extensions/net_read_adapter_spec.rb",
67
69
  "spec/fixtures/1.8.6/0_3_1_cassette.yml",
@@ -105,6 +107,7 @@ Gem::Specification.new do |s|
105
107
  "spec/config_spec.rb",
106
108
  "spec/cucumber_tags_spec.rb",
107
109
  "spec/deprecations_spec.rb",
110
+ "spec/extensions/net_http_response_spec.rb",
108
111
  "spec/extensions/net_http_spec.rb",
109
112
  "spec/extensions/net_read_adapter_spec.rb",
110
113
  "spec/http_stubbing_adapters/fakeweb_spec.rb",
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 4
8
- - 0
9
- version: 0.4.0
8
+ - 1
9
+ version: 0.4.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Myron Marston
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-28 00:00:00 -07:00
17
+ date: 2010-05-11 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -117,6 +117,7 @@ files:
117
117
  - lib/vcr/deprecations.rb
118
118
  - lib/vcr/extensions/fake_web.rb
119
119
  - lib/vcr/extensions/net_http.rb
120
+ - lib/vcr/extensions/net_http_response.rb
120
121
  - lib/vcr/extensions/net_read_adapter.rb
121
122
  - lib/vcr/http_stubbing_adapters/base.rb
122
123
  - lib/vcr/http_stubbing_adapters/fakeweb.rb
@@ -128,6 +129,7 @@ files:
128
129
  - spec/config_spec.rb
129
130
  - spec/cucumber_tags_spec.rb
130
131
  - spec/deprecations_spec.rb
132
+ - spec/extensions/net_http_response_spec.rb
131
133
  - spec/extensions/net_http_spec.rb
132
134
  - spec/extensions/net_read_adapter_spec.rb
133
135
  - spec/fixtures/1.8.6/0_3_1_cassette.yml
@@ -195,6 +197,7 @@ test_files:
195
197
  - spec/config_spec.rb
196
198
  - spec/cucumber_tags_spec.rb
197
199
  - spec/deprecations_spec.rb
200
+ - spec/extensions/net_http_response_spec.rb
198
201
  - spec/extensions/net_http_spec.rb
199
202
  - spec/extensions/net_read_adapter_spec.rb
200
203
  - spec/http_stubbing_adapters/fakeweb_spec.rb