vcr 2.0.0.beta2 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +0 -2
  3. data/CHANGELOG.md +22 -1
  4. data/CONTRIBUTING.md +46 -0
  5. data/Gemfile +1 -9
  6. data/README.md +8 -2
  7. data/Rakefile +12 -1
  8. data/cucumber.yml +8 -9
  9. data/features/.nav +10 -4
  10. data/features/cassettes/format.feature +1 -1
  11. data/features/cassettes/no_cassette.feature +8 -11
  12. data/features/configuration/allow_http_connections_when_no_cassette.feature +4 -4
  13. data/features/configuration/filter_sensitive_data.feature +3 -0
  14. data/features/configuration/hook_into.feature +4 -8
  15. data/features/configuration/ignore_request.feature +191 -0
  16. data/features/getting_started.md +38 -21
  17. data/features/hooks/after_http_request.feature +44 -0
  18. data/features/hooks/around_http_request.feature +56 -0
  19. data/features/hooks/before_http_request.feature +44 -0
  20. data/features/hooks/before_playback.feature +181 -0
  21. data/features/hooks/before_record.feature +172 -0
  22. data/features/middleware/faraday.feature +7 -3
  23. data/features/record_modes/none.feature +2 -1
  24. data/features/record_modes/once.feature +2 -1
  25. data/features/request_matching/body.feature +2 -2
  26. data/features/request_matching/custom_matcher.feature +2 -2
  27. data/features/request_matching/headers.feature +2 -2
  28. data/features/request_matching/host.feature +2 -2
  29. data/features/request_matching/identical_request_sequence.feature +2 -2
  30. data/features/request_matching/method.feature +2 -2
  31. data/features/request_matching/path.feature +2 -2
  32. data/features/request_matching/playback_repeats.feature +2 -1
  33. data/features/request_matching/uri.feature +2 -2
  34. data/features/support/env.rb +21 -12
  35. data/features/test_frameworks/cucumber.feature +9 -4
  36. data/features/test_frameworks/{rspec.feature → rspec_macro.feature} +7 -7
  37. data/features/test_frameworks/rspec_metadata.feature +90 -0
  38. data/lib/vcr.rb +1 -1
  39. data/lib/vcr/cassette.rb +3 -3
  40. data/lib/vcr/cassette/http_interaction_list.rb +13 -9
  41. data/lib/vcr/cassette/migrator.rb +1 -1
  42. data/lib/vcr/configuration.rb +37 -0
  43. data/lib/vcr/errors.rb +172 -6
  44. data/lib/vcr/library_hooks.rb +4 -6
  45. data/lib/vcr/library_hooks/excon.rb +23 -11
  46. data/lib/vcr/library_hooks/fakeweb.rb +85 -24
  47. data/lib/vcr/library_hooks/faraday.rb +30 -2
  48. data/lib/vcr/library_hooks/typhoeus.rb +25 -3
  49. data/lib/vcr/library_hooks/webmock.rb +25 -36
  50. data/lib/vcr/middleware/faraday.rb +23 -5
  51. data/lib/vcr/request_handler.rb +12 -1
  52. data/lib/vcr/request_ignorer.rb +12 -1
  53. data/lib/vcr/request_matcher_registry.rb +1 -9
  54. data/lib/vcr/structs.rb +32 -2
  55. data/lib/vcr/test_frameworks/rspec.rb +28 -0
  56. data/lib/vcr/util/hooks.rb +12 -4
  57. data/lib/vcr/util/version_checker.rb +2 -0
  58. data/lib/vcr/version.rb +1 -1
  59. data/spec/fixtures/cassette_spec/example.yml +1 -1
  60. data/spec/fixtures/{fake_example.com_responses.yml → fake_example_responses.yml} +0 -0
  61. data/spec/monkey_patches.rb +1 -1
  62. data/spec/spec_helper.rb +3 -1
  63. data/spec/support/http_library_adapters.rb +4 -3
  64. data/spec/support/shared_example_groups/hook_into_http_library.rb +194 -12
  65. data/spec/support/shared_example_groups/request_hooks.rb +58 -0
  66. data/spec/support/shared_example_groups/version_checking.rb +5 -0
  67. data/spec/support/sinatra_app.rb +17 -9
  68. data/spec/support/vcr_stub_helpers.rb +17 -0
  69. data/spec/vcr/cassette/http_interaction_list_spec.rb +28 -29
  70. data/spec/vcr/cassette/migrator_spec.rb +6 -7
  71. data/spec/vcr/cassette_spec.rb +5 -5
  72. data/spec/vcr/configuration_spec.rb +51 -32
  73. data/spec/vcr/deprecations_spec.rb +0 -8
  74. data/spec/vcr/errors_spec.rb +129 -0
  75. data/spec/vcr/library_hooks/excon_spec.rb +21 -4
  76. data/spec/vcr/library_hooks/fakeweb_spec.rb +71 -3
  77. data/spec/vcr/library_hooks/faraday_spec.rb +45 -0
  78. data/spec/vcr/library_hooks/typhoeus_spec.rb +31 -1
  79. data/spec/vcr/library_hooks/webmock_spec.rb +26 -3
  80. data/spec/vcr/middleware/faraday_spec.rb +84 -1
  81. data/spec/vcr/request_ignorer_spec.rb +16 -0
  82. data/spec/vcr/request_matcher_registry_spec.rb +0 -26
  83. data/spec/vcr/structs_spec.rb +61 -1
  84. data/spec/vcr/test_frameworks/rspec_spec.rb +32 -0
  85. data/spec/vcr/util/hooks_spec.rb +73 -63
  86. data/spec/vcr_spec.rb +2 -2
  87. data/vcr.gemspec +5 -5
  88. metadata +51 -31
  89. data/features/configuration/hooks.feature +0 -270
  90. data/features/configuration/ignore_hosts.feature +0 -61
  91. data/features/configuration/ignore_localhost.feature +0 -97
