vcr 3.0.3 → 6.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.
- checksums.yaml +5 -5
- data/lib/vcr/cassette/erb_renderer.rb +4 -2
- data/lib/vcr/cassette/http_interaction_list.rb +14 -9
- data/lib/vcr/cassette/migrator.rb +5 -6
- data/lib/vcr/cassette/persisters/file_system.rb +9 -1
- data/lib/vcr/cassette/serializers/compressed.rb +2 -2
- data/lib/vcr/cassette/serializers/json.rb +14 -8
- data/lib/vcr/cassette/serializers/psych.rb +10 -2
- data/lib/vcr/cassette/serializers/syck.rb +7 -1
- data/lib/vcr/cassette/serializers/yaml.rb +14 -2
- data/lib/vcr/cassette/serializers.rb +10 -0
- data/lib/vcr/cassette.rb +63 -16
- data/lib/vcr/configuration.rb +21 -8
- data/lib/vcr/deprecations.rb +0 -62
- data/lib/vcr/errors.rb +17 -12
- data/lib/vcr/library_hooks/excon.rb +8 -0
- data/lib/vcr/library_hooks/typhoeus.rb +91 -79
- data/lib/vcr/library_hooks/webmock.rb +2 -11
- data/lib/vcr/linked_cassette.rb +4 -4
- data/lib/vcr/middleware/excon.rb +1 -1
- data/lib/vcr/middleware/faraday.rb +29 -2
- data/lib/vcr/request_ignorer.rb +8 -1
- data/lib/vcr/request_matcher_registry.rb +3 -3
- data/lib/vcr/structs.rb +48 -32
- data/lib/vcr/test_frameworks/cucumber.rb +16 -5
- data/lib/vcr/test_frameworks/rspec.rb +34 -22
- data/lib/vcr/util/hooks.rb +1 -0
- data/lib/vcr/util/internet_connection.rb +15 -21
- data/lib/vcr/version.rb +2 -2
- data/lib/vcr.rb +52 -2
- metadata +45 -272
- data/features/CHANGELOG.md +0 -710
- data/features/CONTRIBUTING.md +0 -26
- data/features/LICENSE.md +0 -20
- data/features/README.md +0 -339
- data/features/Upgrade.md +0 -289
- data/features/about_these_examples.md +0 -18
- data/features/cassettes/allow_unused_http_interactions.feature +0 -100
- data/features/cassettes/automatic_re_recording.feature +0 -72
- data/features/cassettes/decompress.feature +0 -74
- data/features/cassettes/dynamic_erb.feature +0 -100
- data/features/cassettes/exclusive.feature +0 -126
- data/features/cassettes/format.feature +0 -411
- data/features/cassettes/freezing_time.feature +0 -68
- data/features/cassettes/naming.feature +0 -28
- data/features/cassettes/no_cassette.feature +0 -152
- data/features/cassettes/update_content_length_header.feature +0 -112
- data/features/configuration/allow_http_connections_when_no_cassette.feature +0 -55
- data/features/configuration/cassette_library_dir.feature +0 -31
- data/features/configuration/debug_logging.feature +0 -58
- data/features/configuration/default_cassette_options.feature +0 -100
- data/features/configuration/filter_sensitive_data.feature +0 -153
- data/features/configuration/hook_into.feature +0 -172
- data/features/configuration/ignore_request.feature +0 -192
- data/features/configuration/preserve_exact_body_bytes.feature +0 -108
- data/features/configuration/query_parser.feature +0 -84
- data/features/configuration/uri_parser.feature +0 -93
- data/features/getting_started.md +0 -82
- data/features/hooks/after_http_request.feature +0 -58
- data/features/hooks/around_http_request.feature +0 -57
- data/features/hooks/before_http_request.feature +0 -63
- data/features/hooks/before_playback.feature +0 -184
- data/features/hooks/before_record.feature +0 -172
- data/features/http_libraries/em_http_request.feature +0 -250
- data/features/http_libraries/net_http.feature +0 -179
- data/features/middleware/faraday.feature +0 -56
- data/features/middleware/rack.feature +0 -92
- data/features/record_modes/all.feature +0 -82
- data/features/record_modes/new_episodes.feature +0 -79
- data/features/record_modes/none.feature +0 -72
- data/features/record_modes/once.feature +0 -95
- data/features/request_matching/README.md +0 -30
- data/features/request_matching/body.feature +0 -91
- data/features/request_matching/body_as_json.feature +0 -90
- data/features/request_matching/custom_matcher.feature +0 -135
- data/features/request_matching/headers.feature +0 -85
- data/features/request_matching/host.feature +0 -95
- data/features/request_matching/identical_request_sequence.feature +0 -89
- data/features/request_matching/method.feature +0 -96
- data/features/request_matching/path.feature +0 -96
- data/features/request_matching/playback_repeats.feature +0 -98
- data/features/request_matching/query.feature +0 -97
- data/features/request_matching/uri.feature +0 -94
- data/features/request_matching/uri_without_param.feature +0 -101
- data/features/step_definitions/cli_steps.rb +0 -199
- data/features/support/env.rb +0 -46
- data/features/support/http_lib_filters.rb +0 -46
- data/features/test_frameworks/cucumber.feature +0 -211
- data/features/test_frameworks/rspec_macro.feature +0 -81
- data/features/test_frameworks/rspec_metadata.feature +0 -150
- data/features/test_frameworks/test_unit.feature +0 -49
- data/lib/vcr/extensions/net_http_response.rb +0 -36
- data/lib/vcr/library_hooks/fakeweb.rb +0 -197
- data/lib/vcr/library_hooks/typhoeus_0.4.rb +0 -103
- data/spec/acceptance/concurrency_spec.rb +0 -51
- data/spec/acceptance/threading_spec.rb +0 -34
- data/spec/fixtures/cassette_spec/1_x_cassette.yml +0 -110
- data/spec/fixtures/cassette_spec/empty.yml +0 -0
- data/spec/fixtures/cassette_spec/example.yml +0 -111
- data/spec/fixtures/cassette_spec/with_localhost_requests.yml +0 -111
- data/spec/fixtures/fake_example_responses.yml +0 -110
- data/spec/fixtures/match_requests_on.yml +0 -187
- data/spec/lib/vcr/cassette/erb_renderer_spec.rb +0 -53
- data/spec/lib/vcr/cassette/http_interaction_list_spec.rb +0 -295
- data/spec/lib/vcr/cassette/migrator_spec.rb +0 -196
- data/spec/lib/vcr/cassette/persisters/file_system_spec.rb +0 -75
- data/spec/lib/vcr/cassette/persisters_spec.rb +0 -39
- data/spec/lib/vcr/cassette/serializers_spec.rb +0 -182
- data/spec/lib/vcr/cassette_spec.rb +0 -618
- data/spec/lib/vcr/configuration_spec.rb +0 -326
- data/spec/lib/vcr/deprecations_spec.rb +0 -85
- data/spec/lib/vcr/errors_spec.rb +0 -178
- data/spec/lib/vcr/extensions/net_http_response_spec.rb +0 -86
- data/spec/lib/vcr/library_hooks/excon_spec.rb +0 -104
- data/spec/lib/vcr/library_hooks/fakeweb_spec.rb +0 -169
- data/spec/lib/vcr/library_hooks/faraday_spec.rb +0 -68
- data/spec/lib/vcr/library_hooks/typhoeus_0.4_spec.rb +0 -36
- data/spec/lib/vcr/library_hooks/typhoeus_spec.rb +0 -162
- data/spec/lib/vcr/library_hooks/webmock_spec.rb +0 -117
- data/spec/lib/vcr/library_hooks_spec.rb +0 -51
- data/spec/lib/vcr/middleware/faraday_spec.rb +0 -181
- data/spec/lib/vcr/middleware/rack_spec.rb +0 -115
- data/spec/lib/vcr/request_ignorer_spec.rb +0 -70
- data/spec/lib/vcr/request_matcher_registry_spec.rb +0 -345
- data/spec/lib/vcr/structs_spec.rb +0 -732
- data/spec/lib/vcr/test_frameworks/cucumber_spec.rb +0 -107
- data/spec/lib/vcr/test_frameworks/rspec_spec.rb +0 -94
- data/spec/lib/vcr/util/hooks_spec.rb +0 -158
- data/spec/lib/vcr/util/internet_connection_spec.rb +0 -37
- data/spec/lib/vcr/util/version_checker_spec.rb +0 -31
- data/spec/lib/vcr/version_spec.rb +0 -27
- data/spec/lib/vcr_spec.rb +0 -354
- data/spec/monkey_patches.rb +0 -186
- data/spec/spec_helper.rb +0 -63
- data/spec/support/configuration_stubbing.rb +0 -8
- data/spec/support/cucumber_helpers.rb +0 -39
- data/spec/support/fixnum_extension.rb +0 -10
- data/spec/support/http_library_adapters.rb +0 -289
- data/spec/support/limited_uri.rb +0 -21
- data/spec/support/ruby_interpreter.rb +0 -7
- data/spec/support/shared_example_groups/excon.rb +0 -63
- data/spec/support/shared_example_groups/hook_into_http_library.rb +0 -594
- data/spec/support/shared_example_groups/request_hooks.rb +0 -59
- data/spec/support/sinatra_app.rb +0 -86
- data/spec/support/vcr_localhost_server.rb +0 -76
- data/spec/support/vcr_stub_helpers.rb +0 -17
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
@with-bundler
|
|
2
|
-
Feature: Usage with RSpec metadata
|
|
3
|
-
|
|
4
|
-
VCR provides easy integration with RSpec using metadata. To set this
|
|
5
|
-
up, call `configure_rspec_metadata!` in your `VCR.configure` block.
|
|
6
|
-
|
|
7
|
-
Once you've done that, you can have an example group or example use
|
|
8
|
-
VCR by passing `:vcr` as an additional argument after the description
|
|
9
|
-
string. It will set the cassette name based on the example's
|
|
10
|
-
full description.
|
|
11
|
-
|
|
12
|
-
If you need to override the cassette name or options, you can pass a
|
|
13
|
-
hash (`:vcr => { ... }`).
|
|
14
|
-
|
|
15
|
-
Background:
|
|
16
|
-
Given a file named "spec/spec_helper.rb" with:
|
|
17
|
-
"""ruby
|
|
18
|
-
require 'vcr'
|
|
19
|
-
|
|
20
|
-
VCR.configure do |c|
|
|
21
|
-
c.cassette_library_dir = 'spec/cassettes'
|
|
22
|
-
c.hook_into :webmock
|
|
23
|
-
c.configure_rspec_metadata!
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
RSpec.configure do |c|
|
|
27
|
-
# so we can use `:vcr` rather than `:vcr => true`;
|
|
28
|
-
# in RSpec 3 this will no longer be necessary.
|
|
29
|
-
c.treat_symbols_as_metadata_keys_with_true_values = true
|
|
30
|
-
end
|
|
31
|
-
"""
|
|
32
|
-
And a previously recorded cassette file "spec/cassettes/Group/optionally_raises_an_error.yml" with:
|
|
33
|
-
"""
|
|
34
|
-
---
|
|
35
|
-
http_interactions:
|
|
36
|
-
- request:
|
|
37
|
-
method: get
|
|
38
|
-
uri: http://example.com/foo
|
|
39
|
-
body:
|
|
40
|
-
encoding: UTF-8
|
|
41
|
-
string: ""
|
|
42
|
-
headers: {}
|
|
43
|
-
response:
|
|
44
|
-
status:
|
|
45
|
-
code: 200
|
|
46
|
-
message: OK
|
|
47
|
-
headers:
|
|
48
|
-
Content-Length:
|
|
49
|
-
- "5"
|
|
50
|
-
body:
|
|
51
|
-
encoding: UTF-8
|
|
52
|
-
string: Hello
|
|
53
|
-
http_version: "1.1"
|
|
54
|
-
recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
|
|
55
|
-
recorded_with: VCR 2.0.0
|
|
56
|
-
"""
|
|
57
|
-
|
|
58
|
-
Scenario: Use `:vcr` metadata
|
|
59
|
-
Given a file named "spec/vcr_example_spec.rb" with:
|
|
60
|
-
"""ruby
|
|
61
|
-
$server = start_sinatra_app do
|
|
62
|
-
get('/') { "Hello" }
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def make_http_request
|
|
66
|
-
Net::HTTP.get_response('localhost', '/', $server.port).body
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
require 'spec_helper'
|
|
70
|
-
|
|
71
|
-
describe "VCR example group metadata", :vcr do
|
|
72
|
-
it 'records an http request' do
|
|
73
|
-
expect(make_http_request).to eq('Hello')
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it 'records another http request' do
|
|
77
|
-
expect(make_http_request).to eq('Hello')
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
context 'in a nested example group' do
|
|
81
|
-
it 'records another one' do
|
|
82
|
-
expect(make_http_request).to eq('Hello')
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
describe "VCR example metadata" do
|
|
88
|
-
it 'records an http request', :vcr do
|
|
89
|
-
expect(make_http_request).to eq('Hello')
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
"""
|
|
93
|
-
When I run `rspec spec/vcr_example_spec.rb`
|
|
94
|
-
Then it should pass with "4 examples, 0 failures"
|
|
95
|
-
And the file "spec/cassettes/VCR_example_group_metadata/records_an_http_request.yml" should contain "Hello"
|
|
96
|
-
And the file "spec/cassettes/VCR_example_group_metadata/records_another_http_request.yml" should contain "Hello"
|
|
97
|
-
And the file "spec/cassettes/VCR_example_group_metadata/in_a_nested_example_group/records_another_one.yml" should contain "Hello"
|
|
98
|
-
And the file "spec/cassettes/VCR_example_metadata/records_an_http_request.yml" should contain "Hello"
|
|
99
|
-
|
|
100
|
-
Scenario: `:allow_unused_http_interactions => false` causes a failure if there are unused interactions
|
|
101
|
-
And a file named "spec/vcr_example_spec.rb" with:
|
|
102
|
-
"""ruby
|
|
103
|
-
require 'spec_helper'
|
|
104
|
-
|
|
105
|
-
describe "Group", :vcr => { :allow_unused_http_interactions => false } do
|
|
106
|
-
it 'optionally raises an error' do
|
|
107
|
-
# don't fail
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
"""
|
|
111
|
-
When I run `rspec spec/vcr_example_spec.rb`
|
|
112
|
-
Then it should fail with an error like:
|
|
113
|
-
"""
|
|
114
|
-
There are unused HTTP interactions left in the cassette:
|
|
115
|
-
- [get http://example.com/foo] => [200 "Hello"]
|
|
116
|
-
"""
|
|
117
|
-
|
|
118
|
-
Scenario: `:allow_unused_http_interactions => false` does not raise if the example already failed
|
|
119
|
-
And a file named "spec/vcr_example_spec.rb" with:
|
|
120
|
-
"""ruby
|
|
121
|
-
require 'spec_helper'
|
|
122
|
-
|
|
123
|
-
describe "Group", :vcr => { :allow_unused_http_interactions => false } do
|
|
124
|
-
it 'optionally raises an error' do
|
|
125
|
-
raise "boom"
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
"""
|
|
129
|
-
When I run `rspec spec/vcr_example_spec.rb`
|
|
130
|
-
Then it should fail with "boom"
|
|
131
|
-
And the output should not contain "There are unused HTTP interactions"
|
|
132
|
-
|
|
133
|
-
Scenario: Pass a hash to set the cassette options
|
|
134
|
-
Given a file named "spec/vcr_example_spec.rb" with:
|
|
135
|
-
"""ruby
|
|
136
|
-
require 'spec_helper'
|
|
137
|
-
|
|
138
|
-
vcr_options = { :cassette_name => "example", :record => :new_episodes }
|
|
139
|
-
describe "Using an options hash", :vcr => vcr_options do
|
|
140
|
-
it 'uses the provided cassette name' do
|
|
141
|
-
expect(VCR.current_cassette.name).to eq("example")
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
it 'sets the given options' do
|
|
145
|
-
expect(VCR.current_cassette.record_mode).to eq(:new_episodes)
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
"""
|
|
149
|
-
When I run `rspec spec/vcr_example_spec.rb`
|
|
150
|
-
Then it should pass with "2 examples, 0 failures"
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
Feature: Usage with Test::Unit
|
|
2
|
-
|
|
3
|
-
To use VCR with Test::Unit, wrap the body of any test method in
|
|
4
|
-
`VCR.use_cassette`.
|
|
5
|
-
|
|
6
|
-
Scenario: Use `VCR.use_cassette` in a test
|
|
7
|
-
Given a file named "test/test_server.rb" with:
|
|
8
|
-
"""ruby
|
|
9
|
-
$server = start_sinatra_app do
|
|
10
|
-
get('/') { "Hello" }
|
|
11
|
-
end
|
|
12
|
-
"""
|
|
13
|
-
Given a file named "test/test_helper.rb" with:
|
|
14
|
-
"""ruby
|
|
15
|
-
require 'test/test_server' if ENV['SERVER'] == 'true'
|
|
16
|
-
require 'test/unit'
|
|
17
|
-
require 'vcr'
|
|
18
|
-
|
|
19
|
-
VCR.configure do |c|
|
|
20
|
-
c.hook_into :webmock
|
|
21
|
-
c.cassette_library_dir = 'test/fixtures/vcr_cassettes'
|
|
22
|
-
c.default_cassette_options = {
|
|
23
|
-
:match_requests_on => [:method, :host, :path]
|
|
24
|
-
}
|
|
25
|
-
end
|
|
26
|
-
"""
|
|
27
|
-
And a file named "test/vcr_example_test.rb" with:
|
|
28
|
-
"""ruby
|
|
29
|
-
require 'test_helper'
|
|
30
|
-
|
|
31
|
-
class VCRExampleTest < Test::Unit::TestCase
|
|
32
|
-
def test_use_vcr
|
|
33
|
-
VCR.use_cassette('test_unit_example') do
|
|
34
|
-
response = Net::HTTP.get_response('localhost', '/', $server ? $server.port : 0)
|
|
35
|
-
assert_equal "Hello", response.body
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
"""
|
|
40
|
-
And the directory "test/fixtures/vcr_cassettes" does not exist
|
|
41
|
-
When I set the "SERVER" environment variable to "true"
|
|
42
|
-
And I run `ruby -Itest test/vcr_example_test.rb`
|
|
43
|
-
Then it should pass with "1 tests, 1 assertions, 0 failures, 0 errors"
|
|
44
|
-
And the file "test/fixtures/vcr_cassettes/test_unit_example.yml" should contain "Hello"
|
|
45
|
-
|
|
46
|
-
# Run again without starting the sinatra server so the response will be replayed
|
|
47
|
-
When I set the "SERVER" environment variable to "false"
|
|
48
|
-
And I run `ruby -Itest test/vcr_example_test.rb`
|
|
49
|
-
Then it should pass with "1 tests, 1 assertions, 0 failures, 0 errors"
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
module VCR
|
|
2
|
-
# @private
|
|
3
|
-
module Net
|
|
4
|
-
# A Net::HTTP response that has already been read raises an IOError when #read_body
|
|
5
|
-
# is called with a destination string or block.
|
|
6
|
-
#
|
|
7
|
-
# This causes a problem when VCR records a response--it reads the body before yielding
|
|
8
|
-
# the response, and if the code that is consuming the HTTP requests uses #read_body, it
|
|
9
|
-
# can cause an error.
|
|
10
|
-
#
|
|
11
|
-
# This is a bit of a hack, but it allows a Net::HTTP response to be "re-read"
|
|
12
|
-
# after it has aleady been read. This attemps to preserve the behavior of
|
|
13
|
-
# #read_body, acting just as if it had never been read.
|
|
14
|
-
# @private
|
|
15
|
-
module HTTPResponse
|
|
16
|
-
def self.extended(response)
|
|
17
|
-
response.instance_variable_set(:@__read_body_previously_called, false)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def read_body(dest = nil, &block)
|
|
21
|
-
return super if @__read_body_previously_called
|
|
22
|
-
return @body if dest.nil? && block.nil?
|
|
23
|
-
raise ArgumentError.new("both arg and block given for HTTP method") if dest && block
|
|
24
|
-
|
|
25
|
-
if @body
|
|
26
|
-
dest ||= ::Net::ReadAdapter.new(block)
|
|
27
|
-
dest << @body
|
|
28
|
-
@body = dest
|
|
29
|
-
end
|
|
30
|
-
ensure
|
|
31
|
-
# allow subsequent calls to #read_body to proceed as normal, without our hack...
|
|
32
|
-
@__read_body_previously_called = true
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
require 'vcr/util/version_checker'
|
|
2
|
-
require 'fakeweb'
|
|
3
|
-
require 'net/http'
|
|
4
|
-
require 'vcr/extensions/net_http_response'
|
|
5
|
-
require 'vcr/request_handler'
|
|
6
|
-
require 'set'
|
|
7
|
-
|
|
8
|
-
VCR::VersionChecker.new('FakeWeb', FakeWeb::VERSION, '1.3.0').check_version!
|
|
9
|
-
|
|
10
|
-
module VCR
|
|
11
|
-
class LibraryHooks
|
|
12
|
-
# @private
|
|
13
|
-
module FakeWeb
|
|
14
|
-
# @private
|
|
15
|
-
class RequestHandler < ::VCR::RequestHandler
|
|
16
|
-
attr_reader :net_http, :request, :request_body, :response_block
|
|
17
|
-
def initialize(net_http, request, request_body = nil, &response_block)
|
|
18
|
-
@net_http, @request, @request_body, @response_block =
|
|
19
|
-
net_http, request, request_body, response_block
|
|
20
|
-
@stubbed_response, @vcr_response, @recursing = nil, nil, false
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def handle
|
|
24
|
-
super
|
|
25
|
-
ensure
|
|
26
|
-
invoke_after_request_hook(@vcr_response) unless @recursing
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
def externally_stubbed?
|
|
32
|
-
::FakeWeb.registered_uri?(request_method, uri)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def on_externally_stubbed_request
|
|
36
|
-
# just perform the request--FakeWeb will handle it
|
|
37
|
-
perform_request(:started)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def on_recordable_request
|
|
41
|
-
perform_request(net_http.started?, :record_interaction)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def on_stubbed_by_vcr_request
|
|
45
|
-
with_exclusive_fakeweb_stub(stubbed_response) do
|
|
46
|
-
# force it to be considered started since it doesn't
|
|
47
|
-
# recurse in this case like the others.
|
|
48
|
-
perform_request(:started)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def on_ignored_request
|
|
53
|
-
perform_request(net_http.started?)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def perform_request(started, record_interaction = false)
|
|
57
|
-
# Net::HTTP calls #request recursively in certain circumstances.
|
|
58
|
-
# We only want to record the request when the request is started, as
|
|
59
|
-
# that is the final time through #request.
|
|
60
|
-
unless started
|
|
61
|
-
@recursing = true
|
|
62
|
-
request.instance_variable_set(:@__vcr_request_handler, recursive_request_handler)
|
|
63
|
-
return net_http.request_without_vcr(request, request_body, &response_block)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
net_http.request_without_vcr(request, request_body) do |response|
|
|
67
|
-
@vcr_response = vcr_response_from(response)
|
|
68
|
-
|
|
69
|
-
if record_interaction
|
|
70
|
-
VCR.record_http_interaction VCR::HTTPInteraction.new(vcr_request, @vcr_response)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
response.extend VCR::Net::HTTPResponse # "unwind" the response
|
|
74
|
-
response_block.call(response) if response_block
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def uri
|
|
79
|
-
@uri ||= ::FakeWeb::Utility.request_uri_as_string(net_http, request)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def response_hash(response)
|
|
83
|
-
(response.headers || {}).merge(
|
|
84
|
-
:body => response.body,
|
|
85
|
-
:status => [response.status.code.to_s, response.status.message]
|
|
86
|
-
)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def with_exclusive_fakeweb_stub(response)
|
|
90
|
-
original_map = ::FakeWeb::Registry.instance.uri_map.dup
|
|
91
|
-
::FakeWeb.clean_registry
|
|
92
|
-
::FakeWeb.register_uri(:any, /.*/, response_hash(response))
|
|
93
|
-
|
|
94
|
-
begin
|
|
95
|
-
return yield
|
|
96
|
-
ensure
|
|
97
|
-
::FakeWeb::Registry.instance.uri_map = original_map
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def request_method
|
|
102
|
-
request.method.downcase.to_sym
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def vcr_request
|
|
106
|
-
@vcr_request ||= VCR::Request.new \
|
|
107
|
-
request_method,
|
|
108
|
-
uri,
|
|
109
|
-
(request_body || request.body),
|
|
110
|
-
request.to_hash
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def vcr_response_from(response)
|
|
114
|
-
VCR::Response.new \
|
|
115
|
-
VCR::ResponseStatus.new(response.code.to_i, response.message),
|
|
116
|
-
response.to_hash,
|
|
117
|
-
response.body,
|
|
118
|
-
response.http_version
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def recursive_request_handler
|
|
122
|
-
@recursive_request_handler ||= RecursiveRequestHandler.new(
|
|
123
|
-
@after_hook_typed_request.type, @stubbed_response, @vcr_request,
|
|
124
|
-
@net_http, @request, @request_body, &@response_block
|
|
125
|
-
)
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
# @private
|
|
130
|
-
class RecursiveRequestHandler < RequestHandler
|
|
131
|
-
attr_reader :stubbed_response
|
|
132
|
-
|
|
133
|
-
def initialize(request_type, stubbed_response, vcr_request, *args, &response_block)
|
|
134
|
-
@request_type, @stubbed_response, @vcr_request =
|
|
135
|
-
request_type, stubbed_response, vcr_request
|
|
136
|
-
super(*args)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def handle
|
|
140
|
-
set_typed_request_for_after_hook(@request_type)
|
|
141
|
-
send "on_#{@request_type}_request"
|
|
142
|
-
ensure
|
|
143
|
-
invoke_after_request_hook(@vcr_response)
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def request_type(*args)
|
|
147
|
-
@request_type
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# @private
|
|
155
|
-
module Net
|
|
156
|
-
# @private
|
|
157
|
-
class HTTP
|
|
158
|
-
unless method_defined?(:request_with_vcr)
|
|
159
|
-
def request_with_vcr(request, *args, &block)
|
|
160
|
-
if VCR.turned_on?
|
|
161
|
-
handler = request.instance_eval do
|
|
162
|
-
remove_instance_variable(:@__vcr_request_handler) if defined?(@__vcr_request_handler)
|
|
163
|
-
end || VCR::LibraryHooks::FakeWeb::RequestHandler.new(self, request, *args, &block)
|
|
164
|
-
|
|
165
|
-
handler.handle
|
|
166
|
-
else
|
|
167
|
-
request_without_vcr(request, *args, &block)
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
alias request_without_vcr request
|
|
172
|
-
alias request request_with_vcr
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
# @private
|
|
178
|
-
module FakeWeb
|
|
179
|
-
class << self
|
|
180
|
-
# ensure HTTP requests are always allowed; VCR takes care of disallowing
|
|
181
|
-
# them at the appropriate times in its hook
|
|
182
|
-
def allow_net_connect_with_vcr?(*args)
|
|
183
|
-
VCR.turned_on? ? true : allow_net_connect_without_vcr?(*args)
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
alias allow_net_connect_without_vcr? allow_net_connect?
|
|
187
|
-
alias allow_net_connect? allow_net_connect_with_vcr?
|
|
188
|
-
end unless respond_to?(:allow_net_connect_with_vcr?)
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
VCR.configuration.after_library_hooks_loaded do
|
|
192
|
-
if defined?(WebMock)
|
|
193
|
-
raise ArgumentError.new("You have configured VCR to hook into both :fakeweb and :webmock. You cannot use both.")
|
|
194
|
-
end
|
|
195
|
-
::Kernel.warn "WARNING: VCR's FakeWeb integration is deprecated and will be removed in VCR 4.0."
|
|
196
|
-
end
|
|
197
|
-
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
VCR::VersionChecker.new('Typhoeus', Typhoeus::VERSION, '0.3.2').check_version!
|
|
2
|
-
|
|
3
|
-
module VCR
|
|
4
|
-
class LibraryHooks
|
|
5
|
-
# @private
|
|
6
|
-
module Typhoeus
|
|
7
|
-
# @private
|
|
8
|
-
class RequestHandler < ::VCR::RequestHandler
|
|
9
|
-
attr_reader :request
|
|
10
|
-
def initialize(request)
|
|
11
|
-
@request = request
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def vcr_request
|
|
15
|
-
@vcr_request ||= VCR::Request.new \
|
|
16
|
-
request.method,
|
|
17
|
-
request.url,
|
|
18
|
-
request.body,
|
|
19
|
-
request.headers
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def externally_stubbed?
|
|
25
|
-
::Typhoeus::Hydra.stubs.detect { |stub| stub.matches?(request) }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def set_typed_request_for_after_hook(*args)
|
|
29
|
-
super
|
|
30
|
-
request.instance_variable_set(:@__typed_vcr_request, @after_hook_typed_request)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def on_unhandled_request
|
|
34
|
-
invoke_after_request_hook(nil)
|
|
35
|
-
super
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def on_stubbed_by_vcr_request
|
|
39
|
-
::Typhoeus::Response.new \
|
|
40
|
-
:http_version => stubbed_response.http_version,
|
|
41
|
-
:code => stubbed_response.status.code,
|
|
42
|
-
:status_message => stubbed_response.status.message,
|
|
43
|
-
:headers_hash => stubbed_response_headers,
|
|
44
|
-
:body => stubbed_response.body
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def stubbed_response_headers
|
|
48
|
-
@stubbed_response_headers ||= {}.tap do |hash|
|
|
49
|
-
stubbed_response.headers.each do |key, values|
|
|
50
|
-
hash[key] = values.size == 1 ? values.first : values
|
|
51
|
-
end if stubbed_response.headers
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# @private
|
|
57
|
-
def self.vcr_response_from(response)
|
|
58
|
-
VCR::Response.new \
|
|
59
|
-
VCR::ResponseStatus.new(response.code, response.status_message),
|
|
60
|
-
response.headers_hash,
|
|
61
|
-
response.body,
|
|
62
|
-
response.http_version
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
::Typhoeus::Hydra.after_request_before_on_complete do |request|
|
|
66
|
-
unless VCR.library_hooks.disabled?(:typhoeus)
|
|
67
|
-
vcr_response = vcr_response_from(request.response)
|
|
68
|
-
typed_vcr_request = request.send(:remove_instance_variable, :@__typed_vcr_request)
|
|
69
|
-
|
|
70
|
-
unless request.response.mock?
|
|
71
|
-
http_interaction = VCR::HTTPInteraction.new(typed_vcr_request, vcr_response)
|
|
72
|
-
VCR.record_http_interaction(http_interaction)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
VCR.configuration.invoke_hook(:after_http_request, typed_vcr_request, vcr_response)
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
::Typhoeus::Hydra.register_stub_finder do |request|
|
|
80
|
-
VCR::LibraryHooks::Typhoeus::RequestHandler.new(request).handle
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# @private
|
|
87
|
-
module Typhoeus
|
|
88
|
-
class << Hydra
|
|
89
|
-
# ensure HTTP requests are always allowed; VCR takes care of disallowing
|
|
90
|
-
# them at the appropriate times in its hook
|
|
91
|
-
def allow_net_connect_with_vcr?(*args)
|
|
92
|
-
VCR.turned_on? ? true : allow_net_connect_without_vcr?
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
alias allow_net_connect_without_vcr? allow_net_connect?
|
|
96
|
-
alias allow_net_connect? allow_net_connect_with_vcr?
|
|
97
|
-
end unless Hydra.respond_to?(:allow_net_connect_with_vcr?)
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
VCR.configuration.after_library_hooks_loaded do
|
|
101
|
-
::Kernel.warn "WARNING: VCR's Typhoeus 0.4 integration is deprecated and will be removed in VCR 3.0."
|
|
102
|
-
end
|
|
103
|
-
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe VCR do
|
|
4
|
-
def recorded_content_for(name)
|
|
5
|
-
VCR.cassette_persisters[:file_system]["#{name}.yml"].to_s
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
context 'when used in a multithreaded environment with an around_http_request', :with_monkey_patches => :excon do
|
|
9
|
-
def preload_yaml_serializer_to_avoid_circular_require_warning_race_condition
|
|
10
|
-
VCR.cassette_serializers[:yaml]
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
before { preload_yaml_serializer_to_avoid_circular_require_warning_race_condition }
|
|
14
|
-
|
|
15
|
-
it 'can use a cassette in an #around_http_request hook', :if => (RUBY_VERSION.to_f > 1.8) do
|
|
16
|
-
VCR.configure do |vcr|
|
|
17
|
-
vcr.around_http_request do |req|
|
|
18
|
-
VCR.use_cassette(req.parsed_uri.path, &req)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
threads = 50.times.map do
|
|
23
|
-
Thread.start do
|
|
24
|
-
Excon.get "http://localhost:#{VCR::SinatraApp.port}/search?q=thread"
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
Excon.get "http://localhost:#{VCR::SinatraApp.port}/foo"
|
|
28
|
-
threads.each(&:join)
|
|
29
|
-
|
|
30
|
-
expect(recorded_content_for("search") +
|
|
31
|
-
recorded_content_for("foo")).to include("query: thread", "FOO!")
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
context 'when used in a multithreaded environment with a cassette', :with_monkey_patches => :excon do
|
|
36
|
-
it 'properly stubs threaded requests' do
|
|
37
|
-
VCR.use_cassette('/foo') do
|
|
38
|
-
threads = 50.times.map do
|
|
39
|
-
Thread.start do
|
|
40
|
-
Excon.get "http://localhost:#{VCR::SinatraApp.port}/foo"
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
threads.each(&:join)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
expect(
|
|
47
|
-
recorded_content_for("foo")).to include("FOO!")
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe VCR do
|
|
4
|
-
context 'when used in a multithreaded environment', :with_monkey_patches => :excon do
|
|
5
|
-
def preload_yaml_serializer_to_avoid_circular_require_warning_race_condition
|
|
6
|
-
VCR.cassette_serializers[:yaml]
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
before { preload_yaml_serializer_to_avoid_circular_require_warning_race_condition }
|
|
10
|
-
|
|
11
|
-
def recorded_content_for(name)
|
|
12
|
-
VCR.cassette_persisters[:file_system]["#{name}.yml"].to_s
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
it 'can use a cassette in an #around_http_request hook', :if => (RUBY_VERSION.to_f > 1.8) do
|
|
16
|
-
VCR.configure do |vcr|
|
|
17
|
-
vcr.around_http_request do |req|
|
|
18
|
-
VCR.use_cassette(req.parsed_uri.path, &req)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
thread = Thread.start do
|
|
23
|
-
Excon.get "http://localhost:#{VCR::SinatraApp.port}/search?q=thread"
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
Excon.get "http://localhost:#{VCR::SinatraApp.port}/foo",
|
|
27
|
-
:response_block => Proc.new { thread.join }
|
|
28
|
-
|
|
29
|
-
expect(recorded_content_for("search") +
|
|
30
|
-
recorded_content_for("foo")).to include("query: thread", "FOO!")
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|