vcr 1.6.0 → 1.7.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 (82) hide show
  1. data/.gemtest +0 -0
  2. data/.gitignore +5 -0
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +29 -2
  5. data/Gemfile +3 -3
  6. data/README.md +55 -11
  7. data/Rakefile +45 -4
  8. data/features/.nav +6 -0
  9. data/features/{README.md → about_the_cucumber_features.md} +1 -1
  10. data/features/cassettes/update_content_length_header.feature +106 -0
  11. data/features/configuration/default_cassette_options.feature +20 -2
  12. data/features/configuration/filter_sensitive_data.feature +154 -0
  13. data/features/getting_started.md +67 -0
  14. data/features/record_modes/all.feature +4 -2
  15. data/features/record_modes/new_episodes.feature +8 -2
  16. data/features/record_modes/none.feature +4 -2
  17. data/features/record_modes/once.feature +92 -0
  18. data/features/step_definitions/cli_steps.rb +18 -0
  19. data/lib/vcr.rb +13 -6
  20. data/lib/vcr/cassette.rb +36 -15
  21. data/lib/vcr/config.rb +14 -2
  22. data/lib/vcr/deprecations/cassette.rb +29 -0
  23. data/lib/vcr/deprecations/config.rb +18 -0
  24. data/lib/vcr/deprecations/http_stubbing_adapters/common.rb +9 -0
  25. data/lib/vcr/deprecations/http_stubbing_adapters/fakeweb.rb +11 -0
  26. data/lib/vcr/http_stubbing_adapters/common.rb +1 -1
  27. data/lib/vcr/http_stubbing_adapters/fakeweb.rb +2 -7
  28. data/lib/vcr/http_stubbing_adapters/multi_object_proxy.rb +1 -1
  29. data/lib/vcr/middleware/common.rb +3 -5
  30. data/lib/vcr/rspec.rb +1 -38
  31. data/lib/vcr/structs/http_interaction.rb +29 -0
  32. data/lib/vcr/structs/request.rb +6 -0
  33. data/lib/vcr/structs/response.rb +4 -0
  34. data/lib/vcr/{cucumber_tags.rb → test_frameworks/cucumber.rb} +10 -2
  35. data/lib/vcr/test_frameworks/rspec.rb +37 -0
  36. data/lib/vcr/util/basic_object.rb +32 -28
  37. data/lib/vcr/{hooks.rb → util/hooks.rb} +3 -6
  38. data/lib/vcr/util/internet_connection.rb +1 -1
  39. data/lib/vcr/util/ping.rb +21 -17
  40. data/lib/vcr/util/variable_args_block_caller.rb +12 -0
  41. data/lib/vcr/util/yaml.rb +11 -0
  42. data/lib/vcr/version.rb +1 -1
  43. data/script/FullBuildRakeFile +7 -0
  44. data/spec/monkey_patches.rb +0 -7
  45. data/spec/spec_helper.rb +40 -8
  46. data/spec/support/http_library_adapters.rb +0 -262
  47. data/spec/support/shared_example_groups/http_library.rb +256 -0
  48. data/spec/support/{http_stubbing_adapter.rb → shared_example_groups/http_stubbing_adapter.rb} +15 -3
  49. data/spec/support/shared_example_groups/ignore_localhost_deprecation.rb +28 -0
  50. data/spec/support/{normalizers.rb → shared_example_groups/normalizers.rb} +3 -3
  51. data/spec/support/{version_checker.rb → shared_example_groups/version_checking.rb} +1 -1
  52. data/spec/vcr/cassette_spec.rb +80 -28
  53. data/spec/vcr/config_spec.rb +55 -8
  54. data/spec/vcr/deprecations/cassette_spec.rb +57 -0
  55. data/spec/vcr/deprecations/config_spec.rb +30 -0
  56. data/spec/vcr/deprecations/http_stubbing_adapters/common_spec.rb +7 -0
  57. data/spec/vcr/deprecations/http_stubbing_adapters/fakeweb_spec.rb +16 -0
  58. data/spec/vcr/extensions/net_http_response_spec.rb +1 -3
  59. data/spec/vcr/extensions/net_http_spec.rb +1 -3
  60. data/spec/vcr/http_stubbing_adapters/fakeweb_spec.rb +1 -4
  61. data/spec/vcr/http_stubbing_adapters/faraday_spec.rb +1 -4
  62. data/spec/vcr/http_stubbing_adapters/typhoeus_spec.rb +1 -4
  63. data/spec/vcr/http_stubbing_adapters/webmock_spec.rb +1 -3
  64. data/spec/vcr/middleware/faraday_spec.rb +4 -4
  65. data/spec/vcr/middleware/rack_spec.rb +4 -4
  66. data/spec/vcr/structs/http_interaction_spec.rb +61 -0
  67. data/spec/vcr/structs/request_spec.rb +20 -2
  68. data/spec/vcr/structs/response_spec.rb +23 -1
  69. data/spec/vcr/structs/response_status_spec.rb +1 -1
  70. data/spec/vcr/{cucumber_tags_spec.rb → test_frameworks/cucumber_spec.rb} +12 -8
  71. data/spec/vcr/{rspec_spec.rb → test_frameworks/rspec_spec.rb} +0 -0
  72. data/spec/vcr/{hooks_spec.rb → util/hooks_spec.rb} +3 -3
  73. data/spec/vcr/util/internet_connection_spec.rb +3 -3
  74. data/spec/vcr_spec.rb +3 -3
  75. data/vcr.gemspec +5 -5
  76. metadata +149 -131
  77. data/Gemfile.lock +0 -155
  78. data/lib/vcr/deprecations.rb +0 -54
  79. data/spec/support/disable_warnings.rb +0 -12
  80. data/spec/support/temp_cassette_library_dir.rb +0 -16
  81. data/spec/support/webmock_macros.rb +0 -14
  82. data/spec/vcr/deprecations_spec.rb +0 -139