@@ -85,44 +85,43 @@ module VCR
85
85
  let(:allow_playback_repeats) { false } # the default
86
86
  let(:list) { HTTPInteractionList.new(original_list_array, [:method], allow_playback_repeats) }
87
87
 
88
- describe "#has_interaction_matching?" do
89
- it_behaves_like "an HTTP interaction finding method", :has_interaction_matching? do
90
- def respond_with(value)
91
- ::RSpec::Matchers::Matcher.new :respond_with, value do |expected|
92
- match { |a| expected ? a : !a }
93
- end
94
- end
88
+ describe "#has_used_interaction_matching?" do
89
+ it 'returns false when no interactions have been used' do
90
+ list.should_not have_used_interaction_matching(request_with(:method => :put))
95
91
  end
96
92
 
97
- it 'does not consume the first matching interaction' do
98
- 10.times do
99
- list.has_interaction_matching?(request_with(:method => :post)).should be_true
100
- end
101
- list.response_for(request_with(:method => :post)).body.should eq("post response 1")
93
+ it 'returns true when there is a matching used interaction (even if there is also an unused one that matches)' do
94
+ list.response_for(request_with(:method => :post))
95
+ list.should have_used_interaction_matching(request_with(:method => :post))
102
96
  end
103
97
 
104
- context 'when allow_playback_repeats is set to false' do
105
- let(:allow_playback_repeats) { false }
98
+ it 'returns false when none of the used interactions match' do
99
+ list.response_for(request_with(:method => :put))
100
+ list.should_not have_used_interaction_matching(request_with(:method => :post))
101
+ end
102
+ end
106
103
 
107
- it 'returns false when there is a used (but no unused) matching interactions' do
108
- list.response_for(request_with(:method => :put))
104
+ describe "#remaining_unused_interaction_count" do
105
+ it 'returns the number of unused interactions' do
106
+ list.remaining_unused_interaction_count.should eq(3)
109
107
 
110
- 10.times.map {
111
- list.has_interaction_matching?(request_with(:method => :put))
112
- }.should eq([false] * 10)
113
- end
114
- end
108
+ list.response_for(request_with(:method => :get))
109
+ list.remaining_unused_interaction_count.should eq(3)
115
110
 
116
- context 'when allow_playback_repeats is set to true' do
117
- let(:allow_playback_repeats) { true }
111
+ list.response_for(request_with(:method => :put))
112
+ list.remaining_unused_interaction_count.should eq(2)
118
113
 
119
- it 'returns true when there is a used (but no unused) matching interactions' do
120
- list.response_for(request_with(:method => :put))
114
+ list.response_for(request_with(:method => :put))
115
+ list.remaining_unused_interaction_count.should eq(2)
121
116
 
