vcr 2.1.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -1
- data/CHANGELOG.md +58 -1
- data/Gemfile +0 -6
- data/README.md +12 -3
- data/Rakefile +2 -2
- data/features/.nav +2 -0
- data/features/cassettes/allow_unused_http_interactions.feature +86 -0
- data/features/cassettes/naming.feature +3 -2
- data/features/cassettes/persistence.feature +63 -0
- data/features/configuration/debug_logging.feature +3 -3
- data/features/configuration/ignore_request.feature +1 -1
- data/features/hooks/after_http_request.feature +1 -1
- data/features/step_definitions/cli_steps.rb +33 -0
- data/features/support/env.rb +0 -1
- data/lib/vcr.rb +13 -0
- data/lib/vcr/cassette.rb +57 -44
- data/lib/vcr/cassette/{reader.rb → erb_renderer.rb} +9 -11
- data/lib/vcr/cassette/http_interaction_list.rb +18 -0
- data/lib/vcr/cassette/persisters.rb +42 -0
- data/lib/vcr/cassette/persisters/file_system.rb +60 -0
- data/lib/vcr/cassette/serializers.rb +1 -1
- data/lib/vcr/cassette/serializers/json.rb +1 -1
- data/lib/vcr/cassette/serializers/psych.rb +1 -1
- data/lib/vcr/cassette/serializers/syck.rb +1 -1
- data/lib/vcr/cassette/serializers/yaml.rb +1 -1
- data/lib/vcr/configuration.rb +49 -25
- data/lib/vcr/errors.rb +6 -0
- data/lib/vcr/library_hooks/excon.rb +1 -1
- data/lib/vcr/library_hooks/fakeweb.rb +16 -3
- data/lib/vcr/library_hooks/faraday.rb +13 -0
- data/lib/vcr/library_hooks/typhoeus.rb +5 -1
- data/lib/vcr/library_hooks/webmock.rb +90 -35
- data/lib/vcr/middleware/faraday.rb +12 -4
- data/lib/vcr/request_handler.rb +10 -2
- data/lib/vcr/structs.rb +31 -7
- data/lib/vcr/version.rb +1 -1
- data/script/ci.sh +14 -0
- data/spec/spec_helper.rb +8 -1
- data/spec/support/shared_example_groups/hook_into_http_library.rb +31 -1
- data/spec/vcr/cassette/{reader_spec.rb → erb_renderer_spec.rb} +15 -21
- data/spec/vcr/cassette/http_interaction_list_spec.rb +15 -0
- data/spec/vcr/cassette/persisters/file_system_spec.rb +64 -0
- data/spec/vcr/cassette/persisters_spec.rb +39 -0
- data/spec/vcr/cassette/serializers_spec.rb +4 -3
- data/spec/vcr/cassette_spec.rb +65 -41
- data/spec/vcr/configuration_spec.rb +33 -2
- data/spec/vcr/library_hooks/fakeweb_spec.rb +11 -0
- data/spec/vcr/library_hooks/faraday_spec.rb +24 -0
- data/spec/vcr/library_hooks/webmock_spec.rb +82 -2
- data/spec/vcr/middleware/faraday_spec.rb +32 -0
- data/spec/vcr/structs_spec.rb +60 -20
- data/spec/vcr/util/hooks_spec.rb +7 -0
- data/spec/vcr_spec.rb +7 -0
- data/vcr.gemspec +2 -2
- metadata +31 -26
- data/Guardfile +0 -9
- data/script/FullBuildRakeFile +0 -56
- data/script/full_build +0 -1
- data/script/spec +0 -1
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'support/ruby_interpreter'
|
1
2
|
require 'vcr/cassette/serializers'
|
2
3
|
require 'multi_json'
|
3
4
|
begin
|
@@ -15,7 +16,7 @@ module VCR
|
|
15
16
|
result = serializer.serialize("a" => string)
|
16
17
|
serializer.deserialize(result)
|
17
18
|
}.to raise_error(error_class, /preserve_exact_body_bytes/)
|
18
|
-
end
|
19
|
+
end unless (RUBY_INTERPRETER == :rubinius && RUBY_VERSION =~ /^1.9/)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
@@ -75,7 +76,7 @@ module VCR
|
|
75
76
|
end
|
76
77
|
|
77
78
|
engines.each do |engine, error|
|
78
|
-
context "when MultiJson is configured to use #{engine.inspect}" do
|
79
|
+
context "when MultiJson is configured to use #{engine.inspect}", :unless => (RUBY_INTERPRETER == :jruby) do
|
79
80
|
before { MultiJson.engine = engine }
|
80
81
|
it_behaves_like "encoding error handling", :json, error do
|
81
82
|
let(:string) { "\xFA" }
|
@@ -159,7 +160,7 @@ module VCR
|
|
159
160
|
::YAML::ENGINE.yamler = 'psych'
|
160
161
|
serialized = subject[:syck].serialize(problematic_syck_string)
|
161
162
|
subject[:syck].deserialize(serialized).should_not eq(problematic_syck_string)
|
162
|
-
end if defined?(::Psych)
|
163
|
+
end if defined?(::Psych) && (RUBY_INTERPRETER != :jruby)
|
163
164
|
end
|
164
165
|
end
|
165
166
|
end
|
data/spec/vcr/cassette_spec.rb
CHANGED
@@ -9,33 +9,17 @@ describe VCR::Cassette do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
describe '#file' do
|
12
|
-
it '
|
13
|
-
|
14
|
-
|
12
|
+
it 'delegates the file resolution to the FileSystem persister' do
|
13
|
+
fs = VCR::Cassette::Persisters::FileSystem
|
14
|
+
fs.should respond_to(:absolute_path_to_file).with(1).argument
|
15
|
+
fs.should_receive(:absolute_path_to_file).with("cassette name.yml") { "f.yml" }
|
16
|
+
VCR::Cassette.new("cassette name").file.should eq("f.yml")
|
15
17
|
end
|
16
18
|
|
17
|
-
it '
|
18
|
-
VCR.
|
19
|
-
cassette = VCR::Cassette.new(
|
20
|
-
cassette.file.
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'strips out disallowed characters so that it is a valid file name with no spaces' do
|
24
|
-
cassette = VCR::Cassette.new("\nthis \t! is-the_13212_file name")
|
25
|
-
cassette.file.should =~ /#{Regexp.escape('_this_is-the_13212_file_name.yml')}$/
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'keeps any path separators' do
|
29
|
-
cassette = VCR::Cassette.new("dir/file_name")
|
30
|
-
cassette.file.should =~ /#{Regexp.escape('dir/file_name.yml')}$/
|
31
|
-
end
|
32
|
-
|
33
|
-
VCR::Cassette::VALID_RECORD_MODES.each do |mode|
|
34
|
-
it "returns nil if the cassette_library_dir is not set (when the record mode is :#{mode})" do
|
35
|
-
VCR.configuration.cassette_library_dir = nil
|
36
|
-
cassette = VCR::Cassette.new('the_file', :record => mode)
|
37
|
-
cassette.file.should be_nil
|
38
|
-
end
|
19
|
+
it 'raises a NotImplementedError when a different persister is used' do
|
20
|
+
VCR.cassette_persisters[:a] = stub
|
21
|
+
cassette = VCR::Cassette.new("f", :persist_with => :a)
|
22
|
+
expect { cassette.file }.to raise_error(NotImplementedError)
|
39
23
|
end
|
40
24
|
end
|
41
25
|
|
@@ -144,38 +128,36 @@ describe VCR::Cassette do
|
|
144
128
|
end
|
145
129
|
|
146
130
|
describe "reading the file from disk" do
|
147
|
-
before(:each) do
|
148
|
-
File.stub(:size? => true)
|
149
|
-
end
|
150
|
-
|
151
131
|
let(:empty_cassette_yaml) { YAML.dump("http_interactions" => []) }
|
152
132
|
|
153
|
-
it '
|
154
|
-
VCR::Cassette::
|
155
|
-
|
156
|
-
|
133
|
+
it 'optionally renders the file as ERB using the ERBRenderer' do
|
134
|
+
VCR::Cassette::Persisters::FileSystem.stub(:[] => empty_cassette_yaml)
|
135
|
+
|
136
|
+
VCR::Cassette::ERBRenderer.should_receive(:new).with(
|
137
|
+
empty_cassette_yaml, anything, "foo"
|
138
|
+
).and_return(mock('renderer', :render => empty_cassette_yaml))
|
157
139
|
|
158
140
|
VCR::Cassette.new('foo', :record => :new_episodes).http_interactions
|
159
141
|
end
|
160
142
|
|
161
143
|
[true, false, nil, { }].each do |erb|
|
162
|
-
it "passes #{erb.inspect} to the VCR::Cassette::
|
144
|
+
it "passes #{erb.inspect} to the VCR::Cassette::ERBRenderer when given as the :erb option" do
|
163
145
|
# test that it overrides the default
|
164
146
|
VCR.configuration.default_cassette_options = { :erb => true }
|
165
147
|
|
166
|
-
VCR::Cassette::
|
167
|
-
anything, erb
|
168
|
-
).and_return(mock('
|
148
|
+
VCR::Cassette::ERBRenderer.should_receive(:new).with(
|
149
|
+
anything, erb, anything
|
150
|
+
).and_return(mock('renderer', :render => empty_cassette_yaml))
|
169
151
|
|
170
152
|
VCR::Cassette.new('foo', :record => :new_episodes, :erb => erb).http_interactions
|
171
153
|
end
|
172
154
|
|
173
|
-
it "passes #{erb.inspect} to the VCR::Cassette::
|
155
|
+
it "passes #{erb.inspect} to the VCR::Cassette::ERBRenderer when it is the default :erb option and none is given" do
|
174
156
|
VCR.configuration.default_cassette_options = { :erb => erb }
|
175
157
|
|
176
|
-
VCR::Cassette::
|
177
|
-
anything, erb
|
178
|
-
).and_return(mock('
|
158
|
+
VCR::Cassette::ERBRenderer.should_receive(:new).with(
|
159
|
+
anything, erb, anything
|
160
|
+
).and_return(mock('renderer', :render => empty_cassette_yaml))
|
179
161
|
|
180
162
|
VCR::Cassette.new('foo', :record => :new_episodes).http_interactions
|
181
163
|
end
|
@@ -205,6 +187,15 @@ describe VCR::Cassette do
|
|
205
187
|
VCR::Cassette.new('empty', :record => :none).send(:previously_recorded_interactions).should eq([])
|
206
188
|
end
|
207
189
|
|
190
|
+
let(:custom_persister) { stub("custom persister") }
|
191
|
+
|
192
|
+
it 'reads from the configured persister' do
|
193
|
+
VCR.configuration.cassette_library_dir = nil
|
194
|
+
VCR.cassette_persisters[:foo] = custom_persister
|
195
|
+
custom_persister.should_receive(:[]).with("abc.yml") { "" }
|
196
|
+
VCR::Cassette.new("abc", :persist_with => :foo).http_interactions
|
197
|
+
end
|
198
|
+
|
208
199
|
VCR::Cassette::VALID_RECORD_MODES.each do |record_mode|
|
209
200
|
stub_requests = (record_mode != :all)
|
210
201
|
|
@@ -401,6 +392,39 @@ describe VCR::Cassette do
|
|
401
392
|
end
|
402
393
|
|
403
394
|
describe '#eject' do
|
395
|
+
let(:custom_persister) { stub("custom persister", :[] => nil) }
|
396
|
+
|
397
|
+
it 'asserts that there are no unused interactions if allow_unused_http_interactions is set to false' do
|
398
|
+
cassette = VCR.insert_cassette("foo", :allow_unused_http_interactions => false)
|
399
|
+
|
400
|
+
interaction_list = cassette.http_interactions
|
401
|
+
interaction_list.should respond_to(:assert_no_unused_interactions!).with(0).arguments
|
402
|
+
interaction_list.should_receive(:assert_no_unused_interactions!)
|
403
|
+
|
404
|
+
cassette.eject
|
405
|
+
end
|
406
|
+
|
407
|
+
it 'does not assert that there are no unused interactions if allow_unused_http_interactions is set to true' do
|
408
|
+
cassette = VCR.insert_cassette("foo", :allow_unused_http_interactions => true)
|
409
|
+
|
410
|
+
interaction_list = cassette.http_interactions
|
411
|
+
interaction_list.should respond_to(:assert_no_unused_interactions!)
|
412
|
+
interaction_list.should_not_receive(:assert_no_unused_interactions!)
|
413
|
+
|
414
|
+
cassette.eject
|
415
|
+
end
|
416
|
+
|
417
|
+
it 'stores the cassette content using the configured persister' do
|
418
|
+
VCR.configuration.cassette_library_dir = nil
|
419
|
+
VCR.cassette_persisters[:foo] = custom_persister
|
420
|
+
cassette = VCR.insert_cassette("foo", :persist_with => :foo)
|
421
|
+
cassette.record_http_interaction http_interaction
|
422
|
+
|
423
|
+
custom_persister.should_receive(:[]=).with("foo.yml", /http_interactions/)
|
424
|
+
|
425
|
+
cassette.eject
|
426
|
+
end
|
427
|
+
|
404
428
|
it "writes the serializable_hash to disk as yaml" do
|
405
429
|
cassette = VCR::Cassette.new(:eject_test)
|
406
430
|
cassette.record_http_interaction http_interaction # so it has one
|
@@ -25,8 +25,10 @@ describe VCR::Configuration do
|
|
25
25
|
it 'has a hash with some defaults' do
|
26
26
|
subject.default_cassette_options.should eq({
|
27
27
|
:match_requests_on => VCR::RequestMatcherRegistry::DEFAULT_MATCHERS,
|
28
|
+
:allow_unused_http_interactions => true,
|
28
29
|
:record => :once,
|
29
|
-
:serialize_with => :yaml
|
30
|
+
:serialize_with => :yaml,
|
31
|
+
:persist_with => :file_system
|
30
32
|
})
|
31
33
|
end
|
32
34
|
|
@@ -131,7 +133,7 @@ describe VCR::Configuration do
|
|
131
133
|
|
132
134
|
before_record_req.should_not respond_to(:type)
|
133
135
|
before_request_req.should respond_to(:type)
|
134
|
-
end unless RUBY_VERSION =~ /^1\.8/
|
136
|
+
end unless (RUBY_VERSION =~ /^1\.8/ || RUBY_INTERPRETER == :jruby)
|
135
137
|
|
136
138
|
specify 'the filter_sensitive_data option works even when it modifies the URL in a way that makes it an invalid URI' do
|
137
139
|
VCR.configure do |c|
|
@@ -202,6 +204,26 @@ describe VCR::Configuration do
|
|
202
204
|
end
|
203
205
|
end
|
204
206
|
|
207
|
+
describe "#after_http_request" do
|
208
|
+
let(:raw_request) { VCR::Request.new }
|
209
|
+
let(:response) { VCR::Response.new }
|
210
|
+
|
211
|
+
def request(type)
|
212
|
+
VCR::Request::Typed.new(raw_request, type)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'handles symbol request predicate filters properly' do
|
216
|
+
yielded = false
|
217
|
+
subject.after_http_request(:stubbed_by_vcr?) { |req| yielded = true }
|
218
|
+
subject.invoke_hook(:after_http_request, request(:stubbed_by_vcr), response)
|
219
|
+
yielded.should be_true
|
220
|
+
|
221
|
+
yielded = false
|
222
|
+
subject.invoke_hook(:after_http_request, request(:ignored), response)
|
223
|
+
yielded.should be_false
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
205
227
|
describe "#around_http_request, when called on ruby 1.8" do
|
206
228
|
it 'raises an error since fibers are not available' do
|
207
229
|
expect {
|
@@ -219,6 +241,15 @@ describe VCR::Configuration do
|
|
219
241
|
end
|
220
242
|
end
|
221
243
|
|
244
|
+
describe "#cassette_persisters" do
|
245
|
+
let(:custom_persister) { stub }
|
246
|
+
it 'allows a custom persister to be registered' do
|
247
|
+
expect { subject.cassette_persisters[:custom] }.to raise_error(ArgumentError)
|
248
|
+
subject.cassette_persisters[:custom] = custom_persister
|
249
|
+
subject.cassette_persisters[:custom].should be(custom_persister)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
222
253
|
describe "#preserve_exact_body_bytes_for?" do
|
223
254
|
def message_for(body)
|
224
255
|
stub(:body => body)
|
@@ -139,4 +139,15 @@ describe "FakeWeb hook", :with_monkey_patches => :fakeweb do
|
|
139
139
|
end
|
140
140
|
end
|
141
141
|
end
|
142
|
+
|
143
|
+
describe "when VCR is turned off" do
|
144
|
+
it 'allows white listed connections' do
|
145
|
+
::FakeWeb.allow_net_connect = %r[localhost]
|
146
|
+
|
147
|
+
VCR.turn_off!
|
148
|
+
|
149
|
+
uri = URI("http://localhost:#{VCR::SinatraApp.port}/foo")
|
150
|
+
Net::HTTP.get(uri).should eq("FOO!")
|
151
|
+
end
|
152
|
+
end
|
142
153
|
end
|
@@ -40,5 +40,29 @@ describe "Faraday hook" do
|
|
40
40
|
Faraday::Adapter::NetHttp
|
41
41
|
])
|
42
42
|
end
|
43
|
+
|
44
|
+
it 'prints a warning if the faraday connection stack contains a middleware after the HTTP adapter' do
|
45
|
+
conn = Faraday.new(:url => 'http://sushi.com') do |builder|
|
46
|
+
builder.use Faraday::Adapter::NetHttp
|
47
|
+
builder.use Faraday::Response::Logger
|
48
|
+
end
|
49
|
+
|
50
|
+
conn.builder.should_receive(:warn).with(/Faraday::Response::Logger/)
|
51
|
+
conn.builder.lock!
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'gracefully handles the case where there is no explicit HTTP adapter' do
|
55
|
+
conn = Faraday.new(:url => 'http://sushi.com') do |builder|
|
56
|
+
builder.request :url_encoded
|
57
|
+
builder.response :logger
|
58
|
+
end
|
59
|
+
|
60
|
+
conn.builder.lock!
|
61
|
+
conn.builder.handlers.map(&:klass).should eq([
|
62
|
+
Faraday::Request::UrlEncoded,
|
63
|
+
Faraday::Response::Logger,
|
64
|
+
VCR::Middleware::Faraday
|
65
|
+
])
|
66
|
+
end
|
43
67
|
end
|
44
68
|
|
@@ -5,8 +5,8 @@ describe "WebMock hook", :with_monkey_patches => :webmock do
|
|
5
5
|
::WebMock.reset!
|
6
6
|
end
|
7
7
|
|
8
|
-
def disable_real_connections
|
9
|
-
::WebMock.disable_net_connect!
|
8
|
+
def disable_real_connections(options = {})
|
9
|
+
::WebMock.disable_net_connect!(options)
|
10
10
|
::WebMock::NetConnectNotAllowedError
|
11
11
|
end
|
12
12
|
|
@@ -18,6 +18,57 @@ describe "WebMock hook", :with_monkey_patches => :webmock do
|
|
18
18
|
::WebMock.stub_request(method, url).to_return(:body => response_body)
|
19
19
|
end
|
20
20
|
|
21
|
+
describe "our WebMock.after_request hook" do
|
22
|
+
let(:webmock_request) { ::WebMock::RequestSignature.new(:get, "http://foo.com/", :body => "", :headers => {}) }
|
23
|
+
let(:webmock_response) { ::WebMock::Response.new(:body => 'OK', :status => [200, '']) }
|
24
|
+
|
25
|
+
def run_after_request_callback
|
26
|
+
::WebMock::CallbackRegistry.invoke_callbacks(
|
27
|
+
{ :real_request => true },
|
28
|
+
webmock_request,
|
29
|
+
webmock_response)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'removes the @__typed_vcr_request instance variable so as not to pollute the webmock object' do
|
33
|
+
request = VCR::Request::Typed.new(VCR::Request, :ignored?)
|
34
|
+
webmock_request.instance_variable_set(:@__typed_vcr_request, request)
|
35
|
+
|
36
|
+
run_after_request_callback
|
37
|
+
webmock_request.instance_variables.map(&:to_sym).should_not include(:@__typed_vcr_request)
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when there'ss a bug and the request does not have the @__typed_vcr_request in the after_request callbacks" do
|
41
|
+
let(:warner) { VCR::LibraryHooks::WebMock }
|
42
|
+
before { warner.stub(:warn) }
|
43
|
+
|
44
|
+
it 'records the HTTP interaction properly' do
|
45
|
+
VCR.should_receive(:record_http_interaction) do |i|
|
46
|
+
i.request.uri.should eq("http://foo.com/")
|
47
|
+
i.response.body.should eq("OK")
|
48
|
+
end
|
49
|
+
|
50
|
+
run_after_request_callback
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'invokes the after_http_request hook with an :unknown request' do
|
54
|
+
request = nil
|
55
|
+
VCR.configuration.after_http_request do |req, res|
|
56
|
+
request = req
|
57
|
+
end
|
58
|
+
|
59
|
+
run_after_request_callback
|
60
|
+
request.uri.should eq("http://foo.com/")
|
61
|
+
request.type.should eq(:unknown)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'prints a warning' do
|
65
|
+
warner.should_receive(:warn).at_least(:once).with(/bug.*after_request/)
|
66
|
+
|
67
|
+
run_after_request_callback
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
21
72
|
%w[net/http patron httpclient em-http-request curb typhoeus excon].each do |lib|
|
22
73
|
other = []
|
23
74
|
other << :status_message_not_exposed if lib == 'excon'
|
@@ -28,5 +79,34 @@ describe "WebMock hook", :with_monkey_patches => :webmock do
|
|
28
79
|
end
|
29
80
|
end
|
30
81
|
end
|
82
|
+
|
83
|
+
http_lib_unsupported = (RUBY_INTERPRETER != :mri && lib =~ /(typhoeus|curb|patron|em-http)/)
|
84
|
+
|
85
|
+
adapter_module = HTTP_LIBRARY_ADAPTERS.fetch(lib)
|
86
|
+
describe "using #{adapter_module.http_library_name}", :unless => http_lib_unsupported do
|
87
|
+
include adapter_module
|
88
|
+
|
89
|
+
let!(:request_url) { "http://localhost:#{VCR::SinatraApp.port}/foo" }
|
90
|
+
|
91
|
+
context 'when real connections are disabled and VCR is turned off' do
|
92
|
+
it 'can allow connections to localhost' do
|
93
|
+
VCR.turn_off!
|
94
|
+
unexpected_error = disable_real_connections(:allow_localhost => true)
|
95
|
+
|
96
|
+
expect {
|
97
|
+
make_http_request(:get, request_url)
|
98
|
+
}.to_not raise_error(unexpected_error)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'can allow connections to matching urls' do
|
102
|
+
VCR.turn_off!
|
103
|
+
unexpected_error = disable_real_connections(:allow => /foo/)
|
104
|
+
|
105
|
+
expect {
|
106
|
+
make_http_request(:get, request_url)
|
107
|
+
}.to_not raise_error(unexpected_error)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
31
111
|
end
|
32
112
|
end
|
@@ -9,6 +9,38 @@ describe VCR::Middleware::Faraday do
|
|
9
9
|
:not_disableable
|
10
10
|
end
|
11
11
|
|
12
|
+
context 'when performing a multipart upload' do
|
13
|
+
let(:connection) do
|
14
|
+
::Faraday.new("http://localhost:#{VCR::SinatraApp.port}/") do |b|
|
15
|
+
b.request :multipart
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.test_recording
|
20
|
+
it 'records the request body correctly' do
|
21
|
+
payload = { :file => Faraday::UploadIO.new(__FILE__, 'text/plain') }
|
22
|
+
|
23
|
+
VCR.should_receive(:record_http_interaction) do |i|
|
24
|
+
i.request.headers['Content-Type'].first.should include("multipart")
|
25
|
+
i.request.body.should include(File.read(__FILE__))
|
26
|
+
end
|
27
|
+
|
28
|
+
VCR.use_cassette("upload") do
|
29
|
+
connection.post '/files', payload
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when the net_http adapter is used' do
|
35
|
+
before { connection.builder.adapter :net_http }
|
36
|
+
test_recording
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when no adapter is used' do
|
40
|
+
test_recording
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
12
44
|
context 'when making parallel requests' do
|
13
45
|
include VCRStubHelpers
|
14
46
|
let(:connection) { ::Faraday.new { |b| b.adapter :typhoeus } }
|
data/spec/vcr/structs_spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
+
require 'support/ruby_interpreter'
|
4
|
+
|
3
5
|
require 'yaml'
|
4
6
|
require 'vcr/structs'
|
5
7
|
require 'vcr/errors'
|
@@ -49,6 +51,12 @@ shared_examples_for "a body normalizer" do
|
|
49
51
|
it 'converts nil to a blank string' do
|
50
52
|
instance(nil).body.should eq("")
|
51
53
|
end
|
54
|
+
|
55
|
+
it 'raises an error if given another type of object as the body' do
|
56
|
+
expect {
|
57
|
+
instance(:a => "hash")
|
58
|
+
}.to raise_error(ArgumentError)
|
59
|
+
end
|
52
60
|
end
|
53
61
|
|
54
62
|
module VCR
|
@@ -190,13 +198,20 @@ module VCR
|
|
190
198
|
end
|
191
199
|
|
192
200
|
context 'when the string cannot be encoded as the original encoding' do
|
201
|
+
def verify_encoding_error
|
202
|
+
pending "rubinius 1.9 mode does not raise an encoding error", :if => (RUBY_INTERPRETER == :rubinius && RUBY_VERSION =~ /^1.9/) do
|
203
|
+
expect { "\xFAbc".encode("ISO-8859-1") }.to raise_error(EncodingError)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
193
207
|
before do
|
194
208
|
Request.stub(:warn)
|
195
209
|
Response.stub(:warn)
|
196
210
|
|
197
211
|
hash['request']['body'] = { 'string' => "\xFAbc", 'encoding' => 'ISO-8859-1' }
|
198
212
|
hash['response']['body'] = { 'string' => "\xFAbc", 'encoding' => 'ISO-8859-1' }
|
199
|
-
|
213
|
+
|
214
|
+
verify_encoding_error
|
200
215
|
end
|
201
216
|
|
202
217
|
it 'does not force the encoding' do
|
@@ -348,6 +363,12 @@ module VCR
|
|
348
363
|
it 'replaces sensitive text in the request URI' do
|
349
364
|
filtered.request.uri.should eq('http://example-AAA.com/AAA/')
|
350
365
|
end
|
366
|
+
|
367
|
+
it 'handles numbers (such as the port) properly' do
|
368
|
+
request.uri = "http://foo.com:9000/bar"
|
369
|
+
subject.filter!(9000, "<PORT>")
|
370
|
+
request.uri.should eq("http://foo.com:<PORT>/bar")
|
371
|
+
end
|
351
372
|
end
|
352
373
|
end
|
353
374
|
|
@@ -365,7 +386,8 @@ module VCR
|
|
365
386
|
end
|
366
387
|
end
|
367
388
|
|
368
|
-
[:ignored, :
|
389
|
+
valid_types = [:ignored, :stubbed_by_vcr, :externally_stubbed, :recordable, :unhandled]
|
390
|
+
valid_types.each do |type|
|
369
391
|
describe "##{type}?" do
|
370
392
|
it "returns true if the type is set to :#{type}" do
|
371
393
|
Request::Typed.new(stub, type).send("#{type}?").should be_true
|
@@ -378,18 +400,34 @@ module VCR
|
|
378
400
|
end
|
379
401
|
|
380
402
|
describe "#real?" do
|
381
|
-
[:ignored, :recordable]
|
403
|
+
real_types = [:ignored, :recordable]
|
404
|
+
real_types.each do |type|
|
382
405
|
it "returns true if the type is set to :#{type}" do
|
383
406
|
Request::Typed.new(stub, type).should be_real
|
384
407
|
end
|
385
408
|
end
|
386
409
|
|
387
|
-
|
410
|
+
(valid_types - real_types).each do |type|
|
388
411
|
it "returns false if the type is set to :#{type}" do
|
389
412
|
Request::Typed.new(stub, type).should_not be_real
|
390
413
|
end
|
391
414
|
end
|
392
415
|
end
|
416
|
+
|
417
|
+
describe "#stubbed?" do
|
418
|
+
stubbed_types = [:externally_stubbed, :stubbed_by_vcr]
|
419
|
+
stubbed_types.each do |type|
|
420
|
+
it "returns true if the type is set to :#{type}" do
|
421
|
+
Request::Typed.new(stub, type).should be_stubbed
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
(valid_types - stubbed_types).each do |type|
|
426
|
+
it "returns false if the type is set to :#{type}" do
|
427
|
+
Request::Typed.new(stub, type).should_not be_stubbed
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
393
431
|
end
|
394
432
|
|
395
433
|
describe Request do
|
@@ -561,22 +599,24 @@ module VCR
|
|
561
599
|
end
|
562
600
|
|
563
601
|
it "unzips gzipped response" do
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
602
|
+
pending "rubinius 1.9 mode has a Gzip issue", :if => (RUBY_INTERPRETER == :rubinius && RUBY_VERSION =~ /^1.9/) do
|
603
|
+
io = StringIO.new
|
604
|
+
|
605
|
+
writer = Zlib::GzipWriter.new(io)
|
606
|
+
writer << content
|
607
|
+
writer.close
|
608
|
+
|
609
|
+
gzipped = io.string
|
610
|
+
resp = instance(gzipped, 'gzip')
|
611
|
+
resp.should be_compressed
|
612
|
+
expect {
|
613
|
+
resp.decompress.should equal(resp)
|
614
|
+
resp.should_not be_compressed
|
615
|
+
resp.body.should eq(content)
|
616
|
+
}.to change { resp.headers['content-length'] }.
|
617
|
+
from([gzipped.bytesize.to_s]).
|
618
|
+
to([content.bytesize.to_s])
|
619
|
+
end
|
580
620
|
end
|
581
621
|
|
582
622
|
it "inflates deflated response" do
|