vcr 2.1.1 → 2.2.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/.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
|