122
- 10.times.map {
123
- list.has_interaction_matching?(request_with(:method => :put))
124
- }.should eq([true] * 10)
125
- end
117
+ list.response_for(request_with(:method => :post))
118
+ list.remaining_unused_interaction_count.should eq(1)
119
+
120
+ list.response_for(request_with(:method => :post))
121
+ list.remaining_unused_interaction_count.should eq(0)
122
+
123
+ list.response_for(request_with(:method => :post))
124
+ list.remaining_unused_interaction_count.should eq(0)
126
125
  end
127
126
  end
128
127
 
@@ -80,17 +80,16 @@ http_interactions:
80
80
  body: Hello bar
81
81
  http_version: "1.1"
82
82
  recorded_at: Wed, 04 May 2011 12:30:00 GMT
83
- recorded_with: VCR 1.11.3
83
+ recorded_with: VCR #{VCR.version}
84
84
  EOF
85
85
  }
86
86
 
87
- attr_accessor :dir
87
+ let(:dir) { './tmp/migrator' }
88
88
 
89
- around(:each) do |example|
90
- Dir.mktmpdir do |dir|
91
- self.dir = dir
92
- example.run
93
- end
89
+ before(:each) do
90
+ # ensure the directory is empty
91
+ FileUtils.rm_rf dir
92
+ FileUtils.mkdir_p dir
94
93
  end
95
94
 
96
95
  # JRuby serializes YAML with some slightly different whitespace.
@@ -330,7 +330,7 @@ describe VCR::Cassette do
330
330
  VCR.stub(:http_interactions => stub)
331
331
  VCR.configuration.cassette_library_dir = "#{VCR::SPEC_ROOT}/fixtures/cassette_spec"
332
332
  cassette = VCR::Cassette.new('example', :record => record_mode, :exclusive => true)
333
- cassette.http_interactions.parent_list.should be_a(VCR::Cassette::HTTPInteractionList::NullList)
333
+ cassette.http_interactions.parent_list.should be(VCR::Cassette::HTTPInteractionList::NullList)
334
334
  end
335
335
 
336
336
  it "instantiates the http_interactions with parent_list set to VCR.http_interactions if given :exclusive => false" do
@@ -342,7 +342,7 @@ describe VCR::Cassette do
342
342
 
343
343
  if stub_requests
344
344
  it 'invokes the appropriately tagged before_playback hooks' do
