vcr 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
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