vcr 2.0.0.beta2 → 2.0.0.rc1

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 (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