vcr 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.travis.yml +2 -1
  2. data/CHANGELOG.md +58 -1
  3. data/Gemfile +0 -6
  4. data/README.md +12 -3
  5. data/Rakefile +2 -2
  6. data/features/.nav +2 -0
  7. data/features/cassettes/allow_unused_http_interactions.feature +86 -0
  8. data/features/cassettes/naming.feature +3 -2
  9. data/features/cassettes/persistence.feature +63 -0
  10. data/features/configuration/debug_logging.feature +3 -3
  11. data/features/configuration/ignore_request.feature +1 -1
  12. data/features/hooks/after_http_request.feature +1 -1
  13. data/features/step_definitions/cli_steps.rb +33 -0
  14. data/features/support/env.rb +0 -1
  15. data/lib/vcr.rb +13 -0
  16. data/lib/vcr/cassette.rb +57 -44
  17. data/lib/vcr/cassette/{reader.rb → erb_renderer.rb} +9 -11
  18. data/lib/vcr/cassette/http_interaction_list.rb +18 -0
  19. data/lib/vcr/cassette/persisters.rb +42 -0
  20. data/lib/vcr/cassette/persisters/file_system.rb +60 -0
  21. data/lib/vcr/cassette/serializers.rb +1 -1
  22. data/lib/vcr/cassette/serializers/json.rb +1 -1
  23. data/lib/vcr/cassette/serializers/psych.rb +1 -1
  24. data/lib/vcr/cassette/serializers/syck.rb +1 -1
  25. data/lib/vcr/cassette/serializers/yaml.rb +1 -1
  26. data/lib/vcr/configuration.rb +49 -25
  27. data/lib/vcr/errors.rb +6 -0
  28. data/lib/vcr/library_hooks/excon.rb +1 -1
  29. data/lib/vcr/library_hooks/fakeweb.rb +16 -3
  30. data/lib/vcr/library_hooks/faraday.rb +13 -0
  31. data/lib/vcr/library_hooks/typhoeus.rb +5 -1
  32. data/lib/vcr/library_hooks/webmock.rb +90 -35
  33. data/lib/vcr/middleware/faraday.rb +12 -4
  34. data/lib/vcr/request_handler.rb +10 -2
  35. data/lib/vcr/structs.rb +31 -7
  36. data/lib/vcr/version.rb +1 -1
  37. data/script/ci.sh +14 -0
  38. data/spec/spec_helper.rb +8 -1
  39. data/spec/support/shared_example_groups/hook_into_http_library.rb +31 -1
  40. data/spec/vcr/cassette/{reader_spec.rb → erb_renderer_spec.rb} +15 -21
  41. data/spec/vcr/cassette/http_interaction_list_spec.rb +15 -0
  42. data/spec/vcr/cassette/persisters/file_system_spec.rb +64 -0
  43. data/spec/vcr/cassette/persisters_spec.rb +39 -0
  44. data/spec/vcr/cassette/serializers_spec.rb +4 -3
  45. data/spec/vcr/cassette_spec.rb +65 -41
  46. data/spec/vcr/configuration_spec.rb +33 -2
  47. data/spec/vcr/library_hooks/fakeweb_spec.rb +11 -0
  48. data/spec/vcr/library_hooks/faraday_spec.rb +24 -0
  49. data/spec/vcr/library_hooks/webmock_spec.rb +82 -2
  50. data/spec/vcr/middleware/faraday_spec.rb +32 -0
  51. data/spec/vcr/structs_spec.rb +60 -20
  52. data/spec/vcr/util/hooks_spec.rb +7 -0
  53. data/spec/vcr_spec.rb +7 -0
  54. data/vcr.gemspec +2 -2
  55. metadata +31 -26
  56. data/Guardfile +0 -9
  57. data/script/FullBuildRakeFile +0 -56
  58. data/script/full_build +0 -1
  59. 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
@@ -9,33 +9,17 @@ describe VCR::Cassette do
9
9
  end
10
10
 
11
11
  describe '#file' do
12
- it 'combines the cassette_library_dir with the cassette name' do
13
- cassette = VCR::Cassette.new('the_file')
14
- cassette.file.should eq(File.join(VCR.configuration.cassette_library_dir, 'the_file.yml'))
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 'uses the file extension from the serializer' do
18
- VCR.cassette_serializers[:custom] = stub(:file_extension => "custom")
19
- cassette = VCR::Cassette.new('the_file', :serialize_with => :custom)
20
- cassette.file.should =~ /\.custom$/
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 'reads the appropriate file from disk using a VCR::Cassette::Reader' do
154
- VCR::Cassette::Reader.should_receive(:new).with(
155
- "#{VCR.configuration.cassette_library_dir}/foo.yml", anything
156
- ).and_return(mock('reader', :read => empty_cassette_yaml))
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::Reader when given as the :erb option" do
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::Reader.should_receive(:new).with(
167
- anything, erb
168
- ).and_return(mock('reader', :read => empty_cassette_yaml))
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::Reader when it is the default :erb option and none is given" do
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::Reader.should_receive(:new).with(
177
- anything, erb
178
- ).and_return(mock('reader', :read => empty_cassette_yaml))
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 } }
@@ -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
- expect { "\xFAbc".encode("ISO-8859-1") }.to raise_error(EncodingError)
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, :stubbed, :recordable, :unhandled].each do |type|
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].each do |type|
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
- [:stubbed, :unhandled].each do |type|
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
- io = StringIO.new
565
-
566
- writer = Zlib::GzipWriter.new(io)
567
- writer << content
568
- writer.close
569
-
570
- gzipped = io.string
571
- resp = instance(gzipped, 'gzip')
572
- resp.should be_compressed
573
- expect {
574
- resp.decompress.should equal(resp)
575
- resp.should_not be_compressed
576
- resp.body.should eq(content)
577
- }.to change { resp.headers['content-length'] }.
578
- from([gzipped.bytesize.to_s]).
579
- to([content.bytesize.to_s])
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