@@ -3,7 +3,7 @@ module VCR
3
3
 
4
4
  def version
5
5
  @version ||= begin
6
- string = '1.6.0'
6
+ string = '1.7.0'
7
7
 
8
8
  def string.parts
9
9
  split('.').map { |p| p.to_i }
@@ -37,6 +37,13 @@ task :print_ruby_description do
37
37
  end
38
38
 
39
39
  task :bundle_install => :ensure_bundler_installed do
40
+ # Unfortunately, there is no version of ruby-debug that installs cleanly on 1.9.1 and 1.9.2.
41
+ # Our Gemfile specifies different versions using conditionals, but we still need to bundle update
42
+ # to get bundler to use the different versions.
43
+ if RUBY_VERSION =~ /^1\.9/
44
+ sh "bundle update ruby-debug-base19"
45
+ end
46
+
40
47
  sh "bundle install"
41
48
  end
42
49
 
@@ -1,13 +1,6 @@
1
1
  module MonkeyPatches
2
2
  extend self
3
3
 
4
- module RSpecMacros
5
- def without_monkey_patches(scope)
6
- before(:each) { MonkeyPatches.disable!(scope) }
7
- after(:each) { MonkeyPatches.enable!(scope) }
8
- end
9
- end
10
-
11
4
  NET_HTTP_SINGLETON = class << Net::HTTP; self; end
12
5
 
