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.
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