345
- VCR.configuration.should_receive(:invoke_hook).with(
345
+ VCR.configuration.should_receive(:invoke_tagged_hook).with(
346
346
  :before_playback,
347
347
  :foo,
348
348
  an_instance_of(VCR::HTTPInteraction),
@@ -367,14 +367,14 @@ describe VCR::Cassette do
367
367
  VCR.configuration.cassette_library_dir = "#{VCR::SPEC_ROOT}/fixtures/cassette_spec"
368
368
  cassette = VCR::Cassette.new('example', :record => record_mode, :match_requests_on => [:body, :headers])
369
369
  cassette.http_interactions.interactions.should have(3).interactions
370
- cassette.http_interactions.request_matchers.should == [:body, :headers]
370
+ cassette.http_interactions.request_matchers.should eq([:body, :headers].map { |m| VCR.request_matchers[m] })
371
371
  end
372
372
  else
373
373
  it 'instantiates the http_interactions with the no interactions and the request matchers' do
374
374
  VCR.configuration.cassette_library_dir = "#{VCR::SPEC_ROOT}/fixtures/cassette_spec"
375
375
  cassette = VCR::Cassette.new('example', :record => record_mode, :match_requests_on => [:body, :headers])
376
376
  cassette.http_interactions.interactions.should have(0).interactions
377
- cassette.http_interactions.request_matchers.should == [:body, :headers]
377
+ cassette.http_interactions.request_matchers.should eq([:body, :headers].map { |m| VCR.request_matchers[m] })
378
378
  end
379
379
  end
380
380
  end
@@ -403,7 +403,7 @@ describe VCR::Cassette do
403
403
  cassette.stub!(:new_recorded_interactions).and_return(interactions)
404
404
 
405
405
  interactions.each do |i|
406
- VCR.configuration.should_receive(:invoke_hook).with(
406
+ VCR.configuration.should_receive(:invoke_tagged_hook).with(
407
407
  :before_record,
408
408
  :foo,
409
409
  i,
@@ -92,6 +92,15 @@ describe VCR::Configuration do
92
92
  end
93
93
  end
94
94
 
95
+ describe '#ignore_request' do
96
+ it 'registers the given block with the request ignorer' do
97
+ block_called = false
98
+ subject.ignore_request { |r| block_called = true }
99
+ VCR.request_ignorer.ignore?(stub(:uri => 'http://foo.com/'))
100
+ block_called.should be_true
101
+ end
102
+ end
103
+
95
104
  describe '#allow_http_connections_when_no_cassette=' do
96
105
  [true, false].each do |val|
97
106
  it "sets the allow_http_connections_when_no_cassette to #{val} when set to #{val}" do
@@ -101,47 +110,57 @@ describe VCR::Configuration do
101
110
  end
102
111
  end
103
112
 
104
- describe '#filter_sensitive_data' do
105
- let(:interaction) { mock('interaction') }
106
- before(:each) { interaction.stub(:filter!) }
113
+ %w[ filter_sensitive_data define_cassette_placeholder ].each do |method|
114
+ describe "##{method}" do
115
+ let(:interaction) { mock('interaction') }
116
+ before(:each) { interaction.stub(:filter!) }
107
117
 
108
- it 'adds a before_record hook that replaces the string returned by the block with the given string' do
109
- subject.filter_sensitive_data('foo', &lambda { 'bar' })
110
- interaction.should_receive(:filter!).with('bar', 'foo')
111
- subject.invoke_hook(:before_record, nil, interaction)
112
- end
118
+ it 'adds a before_record hook that replaces the string returned by the block with the given string' do
119
+ subject.send(method, 'foo', &lambda { 'bar' })
120
+ interaction.should_receive(:filter!).with('bar', 'foo')
121
+ subject.invoke_hook(:before_record, interaction)
122
+ end
113
123
 
114
- it 'adds a before_playback hook that replaces the given string with the string returned by the block' do
115
- subject.filter_sensitive_data('foo', &lambda { 'bar' })
116
- interaction.should_receive(:filter!).with('foo', 'bar')
117
- subject.invoke_hook(:before_playback, nil, interaction)
118
- end
124
+ it 'adds a before_playback hook that replaces the given string with the string returned by the block' do
125
+ subject.send(method, 'foo', &lambda { 'bar' })
126
+ interaction.should_receive(:filter!).with('foo', 'bar')
127
+ subject.invoke_hook(:before_playback, interaction)
128
+ end
119
129
 
120
- it 'tags the before_record hook when given a tag' do
121
- subject.should_receive(:before_record).with(:my_tag)
122
- subject.filter_sensitive_data('foo', :my_tag) { 'bar' }
123
- end
130
+ it 'tags the before_record hook when given a tag' do
131
+ subject.should_receive(:before_record).with(:my_tag)
132
+ subject.send(method, 'foo', :my_tag) { 'bar' }
133
+ end
124
134
 
125
- it 'tags the before_playback hook when given a tag' do
126
- subject.should_receive(:before_playback).with(:my_tag)
127
- subject.filter_sensitive_data('foo', :my_tag) { 'bar' }
128
- end
135
+ it 'tags the before_playback hook when given a tag' do
136
+ subject.should_receive(:before_playback).with(:my_tag)
137
+ subject.send(method, 'foo', :my_tag) { 'bar' }
138
+ end
129
139
 
130
- it 'yields the interaction to the block for the before_record hook' do
131
- yielded_interaction = nil
132
- subject.filter_sensitive_data('foo', &lambda { |i| yielded_interaction = i; 'bar' })
133
- subject.invoke_hook(:before_record, nil, interaction)
134
- yielded_interaction.should equal(interaction)
135
- end
140
+ it 'yields the interaction to the block for the before_record hook' do
141
+ yielded_interaction = nil
142
+ subject.send(method, 'foo', &lambda { |i| yielded_interaction = i; 'bar' })
143
+ subject.invoke_hook(:before_record, interaction)
144
+ yielded_interaction.should equal(interaction)
145
+ end
136
146
 
137
- it 'yields the interaction to the block for the before_playback hook' do
138
- yielded_interaction = nil
139
- subject.filter_sensitive_data('foo', &lambda { |i| yielded_interaction = i; 'bar' })
140
- subject.invoke_hook(:before_playback, nil, interaction)
141
- yielded_interaction.should equal(interaction)
147
+ it 'yields the interaction to the block for the before_playback hook' do
148
+ yielded_interaction = nil
149
+ subject.send(method, 'foo', &lambda { |i| yielded_interaction = i; 'bar' })
150
+ subject.invoke_hook(:before_playback, interaction)
151
+ yielded_interaction.should equal(interaction)
152
+ end
142
153
  end
143
154
  end
144
155
 
156
+ describe "#around_http_request, when called on ruby 1.8" do
157
+ it 'raises an error since fibers are not available' do
158
+ expect {
159
+ subject.around_http_request { }
160
+ }.to raise_error(/requires fibers, which are not available/)
161
+ end
162
+ end if RUBY_VERSION < '1.9'
163
+
145
164
  describe "#cassette_serializers" do
146
165
  let(:custom_serializer) { stub }
147
166
  it 'allows a custom serializer to be registered' do
@@ -73,14 +73,6 @@ describe VCR, 'deprecations', :disable_warnings do
73
73
  end
74
74
  end
75
75
 
76
- describe "VCR.configure { |c| c.stub_with :faraday }" do
77
- it 'prints a descriptive warning' do
78
- Kernel.should_receive(:warn).with(/Just use `VCR::Middleware::Faraday` in your faraday stack/)
79
- # simulate the loading of the adapter (since it may have already been required)
80
- load 'vcr/library_hooks/faraday.rb'
81
- end
82
- end
83
-
84
76
  describe "VCR::Middleware::Faraday" do
85
77
  it 'prints a deprecation warning when passed a block' do
86
78
  Kernel.should_receive(:warn).with(/Passing a block .* is deprecated/)
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ module VCR
4
+ module Errors
5
+ describe UnhandledHTTPRequestError do
6
+ def message_for(request_values = {})
7
+ described_class.new(request_with request_values).message
8
+ end
9
+ alias message message_for
10
+
11
+ def request_with(values)
12
+ VCR::Request.new.tap do |request|
13
+ values.each do |name, value|
14
+ request.send("#{name}=", value)
15
+ end
16
+ end
17
+ end
18
+
19
+ it 'identifies the request by method and URI' do
20
+ message_for(:method => :post, :uri => 'http://foo.com/').should include(
21
+ 'POST http://foo.com/'
22
+ )
23
+ end
24
+
25
+ context 'when there is no current cassette' do
26
+ it 'mentions that there is no current cassette' do
27
+ message.should include('There is currently no cassette in use.')
28
+ end
29
+
30
+ it 'mentions that the request can be recorded by inserting a cassette' do
31
+ message.should match(/record this request and play it back.*VCR.use_cassette/m)
32
+ end
33
+
34
+ it 'mentions the allow_http_connections_when_no_cassette option' do
35
+ message.should include('allow_http_connections_when_no_cassette')
36
+ end
37
+
38
+ it 'mentions that the request can be ignored' do
39
+ message.should include('set an `ignore_request` callback')
40
+ end
41
+
42
+ it 'does not double-insert the asterisks for the bullet points' do
43
+ message.should_not match(/\s+\*\s+\*/)
44
+ end
45
+ end
46
+
47
+ context 'when there is a current cassette' do
48
+ it 'mentions the details about the current casette' do
49
+ VCR.use_cassette('example') do
50
+ message.should match(/VCR is currently using the following cassette:.+example.yml/m)
51
+ end
52
+ end
53
+
54
+ it 'mentions that :new_episodes can be used to record the request' do
55
+ VCR.use_cassette('example') do
56
+ message.should include('use the :new_episodes record mode')
57
+ end
58
+ end
59
+
60
+ it 'mentions that :once does not allow a cassette to be re-recorded' do
61
+ VCR.use_cassette('example', :record => :once) do
62
+ message.should include('(:once) does not allow new requests to be recorded')
63
+ end
64
+ end
65
+
66
+ it 'mentions that :none does not allow any recording' do
67
+ VCR.use_cassette('example', :record => :none) do
68
+ message.should include('(:none) does not allow requests to be recorded')
69
+ end
70
+ end
71
+
72
+ it 'does not mention the :once or :none record modes if using the :new_episodes record mode' do
73
+ VCR.use_cassette('example', :record => :new_episodes) do
74
+ message.should_not include(':once', ':none')
75
+ end
76
+ end
77
+
78
+ it 'mentions :allow_playback_repeats if the current cassette has a used matching interaction' do
79
+ VCR.use_cassette('example') do |cassette|
80
+ cassette.http_interactions.should respond_to(:has_used_interaction_matching?)
81
+ cassette.http_interactions.stub(:has_used_interaction_matching? => true)
82
+ message.should include('allow_playback_repeats')
83
+ end
84
+ end
85
+
86
+ it 'does not mention :allow_playback_repeats if the current cassette does not have a used matching interaction' do
87
+ VCR.use_cassette('example') do |cassette|
88
+ cassette.http_interactions.should respond_to(:has_used_interaction_matching?)
89
+ cassette.http_interactions.stub(:has_used_interaction_matching? => false)
90
+ message.should_not include('allow_playback_repeats')
91
+ end
92
+ end
93
+
94
+ it 'does not mention using a different :match_requests_on option when there are no remaining unused interactions' do
95
+ VCR.use_cassette('example') do |cassette|
96
+ cassette.http_interactions.should respond_to(:remaining_unused_interaction_count)
97
+ cassette.http_interactions.stub(:remaining_unused_interaction_count => 0)
98
+ message.should_not include('match_requests_on cassette option')
99
+ end
100
+ end
101
+
102
+ it 'mentions using a different :match_requests_on option when there are some remaining unused interactions' do
103
+ VCR.use_cassette('example') do |cassette|
104
+ cassette.http_interactions.should respond_to(:remaining_unused_interaction_count)
105
+ cassette.http_interactions.stub(:remaining_unused_interaction_count => 1)
106
+ message.should include('match_requests_on cassette option')
107
+ end
108
+ end
109
+
110
+ it 'uses the singular (HTTP interaction) when there is only 1 left' do
111
+ VCR.use_cassette('example') do |cassette|
112
+ cassette.http_interactions.should respond_to(:remaining_unused_interaction_count)
113
+ cassette.http_interactions.stub(:remaining_unused_interaction_count => 1)
114
+ message.should include('1 HTTP interaction ')
115
+ end
116
+ end
117
+
118
+ it 'uses the plural (HTTP interactions) when there is more than 1 left' do
119
+ VCR.use_cassette('example') do |cassette|
120
+ cassette.http_interactions.should respond_to(:remaining_unused_interaction_count)
121
+ cassette.http_interactions.stub(:remaining_unused_interaction_count => 2)
122
+ message.should include('2 HTTP interactions ')
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+
@@ -1,12 +1,18 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Excon hook" do
4
- it_behaves_like 'a hook into an HTTP library', 'excon', :status_message_not_exposed
4
+ # TODO: figure out a way to get disabling VCR to work with Excon
5
+ # and allow dirct excon stubs to work.
6
+ # def directly_stub_request(method, url, response_body)
7
+ # ::Excon.stub({ :method => method, :url => url }, { :body => response_body })
8
+ # end
9
+
10
+ it_behaves_like 'a hook into an HTTP library', :excon, 'excon', :status_message_not_exposed
5
11
 
6
12
  it_performs('version checking', 'Excon',
7
- :valid => %w[ 0.6.5 0.6.99 ],
13
+ :valid => %w[ 0.6.5 0.7.9 ],
8
14
  :too_low => %w[ 0.5.99 0.6.4 ],
9
- :too_high => %w[ 0.7.0 1.0.0 ]
15
+ :too_high => %w[ 0.8.0 1.0.0 ]
10
16
  ) do
11
17
  before(:each) { @orig_version = Excon::VERSION }
12
18
  after(:each) { Excon::VERSION = @orig_version }
@@ -54,9 +60,11 @@ describe "Excon hook" do
54
60
  end
55
61
 
56
62
  context 'when Excon raises an error due to an unexpected response status' do
57
- it 'still records properly' do
63
+ before(:each) do
58
64
  VCR.stub(:real_http_connections_allowed? => true)
65
+ end
59
66
 
67
+ it 'still records properly' do
60
68
  VCR.should_receive(:record_http_interaction) do |interaction|
61
69
  interaction.response.status.code.should eq(404)
62
70
  end
@@ -65,6 +73,15 @@ describe "Excon hook" do
65
73
  Excon.get("http://localhost:#{VCR::SinatraApp.port}/not_found", :expects => 200)
66
74
  }.to raise_error(Excon::Errors::Error)
67
75
  end
76
+
77
+ it_behaves_like "request hooks", :excon do
78
+ undef make_request
79
+ def make_request(disabled = false)
80
+ expect {
81
+ Excon.get(request_url, :expects => 404)
82
+ }.to raise_error(Excon::Errors::Error)
83
+ end
84
+ end
68
85
  end
69
86
  end
70
87
 
@@ -1,7 +1,33 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "FakeWeb hook", :with_monkey_patches => :fakeweb do
4
- it_behaves_like 'a hook into an HTTP library', 'net/http'
4
+ after(:each) do
5
+ ::FakeWeb.clean_registry
6
+ end
7
+
8
+ def disable_real_connections
9
+ ::FakeWeb.allow_net_connect = false
10
+ ::FakeWeb::NetConnectNotAllowedError
11
+ end
12
+
13
+ def enable_real_connections
14
+ ::FakeWeb.allow_net_connect = true
15
+ end
16
+
17
+ def directly_stub_request(method, url, response_body)
18
+ ::FakeWeb.register_uri(method, url, :body => response_body)
19
+ end
20
+
21
+ it_behaves_like 'a hook into an HTTP library', :fakeweb, 'net/http' do
22
+ before(:each) do
23
+ VCR::LibraryHooks::FakeWeb::RequestHandler.already_seen_requests.clear
24
+ end
25
+
26
+ after(:each) do
27
+ # assert that we are cleaning up the global state after every request
28
+ VCR::LibraryHooks::FakeWeb::RequestHandler.already_seen_requests.to_a.should eq([])
29
+ end
30
+ end
5
31
 
6
32
  it_performs('version checking', 'FakeWeb',
7
33
  :valid => %w[ 1.3.0 1.3.1 1.3.99 ],
@@ -46,12 +72,33 @@ describe "FakeWeb hook", :with_monkey_patches => :fakeweb do
46
72
 
47
73
  it 'records the interaction when Net::HTTP#request is called with a block with a return statement' do
48
74
  VCR.should_receive(:record_http_interaction).once
49
- perform_get_with_returning_block
75
+ perform_get_with_returning_block.body.should eq("GET to root")
76
+ end
77
+
78
+ def make_post_request
79
+ Net::HTTP.new('localhost', VCR::SinatraApp.port).post('/record-and-playback', '')
50
80
  end
51
81
 
52
82
  it 'records the interaction only once, even when Net::HTTP internally recursively calls #request' do
53
83
  VCR.should_receive(:record_http_interaction).once
54
- Net::HTTP.new('localhost', VCR::SinatraApp.port).post('/', nil)
84
+ make_post_request
85
+ end
86
+
87
+ it 'properly returns the response body for a post request when recording, stubbing or ignoring the request' do
88
+ recorded_body = nil
89
+ VCR.use_cassette("new_cassette", :record => :once) do
90
+ recorded_body = make_post_request.body
91
+ recorded_body.should match(/Response \d+/)
92
+ end
93
+
94
+ VCR.use_cassette("new_cassette", :record => :once) do
95
+ make_post_request.body.should eq(recorded_body)
96
+ end
97
+
98
+ VCR.configuration.ignore_request { |r| true }
99
+ ignored_body = make_post_request.body
100
+ ignored_body.should_not eq(recorded_body)
101
+ ignored_body.should match(/Response \d+/)
55
102
  end
56
103
  end
57
104
 
@@ -80,4 +127,25 @@ describe "FakeWeb hook", :with_monkey_patches => :fakeweb do
80
127
  end
81
128
  end
82
129
  end
130
+
131
+ describe "when a SocketError occurs" do
132
+ before(:each) do
133
+ VCR.configuration.ignore_request { |r| true }
134
+ end
135
+
136
+ it_behaves_like "request hooks", :fakeweb do
137
+ undef assert_expected_response
138
+ def assert_expected_response(response)
139
+ response.should be_nil
140
+ end
141
+
142
+ undef make_request
143
+ def make_request(disabled = false)
144
+ ::Net::HTTP.any_instance.stub(:request_without_vcr).and_raise(SocketError)
145
+ expect {
146
+ ::Net::HTTP.get_response(URI(request_url))
147
+ }.to raise_error(SocketError)
148
+ end
149
+ end
150
+ end
83
151
  end