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.
- data/.gemtest +0 -0
- data/.gitignore +5 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +29 -2
- data/Gemfile +3 -3
- data/README.md +55 -11
- data/Rakefile +45 -4
- data/features/.nav +6 -0
- data/features/{README.md → about_the_cucumber_features.md} +1 -1
- data/features/cassettes/update_content_length_header.feature +106 -0
- data/features/configuration/default_cassette_options.feature +20 -2
- data/features/configuration/filter_sensitive_data.feature +154 -0
- data/features/getting_started.md +67 -0
- data/features/record_modes/all.feature +4 -2
- data/features/record_modes/new_episodes.feature +8 -2
- data/features/record_modes/none.feature +4 -2
- data/features/record_modes/once.feature +92 -0
- data/features/step_definitions/cli_steps.rb +18 -0
- data/lib/vcr.rb +13 -6
- data/lib/vcr/cassette.rb +36 -15
- data/lib/vcr/config.rb +14 -2
- data/lib/vcr/deprecations/cassette.rb +29 -0
- data/lib/vcr/deprecations/config.rb +18 -0
- data/lib/vcr/deprecations/http_stubbing_adapters/common.rb +9 -0
- data/lib/vcr/deprecations/http_stubbing_adapters/fakeweb.rb +11 -0
- data/lib/vcr/http_stubbing_adapters/common.rb +1 -1
- data/lib/vcr/http_stubbing_adapters/fakeweb.rb +2 -7
- data/lib/vcr/http_stubbing_adapters/multi_object_proxy.rb +1 -1
- data/lib/vcr/middleware/common.rb +3 -5
- data/lib/vcr/rspec.rb +1 -38
- data/lib/vcr/structs/http_interaction.rb +29 -0
- data/lib/vcr/structs/request.rb +6 -0
- data/lib/vcr/structs/response.rb +4 -0
- data/lib/vcr/{cucumber_tags.rb → test_frameworks/cucumber.rb} +10 -2
- data/lib/vcr/test_frameworks/rspec.rb +37 -0
- data/lib/vcr/util/basic_object.rb +32 -28
- data/lib/vcr/{hooks.rb → util/hooks.rb} +3 -6
- data/lib/vcr/util/internet_connection.rb +1 -1
- data/lib/vcr/util/ping.rb +21 -17
- data/lib/vcr/util/variable_args_block_caller.rb +12 -0
- data/lib/vcr/util/yaml.rb +11 -0
- data/lib/vcr/version.rb +1 -1
- data/script/FullBuildRakeFile +7 -0
- data/spec/monkey_patches.rb +0 -7
- data/spec/spec_helper.rb +40 -8
- data/spec/support/http_library_adapters.rb +0 -262
- data/spec/support/shared_example_groups/http_library.rb +256 -0
- data/spec/support/{http_stubbing_adapter.rb → shared_example_groups/http_stubbing_adapter.rb} +15 -3
- data/spec/support/shared_example_groups/ignore_localhost_deprecation.rb +28 -0
- data/spec/support/{normalizers.rb → shared_example_groups/normalizers.rb} +3 -3
- data/spec/support/{version_checker.rb → shared_example_groups/version_checking.rb} +1 -1
- data/spec/vcr/cassette_spec.rb +80 -28
- data/spec/vcr/config_spec.rb +55 -8
- data/spec/vcr/deprecations/cassette_spec.rb +57 -0
- data/spec/vcr/deprecations/config_spec.rb +30 -0
- data/spec/vcr/deprecations/http_stubbing_adapters/common_spec.rb +7 -0
- data/spec/vcr/deprecations/http_stubbing_adapters/fakeweb_spec.rb +16 -0
- data/spec/vcr/extensions/net_http_response_spec.rb +1 -3
- data/spec/vcr/extensions/net_http_spec.rb +1 -3
- data/spec/vcr/http_stubbing_adapters/fakeweb_spec.rb +1 -4
- data/spec/vcr/http_stubbing_adapters/faraday_spec.rb +1 -4
- data/spec/vcr/http_stubbing_adapters/typhoeus_spec.rb +1 -4
- data/spec/vcr/http_stubbing_adapters/webmock_spec.rb +1 -3
- data/spec/vcr/middleware/faraday_spec.rb +4 -4
- data/spec/vcr/middleware/rack_spec.rb +4 -4
- data/spec/vcr/structs/http_interaction_spec.rb +61 -0
- data/spec/vcr/structs/request_spec.rb +20 -2
- data/spec/vcr/structs/response_spec.rb +23 -1
- data/spec/vcr/structs/response_status_spec.rb +1 -1
- data/spec/vcr/{cucumber_tags_spec.rb → test_frameworks/cucumber_spec.rb} +12 -8
- data/spec/vcr/{rspec_spec.rb → test_frameworks/rspec_spec.rb} +0 -0
- data/spec/vcr/{hooks_spec.rb → util/hooks_spec.rb} +3 -3
- data/spec/vcr/util/internet_connection_spec.rb +3 -3
- data/spec/vcr_spec.rb +3 -3
- data/vcr.gemspec +5 -5
- metadata +149 -131
- data/Gemfile.lock +0 -155
- data/lib/vcr/deprecations.rb +0 -54
- data/spec/support/disable_warnings.rb +0 -12
- data/spec/support/temp_cassette_library_dir.rb +0 -16
- data/spec/support/webmock_macros.rb +0 -14
- data/spec/vcr/deprecations_spec.rb +0 -139
data/lib/vcr/version.rb
CHANGED
data/script/FullBuildRakeFile
CHANGED
@@ -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
|
|
data/spec/monkey_patches.rb
CHANGED
@@ -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 = [
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
|
3
|
-
|
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
|
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
|