13
6
  MONKEY_PATCHES = [
@@ -1,6 +1,10 @@
1
1
  require 'rubygems'
2
- require 'bundler'
3
- Bundler.setup
2
+
3
+ using_git = File.exist?(File.expand_path('../../.git/', __FILE__))
4
+ if using_git
5
+ require 'bundler'
6
+ Bundler.setup
7
+ end
4
8
 
5
9
  require 'rspec'
6
10
 
@@ -36,13 +40,8 @@ module VCR
36
40
  end
37
41
 
38
42
  RSpec.configure do |config|
39
- config.extend TempCassetteLibraryDir
40
- config.extend DisableWarnings
41
- config.extend MonkeyPatches::RSpecMacros
42
- config.extend WebMockMacros
43
-
44
43
  config.color_enabled = true
45
- config.debug = RUBY_INTERPRETER == :mri && RUBY_VERSION != '1.9.2'
44
+ config.debug = (using_git && RUBY_INTERPRETER == :mri)
46
45
 
47
46
  config.before(:each) do
48
47
  VCR.turn_on! unless VCR.turned_on?
@@ -59,12 +58,45 @@ RSpec.configure do |config|
59
58
  VCR::HttpStubbingAdapters::Faraday.reset!
60
59
  end
61
60
 
61
+ # Ensure each example uses a different cassette library to keep them isolated.
62
+ config.around(:each) do |example|
63
+ Dir.mktmpdir do |dir|
64
+ VCR::Config.cassette_library_dir = dir
65
+ example.run
66
+ end
67
+ end
68
+
62
69
  config.after(:each) do
63
70
  VCR::HttpStubbingAdapters::Common.adapters.each do |a|
64
71
  a.ignored_hosts = []
65
72
  end
66
73
  end
67
74
 
75
+ config.before(:all, :disable_warnings => true) do
76
+ @orig_std_err = $stderr
77
+ $stderr = StringIO.new
78
+ end
79
+
80
+ config.after(:all, :disable_warnings => true) do
81
+ $stderr = @orig_std_err
82
+ end
83
+
84
+ config.before(:all, :without_webmock_callbacks => true) do
85
+ @original_webmock_callbacks = ::WebMock::CallbackRegistry.callbacks
86
+ ::WebMock::CallbackRegistry.reset
87
+ end
88
+
89
+ config.after(:all, :without_webmock_callbacks => true) do
90
+ @original_webmock_callbacks.each do |cb|
91
+ ::WebMock::CallbackRegistry.add_callback(cb[:options], cb[:block])
92
+ end
93
+ end
94
+
95
+ [:all, :vcr].each do |scope|
96
+ config.before(:each, :without_monkey_patches => scope) { MonkeyPatches.disable!(scope) }
97
+ config.after(:each, :without_monkey_patches => scope) { MonkeyPatches.enable!(scope) }
98
+ end
99
+
68
100
  config.filter_run :focus => true
69
101
  config.run_all_when_everything_filtered = true
70
102
 
@@ -167,265 +167,3 @@ end
167
167
  end
168
168
  end
169
169
  end
170
-
171
- NET_CONNECT_NOT_ALLOWED_ERROR = /You can use VCR to automatically record this request and replay it later/
172
-
173
- module HttpLibrarySpecs
174
- def test_http_library(library, supported_request_match_attributes, *other)
175
- # skip libs that only work on MRI
176
- return if RUBY_INTERPRETER != :mri && library =~ /(typhoeus|curb|patron|em-http)/
177
-
178
- unless adapter_module = HTTP_LIBRARY_ADAPTERS[library]
179
- raise ArgumentError.new("No http library adapter module could be found for #{library}")
180
- end
181
-
182
- describe "using #{adapter_module.http_library_name}" do
183
- include adapter_module
184
-
185
- # Necessary for ruby 1.9.2. On 1.9.2 we get an error when we use super,
186
- # so this gives us another alias we can use for the original method.
187
- alias make_request make_http_request
188
-
189
- describe '#stub_requests using specific match_attributes' do
190
- before(:each) { subject.http_connections_allowed = false }
191
- let(:interactions) { YAML.load(File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', YAML_SERIALIZATION_VERSION, 'match_requests_on.yml'))) }
192
-
193
- @supported_request_match_attributes = supported_request_match_attributes
194
- def self.matching_on(attribute, valid, invalid, &block)
195
- supported_request_match_attributes = @supported_request_match_attributes
196
-
197
- describe ":#{attribute}" do
198
- let(:perform_stubbing) { subject.stub_requests(interactions, match_requests_on) }
199
- let(:match_requests_on) { [attribute] }
200
- let(:record_mode) { :none }
201
-
202
- if supported_request_match_attributes.include?(attribute)
203
- before(:each) { perform_stubbing }
204
- module_eval(&block)
205
-
206
- valid.each do |val, response|
207
- it "returns the expected response for a #{val.inspect} request" do
208
- get_body_string(make_http_request(val)).should == response
209
- end
210
- end
211
-
212
- it "raises an error for a request with a different #{attribute}" do
213
- expect { make_http_request(invalid) }.to raise_error(NET_CONNECT_NOT_ALLOWED_ERROR)
214
- end
215
- else
216
- it 'raises an error indicating matching requests on this attribute is not supported' do
217
- expect { perform_stubbing }.to raise_error(/does not support matching requests on #{attribute}/)
218
- end
219
- end
220
- end
221
- end
222
-
223
- matching_on :method, { :get => "get method response", :post => "post method response" }, :put do
224
- def make_http_request(http_method)
225
- make_request(http_method, 'http://some-wrong-domain.com/', nil, {})
226
- end
227
- end
228
-
229
- matching_on :host, { 'example1.com' => 'example1.com host response', 'example2.com' => 'example2.com host response' }, 'example3.com' do
230
- def make_http_request(host)
231
- make_request(:get, "http://#{host}/some/wrong/path", nil, {})
232
- end
233
- end
234
-
235
- matching_on :path, { '/path1' => 'path1 response', '/path2' => 'path2 response' }, '/path3' do
236
- def make_http_request(path)
237
- make_request(:get, "http://some.wrong.domain.com#{path}?p=q", nil, {})
238
- end
239
- end
240
-
241
- matching_on :uri, { 'http://example.com/uri1' => 'uri1 response', 'http://example.com/uri2' => 'uri2 response' }, 'http://example.com/uri3' do
242
- def make_http_request(uri)
243
- make_request(:get, uri, nil, {})
244
- end
245
- end
246
-
247
- matching_on :body, { 'param=val1' => 'val1 body response', 'param=val2' => 'val2 body response' }, 'param=val3' do
248
- def make_http_request(body)
249
- make_request(:put, "http://wrong-domain.com/wrong/path", body, {})
250
- end
251
- end
252
-
253
- matching_on :headers, {{ 'X-HTTP-HEADER1' => 'val1' } => 'val1 header response', { 'X-HTTP-HEADER1' => 'val2' } => 'val2 header response' }, { 'X-HTTP-HEADER1' => 'val3' } do
254
- def make_http_request(headers)
255
- make_request(:get, "http://wrong-domain.com/wrong/path", nil, headers)
256
- end
257
- end
258
- end
259
-
260
- def self.test_real_http_request(http_allowed, *other)
261
- let(:url) { "http://localhost:#{VCR::SinatraApp.port}/foo" }
262
-
263
- if http_allowed
264
-
265
- it 'allows real http requests' do
266
- get_body_string(make_http_request(:get, url)).should == 'FOO!'
267
- end
268
-
269
- describe 'recording new http requests' do
270
- let(:recorded_interaction) do
271
- interaction = nil
272
- VCR.should_receive(:record_http_interaction) { |i| interaction = i }
273
- make_http_request(:get, url)
274
- interaction
275
- end
276
-
277
- it 'does not record the request if the adapter is disabled' do
278
- subject.stub(:enabled?).and_return(false)
279
- VCR.should_not_receive(:record_http_interaction)
280
- make_http_request(:get, url)
281
- end
282
-
283
- it 'records the request uri' do
284
- recorded_interaction.request.uri.should == url
285
- end
286
-
287
- it 'records the request method' do
288
- recorded_interaction.request.method.should == :get
289
- end
290
-
291
- it 'records the request body' do
292
- recorded_interaction.request.body.should be_nil
293
- end
294
-
295
- it 'records the request headers' do
296
- recorded_interaction.request.headers.should be_nil
297
- end
298
-
299
- it 'records the response status code' do
300
- recorded_interaction.response.status.code.should == 200
301
- end
302
-
303
- it 'records the response status message' do
304
- recorded_interaction.response.status.message.should == 'OK'
305
- end unless other.include?(:status_message_not_exposed)
306
-
307
- it 'records the response body' do
308
- recorded_interaction.response.body.should == 'FOO!'
309
- end
310
-
311
- it 'records the response headers' do
312
- recorded_interaction.response.headers['content-type'].should == ["text/html;charset=utf-8"]
313
- end
314
- end
315
- else
316
- let(:record_mode) { :none }
317
-
318
- it 'does not allow real HTTP requests or record them' do
319
- VCR.should_receive(:record_http_interaction).never
320
- expect { make_http_request(:get, url) }.to raise_error(NET_CONNECT_NOT_ALLOWED_ERROR)
321
- end
322
- end
323
- end
324
-
325
- def test_request_stubbed(method, url, expected)
326
- subject.request_stubbed?(VCR::Request.new(method, url), [:method, :uri]).should == expected
327
- end
328
-
329
- it "returns false from #http_connections_allowed? when http_connections_allowed is set to nil" do
330
- subject.http_connections_allowed = nil
331
- subject.http_connections_allowed?.should == false
332
- end
333
-
334
- describe '.restore_stubs_checkpoint' do
335
- it 'raises an appropriate error when there is no matching checkpoint' do
336
- expect {
337
- subject.restore_stubs_checkpoint(:some_crazy_checkpoint_that_doesnt_exist)
338
- }.to raise_error(ArgumentError, /no checkpoint .* could be found/i)
339
- end
340
- end
341
-
342
- [true, false].each do |http_allowed|
343
- context "when http_connections_allowed is set to #{http_allowed}" do
344
- before(:each) { subject.http_connections_allowed = http_allowed }
345
-
346
- it "returns #{http_allowed} for #http_connections_allowed?" do
347
- subject.http_connections_allowed?.should == http_allowed
348
- end
349
-
350
- test_real_http_request(http_allowed, *other)
351
-
352
- unless http_allowed
353
- localhost_response = "Localhost response"
354
-
355
- describe '.ignore_hosts' do
356
- let(:record_mode) { :none }
357
-
358
- context 'when set to ["127.0.0.1", "localhost"]' do
359
- before(:each) do
360
- subject.ignored_hosts = ["127.0.0.1", "localhost"]
361
- end
362
-
363
- %w[ 127.0.0.1 localhost ].each do |localhost_alias|
364
- it "allows requests to #{localhost_alias}" do
365
- get_body_string(make_http_request(:get, "http://#{localhost_alias}:#{VCR::SinatraApp.port}/localhost_test")).should == localhost_response
366
- end
367
- end
368
-
369
- it 'does not allow requests to 0.0.0.0' do
370
- expect { make_http_request(:get, "http://0.0.0.0:#{VCR::SinatraApp.port}/localhost_test") }.to raise_error(NET_CONNECT_NOT_ALLOWED_ERROR)
371
- end
372
- end
373
- end
374
- end
375
-
376
- context 'when some requests are stubbed, after setting a checkpoint' do
377
- before(:each) do
378
- subject.create_stubs_checkpoint(:my_checkpoint)
379
- @recorded_interactions = YAML.load(File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', YAML_SERIALIZATION_VERSION, 'fake_example.com_responses.yml')))
380
- subject.stub_requests(@recorded_interactions, VCR::RequestMatcher::DEFAULT_MATCH_ATTRIBUTES)
381
- end
382
-
383
- if other.include?(:needs_net_http_extension)
384
- it 'returns true from #request_stubbed? for the requests that are stubbed' do
385
- test_request_stubbed(:post, 'http://example.com', true)
386
- test_request_stubbed(:get, 'http://example.com/foo', true)
387
- end
388
-
389
- it 'returns false from #request_stubbed? for requests that are not stubbed' do
390
- test_request_stubbed(:post, 'http://example.com/foo', false)
391
- test_request_stubbed(:get, 'http://google.com', false)
392
- end
393
- end
394
-
395
- it 'gets the stubbed responses when requests are made to http://example.com/foo, and does not record them' do
396
- VCR.should_receive(:record_http_interaction).never
397
- get_body_string(make_http_request(:get, 'http://example.com/foo')).should =~ /example\.com get response \d with path=foo/
398
- end
399
-
400
- it 'rotates through multiple responses for the same request' do
401
- get_body_string(make_http_request(:get, 'http://example.com/foo')).should == 'example.com get response 1 with path=foo'
402
- get_body_string(make_http_request(:get, 'http://example.com/foo')).should == 'example.com get response 2 with path=foo'
403
-
404
- # subsequent requests keep getting the last one
405
- get_body_string(make_http_request(:get, 'http://example.com/foo')).should == 'example.com get response 2 with path=foo'
406
- get_body_string(make_http_request(:get, 'http://example.com/foo')).should == 'example.com get response 2 with path=foo'
407
- end unless other.include?(:does_not_support_rotating_responses)
408
-
409
- it "correctly handles stubbing multiple values for the same header" do
410
- get_header('Set-Cookie', make_http_request(:get, 'http://example.com/two_set_cookie_headers')).should =~ ['bar=bazz', 'foo=bar']
411
- end
412
-
413
- context 'when we restore our previous check point' do
414
- before(:each) { subject.restore_stubs_checkpoint(:my_checkpoint) }
415
-
416
- test_real_http_request(http_allowed, *other)
417
-
418
- if other.include?(:needs_net_http_extension)
419
- it 'returns false from #request_stubbed?' do
420
- test_request_stubbed(:get, 'http://example.com/foo', false)
421
- test_request_stubbed(:post, 'http://example.com', false)
422
- test_request_stubbed(:get, 'http://google.com', false)
423
- end
424
- end
425
- end
426
- end
427
- end
428
- end
429
- end
430
- end
431
- end
@@ -0,0 +1,256 @@
1
+ NET_CONNECT_NOT_ALLOWED_ERROR = /You can use VCR to automatically record this request and replay it later/
2
+
3
+ shared_examples_for "an http library" do |library, supported_request_match_attributes, *other|
4
+ unless adapter_module = HTTP_LIBRARY_ADAPTERS[library]
5
+ raise ArgumentError.new("No http library adapter module could be found for #{library}")
6
+ end
7
+
8
+ describe "using #{adapter_module.http_library_name}", :unless => (RUBY_INTERPRETER != :mri && library =~ /(typhoeus|curb|patron|em-http)/) do
9
+ include adapter_module
10
+
11
+ # Necessary for ruby 1.9.2. On 1.9.2 we get an error when we use super,
12
+ # so this gives us another alias we can use for the original method.
13
+ alias make_request make_http_request
14
+
15
+ describe '#stub_requests using specific match_attributes' do
16
+ before(:each) { subject.http_connections_allowed = false }
17
+ let(:interactions) { VCR::YAML.load_file(File.join(VCR::SPEC_ROOT, 'fixtures', YAML_SERIALIZATION_VERSION, 'match_requests_on.yml')) }
18
+
19
+ @supported_request_match_attributes = supported_request_match_attributes
20
+ def self.matching_on(attribute, valid, invalid, &block)
21
+ supported_request_match_attributes = @supported_request_match_attributes
22
+
23
+ describe ":#{attribute}" do
24
+ let(:perform_stubbing) { subject.stub_requests(interactions, match_requests_on) }
25
+ let(:match_requests_on) { [attribute] }
26
+ let(:record_mode) { :none }
27
+
28
+ if supported_request_match_attributes.include?(attribute)
29
+ before(:each) { perform_stubbing }
30
+ module_eval(&block)
31
+
32
+ valid.each do |val, response|
33
+ it "returns the expected response for a #{val.inspect} request" do
34
+ get_body_string(make_http_request(val)).should == response
35
+ end
36
+ end
37
+
38
+ it "raises an error for a request with a different #{attribute}" do
39
+ expect { make_http_request(invalid) }.to raise_error(NET_CONNECT_NOT_ALLOWED_ERROR)
40
+ end
41
+ else
42
+ it 'raises an error indicating matching requests on this attribute is not supported' do
43
+ expect { perform_stubbing }.to raise_error(/does not support matching requests on #{attribute}/)
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ matching_on :method, { :get => "get method response", :post => "post method response" }, :put do
50
+ def make_http_request(http_method)
51
+ make_request(http_method, 'http://some-wrong-domain.com/', nil, {})
52
+ end
53
+ end
54
+
55
+ matching_on :host, { 'example1.com' => 'example1.com host response', 'example2.com' => 'example2.com host response' }, 'example3.com' do
56
+ def make_http_request(host)
57
+ make_request(:get, "http://#{host}/some/wrong/path", nil, {})
58
+ end
59
+ end
60
+
61
+ matching_on :path, { '/path1' => 'path1 response', '/path2' => 'path2 response' }, '/path3' do
62
+ def make_http_request(path)
63
+ make_request(:get, "http://some.wrong.domain.com#{path}?p=q", nil, {})
64
+ end
65
+ end
66
+
67
+ matching_on :uri, { 'http://example.com/uri1' => 'uri1 response', 'http://example.com/uri2' => 'uri2 response' }, 'http://example.com/uri3' do
68
+ def make_http_request(uri)
69
+ make_request(:get, uri, nil, {})
70
+ end
71
+ end
72
+
73
+ matching_on :body, { 'param=val1' => 'val1 body response', 'param=val2' => 'val2 body response' }, 'param=val3' do
74
+ def make_http_request(body)
75
+ make_request(:put, "http://wrong-domain.com/wrong/path", body, {})
76
+ end
77
+ end
78
+
79
+ matching_on :headers, {{ 'X-HTTP-HEADER1' => 'val1' } => 'val1 header response', { 'X-HTTP-HEADER1' => 'val2' } => 'val2 header response' }, { 'X-HTTP-HEADER1' => 'val3' } do
80
+ def make_http_request(headers)
81
+ make_request(:get, "http://wrong-domain.com/wrong/path", nil, headers)
82
+ end
83
+ end
84
+ end
85
+
86
+ def self.test_real_http_request(http_allowed, *other)
87
+ let(:url) { "http://localhost:#{VCR::SinatraApp.port}/foo" }
88
+
89
+ if http_allowed
90
+
91
+ it 'allows real http requests' do
92
+ get_body_string(make_http_request(:get, url)).should == 'FOO!'
93
+ end
94
+
95
+ describe 'recording new http requests' do
96
+ let(:recorded_interaction) do
97
+ interaction = nil
98
+ VCR.should_receive(:record_http_interaction) { |i| interaction = i }
99
+ make_http_request(:get, url)
100
+ interaction
101
+ end
102
+
103
+ it 'does not record the request if the adapter is disabled' do
104
+ subject.stub(:enabled?).and_return(false)
105
+ VCR.should_not_receive(:record_http_interaction)
106
+ make_http_request(:get, url)
107
+ end
108
+
109
+ it 'records the request uri' do
110
+ recorded_interaction.request.uri.should == url
111
+ end
112
+
113
+ it 'records the request method' do
114
+ recorded_interaction.request.method.should == :get
115
+ end
116
+
117
+ it 'records the request body' do
118
+ recorded_interaction.request.body.should be_nil
119
+ end
120
+
121
+ it 'records the request headers' do
122
+ recorded_interaction.request.headers.should be_nil
123
+ end
124
+
125
+ it 'records the response status code' do
126
+ recorded_interaction.response.status.code.should == 200
127
+ end
128
+
129
+ it 'records the response status message' do
130
+ recorded_interaction.response.status.message.should == 'OK'
131
+ end unless other.include?(:status_message_not_exposed)
132
+
133
+ it 'records the response body' do
134
+ recorded_interaction.response.body.should == 'FOO!'
135
+ end
136
+
137
+ it 'records the response headers' do
138
+ recorded_interaction.response.headers['content-type'].should == ["text/html;charset=utf-8"]
139
+ end
140
+ end
141
+ else
142
+ let(:record_mode) { :none }
143
+
144
+ it 'does not allow real HTTP requests or record them' do
145
+ VCR.should_receive(:record_http_interaction).never
146
+ expect { make_http_request(:get, url) }.to raise_error(NET_CONNECT_NOT_ALLOWED_ERROR)
147
+ end
148
+ end
149
+ end
150
+
151
+ def test_request_stubbed(method, url, expected)
152
+ subject.request_stubbed?(VCR::Request.new(method, url), [:method, :uri]).should == expected
153
+ end
154
+
155
+ it "returns false from #http_connections_allowed? when http_connections_allowed is set to nil" do
156
+ subject.http_connections_allowed = nil
157
+ subject.http_connections_allowed?.should == false
158
+ end
159
+
160
+ describe '.restore_stubs_checkpoint' do
161
+ it 'raises an appropriate error when there is no matching checkpoint' do
162
+ expect {
163
+ subject.restore_stubs_checkpoint(:some_crazy_checkpoint_that_doesnt_exist)
164
+ }.to raise_error(ArgumentError, /no checkpoint .* could be found/i)
165
+ end
166
+ end
167
+
168
+ [true, false].each do |http_allowed|
169
+ context "when http_connections_allowed is set to #{http_allowed}" do
170
+ before(:each) { subject.http_connections_allowed = http_allowed }
171
+
172
+ it "returns #{http_allowed} for #http_connections_allowed?" do
173
+ subject.http_connections_allowed?.should == http_allowed
174
+ end
175
+
176
+ test_real_http_request(http_allowed, *other)
177
+
178
+ unless http_allowed
179
+ localhost_response = "Localhost response"
180
+
181
+ describe '.ignore_hosts' do
182
+ let(:record_mode) { :none }
183
+
184
+ context 'when set to ["127.0.0.1", "localhost"]' do
185
+ before(:each) do
186
+ subject.ignored_hosts = ["127.0.0.1", "localhost"]
187
+ end
188
+
189
+ %w[ 127.0.0.1 localhost ].each do |localhost_alias|
190
+ it "allows requests to #{localhost_alias}" do
191
+ get_body_string(make_http_request(:get, "http://#{localhost_alias}:#{VCR::SinatraApp.port}/localhost_test")).should == localhost_response
192
+ end
193
+ end
194
+
195
+ it 'does not allow requests to 0.0.0.0' do
196
+ expect { make_http_request(:get, "http://0.0.0.0:#{VCR::SinatraApp.port}/localhost_test") }.to raise_error(NET_CONNECT_NOT_ALLOWED_ERROR)
197
+ end
198
+ end
199
+ end
200
+ end
201
+
202
+ context 'when some requests are stubbed, after setting a checkpoint' do
203
+ before(:each) do
204
+ subject.create_stubs_checkpoint(:my_checkpoint)
205
+ @recorded_interactions = VCR::YAML.load_file(File.join(VCR::SPEC_ROOT, 'fixtures', YAML_SERIALIZATION_VERSION, 'fake_example.com_responses.yml'))
206
+ subject.stub_requests(@recorded_interactions, VCR::RequestMatcher::DEFAULT_MATCH_ATTRIBUTES)
207
+ end
208
+
209
+ if other.include?(:needs_net_http_extension)
210
+ it 'returns true from #request_stubbed? for the requests that are stubbed' do
211
+ test_request_stubbed(:post, 'http://example.com', true)
212
+ test_request_stubbed(:get, 'http://example.com/foo', true)
213
+ end
214
+
215
+ it 'returns false from #request_stubbed? for requests that are not stubbed' do
216
+ test_request_stubbed(:post, 'http://example.com/foo', false)
217
+ test_request_stubbed(:get, 'http://google.com', false)
218
+ end
219
+ end
220
+
221
+ it 'gets the stubbed responses when requests are made to http://example.com/foo, and does not record them' do
222
+ VCR.should_receive(:record_http_interaction).never
223
+ get_body_string(make_http_request(:get, 'http://example.com/foo')).should =~ /example\.com get response \d with path=foo/
224
+ end
225
+
226
+ it 'rotates through multiple responses for the same request' do
227
+ get_body_string(make_http_request(:get, 'http://example.com/foo')).should == 'example.com get response 1 with path=foo'
228
+ get_body_string(make_http_request(:get, 'http://example.com/foo')).should == 'example.com get response 2 with path=foo'
229
+
230
+ # subsequent requests keep getting the last one
231
+ get_body_string(make_http_request(:get, 'http://example.com/foo')).should == 'example.com get response 2 with path=foo'
232
+ get_body_string(make_http_request(:get, 'http://example.com/foo')).should == 'example.com get response 2 with path=foo'
233
+ end unless other.include?(:does_not_support_rotating_responses)
234
+
235
+ it "correctly handles stubbing multiple values for the same header" do
236
+ get_header('Set-Cookie', make_http_request(:get, 'http://example.com/two_set_cookie_headers')).should =~ ['bar=bazz', 'foo=bar']
237
+ end
238
+
239
+ context 'when we restore our previous check point' do
240
+ before(:each) { subject.restore_stubs_checkpoint(:my_checkpoint) }
241
+
242
+ test_real_http_request(http_allowed, *other)
243
+
244
+ if other.include?(:needs_net_http_extension)
245
+ it 'returns false from #request_stubbed?' do
246
+ test_request_stubbed(:get, 'http://example.com/foo', false)
247
+ test_request_stubbed(:post, 'http://example.com', false)
248
+ test_request_stubbed(:get, 'http://google.com', false)
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end