vcr 6.0.0 → 6.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vcr/cassette/erb_renderer.rb +4 -2
- data/lib/vcr/cassette/migrator.rb +5 -1
- data/lib/vcr/cassette/serializers/json.rb +9 -3
- data/lib/vcr/cassette/serializers/psych.rb +7 -1
- data/lib/vcr/cassette/serializers/syck.rb +7 -1
- data/lib/vcr/cassette/serializers/yaml.rb +11 -1
- data/lib/vcr/cassette/serializers.rb +10 -0
- data/lib/vcr/cassette.rb +18 -6
- data/lib/vcr/configuration.rb +1 -0
- data/lib/vcr/library_hooks/typhoeus.rb +94 -111
- data/lib/vcr/library_hooks/webmock.rb +2 -11
- data/lib/vcr/middleware/excon.rb +1 -1
- data/lib/vcr/middleware/faraday.rb +19 -1
- data/lib/vcr/request_ignorer.rb +4 -0
- data/lib/vcr/request_matcher_registry.rb +2 -2
- data/lib/vcr/test_frameworks/cucumber.rb +12 -1
- data/lib/vcr/test_frameworks/rspec.rb +23 -20
- data/lib/vcr/version.rb +2 -2
- data/lib/vcr.rb +19 -1
- metadata +16 -17
- data/lib/vcr/library_hooks/typhoeus_0.4.rb +0 -103
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 902881c25780fa44253365c8f5fd0bb260510d7f754287d74a70275abc2dabce
|
4
|
+
data.tar.gz: fe52ddaa831a711b7415c350205a2662e833de2c4a6d58b8b6539170645bd218
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f79ffb02f15e691a1266c3421043a5ee95f3bd35715687137f139b291c490ee87a93351e0526faa0f29c73deba80ba41740f87d0fc9d50793a6b6d4101c7b116
|
7
|
+
data.tar.gz: 3e9276ffc9e2a2ae07f4a11054dcb484a324dc18e28a4badaa06df7454db36cfdbfbf38b95aec40c01a15a40cde56fb6cd9868780e50994fc2f554caf86e209a
|
@@ -32,7 +32,7 @@ module VCR
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def erb_variables
|
35
|
-
@erb if @erb.is_a?(Hash)
|
35
|
+
@erb if @erb.is_a?(Hash) && !@erb.empty?
|
36
36
|
end
|
37
37
|
|
38
38
|
def template
|
@@ -40,7 +40,9 @@ module VCR
|
|
40
40
|
end
|
41
41
|
|
42
42
|
@@struct_cache = Hash.new do |hash, attributes|
|
43
|
-
|
43
|
+
attributes = attributes.map(&:to_sym)
|
44
|
+
hash[attributes] = Struct.new(*attributes) unless hash.key?(attributes)
|
45
|
+
hash[attributes]
|
44
46
|
end
|
45
47
|
|
46
48
|
def variables_object
|
@@ -50,7 +50,11 @@ module VCR
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def load_yaml(cassette)
|
53
|
-
::YAML.
|
53
|
+
if ::YAML.respond_to?(:unsafe_load_file)
|
54
|
+
::YAML.unsafe_load_file(cassette)
|
55
|
+
else
|
56
|
+
::YAML.load_file(cassette)
|
57
|
+
end
|
54
58
|
rescue *@yaml_load_errors
|
55
59
|
return nil
|
56
60
|
end
|
@@ -3,7 +3,7 @@ require 'json'
|
|
3
3
|
module VCR
|
4
4
|
class Cassette
|
5
5
|
class Serializers
|
6
|
-
# The JSON serializer.
|
6
|
+
# The JSON serializer.
|
7
7
|
#
|
8
8
|
# @see Psych
|
9
9
|
# @see Syck
|
@@ -11,11 +11,15 @@ module VCR
|
|
11
11
|
module JSON
|
12
12
|
extend self
|
13
13
|
extend EncodingErrorHandling
|
14
|
+
extend SyntaxErrorHandling
|
14
15
|
|
15
16
|
# @private
|
16
17
|
ENCODING_ERRORS = [ArgumentError]
|
17
18
|
ENCODING_ERRORS << ::JSON::GeneratorError
|
18
19
|
|
20
|
+
# @private
|
21
|
+
SYNTAX_ERRORS = [::JSON::ParserError]
|
22
|
+
|
19
23
|
# The file extension to use for this serializer.
|
20
24
|
#
|
21
25
|
# @return [String] "json"
|
@@ -29,7 +33,7 @@ module VCR
|
|
29
33
|
# @return [String] the JSON string
|
30
34
|
def serialize(hash)
|
31
35
|
handle_encoding_errors do
|
32
|
-
::JSON.
|
36
|
+
::JSON.pretty_generate(hash)
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
@@ -39,7 +43,9 @@ module VCR
|
|
39
43
|
# @return [Hash] the deserialized object
|
40
44
|
def deserialize(string)
|
41
45
|
handle_encoding_errors do
|
42
|
-
|
46
|
+
handle_syntax_errors do
|
47
|
+
::JSON.parse(string)
|
48
|
+
end
|
43
49
|
end
|
44
50
|
end
|
45
51
|
end
|
@@ -11,10 +11,14 @@ module VCR
|
|
11
11
|
module Psych
|
12
12
|
extend self
|
13
13
|
extend EncodingErrorHandling
|
14
|
+
extend SyntaxErrorHandling
|
14
15
|
|
15
16
|
# @private
|
16
17
|
ENCODING_ERRORS = [ArgumentError]
|
17
18
|
|
19
|
+
# @private
|
20
|
+
SYNTAX_ERRORS = [::Psych::SyntaxError]
|
21
|
+
|
18
22
|
# The file extension to use for this serializer.
|
19
23
|
#
|
20
24
|
# @return [String] "yml"
|
@@ -40,7 +44,9 @@ module VCR
|
|
40
44
|
# @return [Hash] the deserialized object
|
41
45
|
def deserialize(string)
|
42
46
|
handle_encoding_errors do
|
43
|
-
|
47
|
+
handle_syntax_errors do
|
48
|
+
::Psych.load(string)
|
49
|
+
end
|
44
50
|
end
|
45
51
|
end
|
46
52
|
end
|
@@ -11,10 +11,14 @@ module VCR
|
|
11
11
|
module Syck
|
12
12
|
extend self
|
13
13
|
extend EncodingErrorHandling
|
14
|
+
extend SyntaxErrorHandling
|
14
15
|
|
15
16
|
# @private
|
16
17
|
ENCODING_ERRORS = [ArgumentError]
|
17
18
|
|
19
|
+
# @private
|
20
|
+
SYNTAX_ERRORS = [::Psych::SyntaxError]
|
21
|
+
|
18
22
|
# The file extension to use for this serializer.
|
19
23
|
#
|
20
24
|
# @return [String] "yml"
|
@@ -38,7 +42,9 @@ module VCR
|
|
38
42
|
# @return [Hash] the deserialized object
|
39
43
|
def deserialize(string)
|
40
44
|
handle_encoding_errors do
|
41
|
-
|
45
|
+
handle_syntax_errors do
|
46
|
+
using_syck { ::YAML.load(string) }
|
47
|
+
end
|
42
48
|
end
|
43
49
|
end
|
44
50
|
|
@@ -13,10 +13,14 @@ module VCR
|
|
13
13
|
module YAML
|
14
14
|
extend self
|
15
15
|
extend EncodingErrorHandling
|
16
|
+
extend SyntaxErrorHandling
|
16
17
|
|
17
18
|
# @private
|
18
19
|
ENCODING_ERRORS = [ArgumentError]
|
19
20
|
|
21
|
+
# @private
|
22
|
+
SYNTAX_ERRORS = [::Psych::SyntaxError]
|
23
|
+
|
20
24
|
# The file extension to use for this serializer.
|
21
25
|
#
|
22
26
|
# @return [String] "yml"
|
@@ -42,7 +46,13 @@ module VCR
|
|
42
46
|
# @return [Hash] the deserialized object
|
43
47
|
def deserialize(string)
|
44
48
|
handle_encoding_errors do
|
45
|
-
|
49
|
+
handle_syntax_errors do
|
50
|
+
if ::YAML.respond_to?(:unsafe_load)
|
51
|
+
::YAML.unsafe_load(string)
|
52
|
+
else
|
53
|
+
::YAML.load(string)
|
54
|
+
end
|
55
|
+
end
|
46
56
|
end
|
47
57
|
end
|
48
58
|
end
|
@@ -54,6 +54,16 @@ module VCR
|
|
54
54
|
raise
|
55
55
|
end
|
56
56
|
end
|
57
|
+
|
58
|
+
# @private
|
59
|
+
module SyntaxErrorHandling
|
60
|
+
def handle_syntax_errors
|
61
|
+
yield
|
62
|
+
rescue *self::SYNTAX_ERRORS => e
|
63
|
+
e.message << "\nNote: This is a VCR cassette. If it is using ERB, you may have forgotten to pass the `:erb` option to `use_cassette`."
|
64
|
+
raise
|
65
|
+
end
|
66
|
+
end
|
57
67
|
end
|
58
68
|
end
|
59
69
|
|
data/lib/vcr/cassette.rb
CHANGED
@@ -46,6 +46,9 @@ module VCR
|
|
46
46
|
# @return [Boolean, nil] Should outdated interactions be recorded back to file
|
47
47
|
attr_reader :clean_outdated_http_interactions
|
48
48
|
|
49
|
+
# @return [Boolean] Should unused requests be dropped from the cassette?
|
50
|
+
attr_reader :drop_unused_requests
|
51
|
+
|
49
52
|
# @return [Array<Symbol>] If set, {VCR::Configuration#before_record} and
|
50
53
|
# {VCR::Configuration#before_playback} hooks with a corresponding tag will apply.
|
51
54
|
attr_reader :tags
|
@@ -176,7 +179,8 @@ module VCR
|
|
176
179
|
:record, :record_on_error, :erb, :match_requests_on, :re_record_interval, :tag, :tags,
|
177
180
|
:update_content_length_header, :allow_playback_repeats, :allow_unused_http_interactions,
|
178
181
|
:exclusive, :serialize_with, :preserve_exact_body_bytes, :decode_compressed_response,
|
179
|
-
:recompress_response, :persist_with, :persister_options, :clean_outdated_http_interactions
|
182
|
+
:recompress_response, :persist_with, :persister_options, :clean_outdated_http_interactions,
|
183
|
+
:drop_unused_requests
|
180
184
|
]
|
181
185
|
|
182
186
|
if invalid_options.size > 0
|
@@ -186,16 +190,15 @@ module VCR
|
|
186
190
|
|
187
191
|
def extract_options
|
188
192
|
[:record_on_error, :erb, :match_requests_on, :re_record_interval, :clean_outdated_http_interactions,
|
189
|
-
:allow_playback_repeats, :allow_unused_http_interactions, :exclusive].each do |name|
|
193
|
+
:allow_playback_repeats, :allow_unused_http_interactions, :exclusive, :drop_unused_requests].each do |name|
|
190
194
|
instance_variable_set("@#{name}", @options[name])
|
191
195
|
end
|
192
196
|
|
193
197
|
assign_tags
|
194
198
|
|
195
|
-
@record_mode = @options[:record]
|
196
199
|
@serializer = VCR.cassette_serializers[@options[:serialize_with]]
|
197
200
|
@persister = VCR.cassette_persisters[@options[:persist_with]]
|
198
|
-
@record_mode = :all
|
201
|
+
@record_mode = should_re_record?(@options[:record]) ? :all : @options[:record]
|
199
202
|
@parent_list = @exclusive ? HTTPInteractionList::NullList : VCR.http_interactions
|
200
203
|
end
|
201
204
|
|
@@ -231,9 +234,10 @@ module VCR
|
|
231
234
|
end
|
232
235
|
end
|
233
236
|
|
234
|
-
def should_re_record?
|
237
|
+
def should_re_record?(record_mode)
|
235
238
|
return false unless @re_record_interval
|
236
239
|
return false unless originally_recorded_at
|
240
|
+
return false if record_mode == :none
|
237
241
|
|
238
242
|
now = Time.now
|
239
243
|
|
@@ -259,6 +263,10 @@ module VCR
|
|
259
263
|
record_mode == :all
|
260
264
|
end
|
261
265
|
|
266
|
+
def should_remove_unused_interactions?
|
267
|
+
@drop_unused_requests
|
268
|
+
end
|
269
|
+
|
262
270
|
def should_assert_no_unused_interactions?
|
263
271
|
!(@allow_unused_http_interactions || $!)
|
264
272
|
end
|
@@ -277,7 +285,11 @@ module VCR
|
|
277
285
|
end
|
278
286
|
end
|
279
287
|
|
280
|
-
|
288
|
+
if should_remove_unused_interactions?
|
289
|
+
new_recorded_interactions
|
290
|
+
else
|
291
|
+
up_to_date_interactions(old_interactions) + new_recorded_interactions
|
292
|
+
end
|
281
293
|
end
|
282
294
|
|
283
295
|
def up_to_date_interactions(interactions)
|
data/lib/vcr/configuration.rb
CHANGED
@@ -495,6 +495,7 @@ module VCR
|
|
495
495
|
:record_on_error => true,
|
496
496
|
:match_requests_on => RequestMatcherRegistry::DEFAULT_MATCHERS,
|
497
497
|
:allow_unused_http_interactions => true,
|
498
|
+
:drop_unused_requests => false,
|
498
499
|
:serialize_with => :yaml,
|
499
500
|
:persist_with => :file_system,
|
500
501
|
:persister_options => {}
|
@@ -2,137 +2,121 @@ require 'vcr/util/version_checker'
|
|
2
2
|
require 'vcr/request_handler'
|
3
3
|
require 'typhoeus'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
module VCR
|
11
|
-
class LibraryHooks
|
5
|
+
module VCR
|
6
|
+
class LibraryHooks
|
7
|
+
# @private
|
8
|
+
module Typhoeus
|
12
9
|
# @private
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
request.block_connection = false if VCR.turned_on?
|
20
|
-
end
|
21
|
-
|
22
|
-
def vcr_request
|
23
|
-
@vcr_request ||= VCR::Request.new \
|
24
|
-
request.options.fetch(:method, :get),
|
25
|
-
request.url,
|
26
|
-
request_body,
|
27
|
-
request.options.fetch(:headers, {})
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
10
|
+
class RequestHandler < ::VCR::RequestHandler
|
11
|
+
attr_reader :request
|
12
|
+
def initialize(request)
|
13
|
+
@request = request
|
14
|
+
request.block_connection = false if VCR.turned_on?
|
15
|
+
end
|
31
16
|
|
32
|
-
|
33
|
-
|
34
|
-
|
17
|
+
def vcr_request
|
18
|
+
@vcr_request ||= VCR::Request.new \
|
19
|
+
request.options.fetch(:method, :get),
|
20
|
+
request.url,
|
21
|
+
request.encoded_body,
|
22
|
+
request.options.fetch(:headers, {})
|
23
|
+
end
|
35
24
|
|
36
|
-
|
37
|
-
super
|
38
|
-
request.instance_variable_set(:@__typed_vcr_request, @after_hook_typed_request)
|
39
|
-
end
|
25
|
+
private
|
40
26
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
27
|
+
def externally_stubbed?
|
28
|
+
::Typhoeus::Expectation.find_by(request)
|
29
|
+
end
|
45
30
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
:status_message => stubbed_response.status.message,
|
51
|
-
:headers => stubbed_response_headers,
|
52
|
-
:body => stubbed_response.body,
|
53
|
-
:effective_url => stubbed_response.adapter_metadata.fetch('effective_url', request.url),
|
54
|
-
:mock => true
|
55
|
-
|
56
|
-
first_header_line = "HTTP/#{stubbed_response.http_version} #{response.code} #{response.status_message}\r\n"
|
57
|
-
response.instance_variable_set(:@first_header_line, first_header_line)
|
58
|
-
response.instance_variable_get(:@options)[:response_headers] =
|
59
|
-
first_header_line + response.headers.map { |k,v| "#{k}: #{v}"}.join("\r\n")
|
60
|
-
|
61
|
-
response
|
62
|
-
end
|
31
|
+
def set_typed_request_for_after_hook(*args)
|
32
|
+
super
|
33
|
+
request.instance_variable_set(:@__typed_vcr_request, @after_hook_typed_request)
|
34
|
+
end
|
63
35
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end if stubbed_response.headers
|
69
|
-
end
|
70
|
-
end
|
36
|
+
def on_unhandled_request
|
37
|
+
invoke_after_request_hook(nil)
|
38
|
+
super
|
39
|
+
end
|
71
40
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
41
|
+
def on_stubbed_by_vcr_request
|
42
|
+
response = ::Typhoeus::Response.new \
|
43
|
+
:http_version => stubbed_response.http_version,
|
44
|
+
:code => stubbed_response.status.code,
|
45
|
+
:status_message => stubbed_response.status.message,
|
46
|
+
:headers => stubbed_response_headers,
|
47
|
+
:body => stubbed_response.body,
|
48
|
+
:effective_url => stubbed_response.adapter_metadata.fetch('effective_url', request.url),
|
49
|
+
:mock => true
|
50
|
+
|
51
|
+
first_header_line = "HTTP/#{stubbed_response.http_version} #{response.code} #{response.status_message}\r\n"
|
52
|
+
response.instance_variable_set(:@first_header_line, first_header_line)
|
53
|
+
response.instance_variable_get(:@options)[:response_headers] =
|
54
|
+
first_header_line + response.headers.map { |k,v| "#{k}: #{v}"}.join("\r\n")
|
55
|
+
|
56
|
+
response
|
81
57
|
end
|
82
58
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
response.headers,
|
89
|
-
response.body,
|
90
|
-
response.http_version,
|
91
|
-
{ "effective_url" => response.effective_url }
|
59
|
+
def stubbed_response_headers
|
60
|
+
@stubbed_response_headers ||= {}.tap do |hash|
|
61
|
+
stubbed_response.headers.each do |key, values|
|
62
|
+
hash[key] = values.size == 1 ? values.first : values
|
63
|
+
end if stubbed_response.headers
|
92
64
|
end
|
65
|
+
end
|
66
|
+
end
|
93
67
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
68
|
+
# @private
|
69
|
+
class << self
|
70
|
+
def vcr_response_from(response)
|
71
|
+
VCR::Response.new \
|
72
|
+
VCR::ResponseStatus.new(response.code, response.status_message),
|
73
|
+
response.headers,
|
74
|
+
response.body,
|
75
|
+
response.http_version,
|
76
|
+
{ "effective_url" => response.effective_url }
|
77
|
+
end
|
103
78
|
|
104
|
-
|
105
|
-
|
106
|
-
|
79
|
+
def collect_chunks(request)
|
80
|
+
chunks = ''
|
81
|
+
request.on_body.unshift(
|
82
|
+
Proc.new do |body, response|
|
83
|
+
chunks += body
|
84
|
+
request.instance_variable_set(:@chunked_body, chunks)
|
85
|
+
end
|
86
|
+
)
|
107
87
|
end
|
108
88
|
|
109
|
-
|
110
|
-
|
89
|
+
def restore_body_from_chunks(response, request)
|
90
|
+
response.options[:response_body] = request.instance_variable_get(:@chunked_body)
|
91
|
+
end
|
92
|
+
end
|
111
93
|
|
112
|
-
|
94
|
+
::Typhoeus.on_complete do |response|
|
95
|
+
request = response.request
|
113
96
|
|
114
|
-
|
115
|
-
vcr_response = vcr_response_from(response)
|
116
|
-
typed_vcr_request = request.send(:remove_instance_variable, :@__typed_vcr_request)
|
97
|
+
restore_body_from_chunks(response, request) if request.streaming?
|
117
98
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
end
|
99
|
+
unless VCR.library_hooks.disabled?(:typhoeus)
|
100
|
+
vcr_response = vcr_response_from(response)
|
101
|
+
typed_vcr_request = request.send(:remove_instance_variable, :@__typed_vcr_request)
|
122
102
|
|
123
|
-
|
103
|
+
unless request.response.mock
|
104
|
+
http_interaction = VCR::HTTPInteraction.new(typed_vcr_request, vcr_response)
|
105
|
+
VCR.record_http_interaction(http_interaction)
|
124
106
|
end
|
107
|
+
|
108
|
+
VCR.configuration.invoke_hook(:after_http_request, typed_vcr_request, vcr_response)
|
125
109
|
end
|
110
|
+
end
|
126
111
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
end
|
112
|
+
::Typhoeus.before do |request|
|
113
|
+
collect_chunks(request) if request.streaming?
|
114
|
+
if response = VCR::LibraryHooks::Typhoeus::RequestHandler.new(request).handle
|
115
|
+
request.on_headers.each { |cb| cb.call(response) }
|
116
|
+
request.on_body.each { |cb| cb.call(response.body, response) }
|
117
|
+
request.finish(response)
|
118
|
+
else
|
119
|
+
true
|
136
120
|
end
|
137
121
|
end
|
138
122
|
end
|
@@ -146,4 +130,3 @@ VCR.configuration.after_library_hooks_loaded do
|
|
146
130
|
WebMock::HttpLibAdapters::TyphoeusAdapter.disable!
|
147
131
|
end
|
148
132
|
end
|
149
|
-
|
@@ -12,8 +12,6 @@ module VCR
|
|
12
12
|
module WebMock
|
13
13
|
extend self
|
14
14
|
|
15
|
-
@global_hook_disabled_requests = {}
|
16
|
-
|
17
15
|
def with_global_hook_disabled(request)
|
18
16
|
global_hook_disabled_requests << request
|
19
17
|
|
@@ -25,19 +23,12 @@ module VCR
|
|
25
23
|
end
|
26
24
|
|
27
25
|
def global_hook_disabled?(request)
|
28
|
-
requests =
|
26
|
+
requests = Thread.current[:_vcr_webmock_disabled_requests]
|
29
27
|
requests && requests.include?(request)
|
30
28
|
end
|
31
29
|
|
32
30
|
def global_hook_disabled_requests
|
33
|
-
|
34
|
-
return requests if requests
|
35
|
-
|
36
|
-
ObjectSpace.define_finalizer(Thread.current, lambda {
|
37
|
-
@global_hook_disabled_requests.delete(Thread.current.object_id)
|
38
|
-
})
|
39
|
-
|
40
|
-
@global_hook_disabled_requests[Thread.current.object_id] = []
|
31
|
+
Thread.current[:_vcr_webmock_disabled_requests] ||= []
|
41
32
|
end
|
42
33
|
|
43
34
|
# @private
|
data/lib/vcr/middleware/excon.rb
CHANGED
@@ -45,9 +45,11 @@ module VCR
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def handle
|
48
|
-
# Faraday must be
|
48
|
+
# Faraday must be exclusive here in case another library hook is being used.
|
49
49
|
# We don't want double recording/double playback.
|
50
50
|
VCR.library_hooks.exclusive_hook = :faraday
|
51
|
+
collect_chunks if env.request.stream_response?
|
52
|
+
|
51
53
|
super
|
52
54
|
ensure
|
53
55
|
response = defined?(@vcr_response) ? @vcr_response : nil
|
@@ -103,6 +105,7 @@ module VCR
|
|
103
105
|
@vcr_response = stubbed_response
|
104
106
|
|
105
107
|
faraday_response = ::Faraday::Response.new
|
108
|
+
env.request.on_data.call(stubbed_response.body, stubbed_response.body.length) if env.request.stream_response?
|
106
109
|
faraday_response.finish(env)
|
107
110
|
env[:response] = faraday_response
|
108
111
|
end
|
@@ -111,6 +114,7 @@ module VCR
|
|
111
114
|
@has_on_complete_hook = true
|
112
115
|
response = app.call(env)
|
113
116
|
response.on_complete do
|
117
|
+
restore_body_from_chunks(env.request) if env.request.stream_response?
|
114
118
|
@vcr_response = response_for(response)
|
115
119
|
VCR.record_http_interaction(VCR::HTTPInteraction.new(vcr_request, @vcr_response))
|
116
120
|
invoke_after_request_hook(@vcr_response) if delay_finishing?
|
@@ -121,6 +125,20 @@ module VCR
|
|
121
125
|
super
|
122
126
|
VCR.library_hooks.exclusive_hook = nil
|
123
127
|
end
|
128
|
+
|
129
|
+
def collect_chunks
|
130
|
+
caller_on_data = env.request.on_data
|
131
|
+
chunks = ''
|
132
|
+
env.request.on_data = Proc.new do |chunk, overall_received_bytes|
|
133
|
+
chunks += chunk
|
134
|
+
env.request.instance_variable_set(:@chunked_body, chunks)
|
135
|
+
caller_on_data.call(chunk, overall_received_bytes)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def restore_body_from_chunks(request)
|
140
|
+
env[:body] = request.instance_variable_get(:@chunked_body)
|
141
|
+
end
|
124
142
|
end
|
125
143
|
end
|
126
144
|
end
|
data/lib/vcr/request_ignorer.rb
CHANGED
@@ -110,12 +110,12 @@ module VCR
|
|
110
110
|
|
111
111
|
def register_built_ins
|
112
112
|
register(:method) { |r1, r2| r1.method == r2.method }
|
113
|
-
register(:uri) { |r1, r2| r1.
|
113
|
+
register(:uri) { |r1, r2| r1.parsed_uri == r2.parsed_uri }
|
114
114
|
register(:body) { |r1, r2| r1.body == r2.body }
|
115
115
|
register(:headers) { |r1, r2| r1.headers == r2.headers }
|
116
116
|
|
117
117
|
register(:host) do |r1, r2|
|
118
|
-
r1.parsed_uri.host == r2.parsed_uri.host
|
118
|
+
r1.parsed_uri.host.chomp('.') == r2.parsed_uri.host.chomp('.')
|
119
119
|
end
|
120
120
|
register(:path) do |r1, r2|
|
121
121
|
r1.parsed_uri.path == r2.parsed_uri.path
|
@@ -47,10 +47,21 @@ module VCR
|
|
47
47
|
scenario.scenario_outline.name,
|
48
48
|
scenario.name.split("\n").first
|
49
49
|
].join("/")
|
50
|
-
|
50
|
+
elsif scenario.respond_to?(:feature)
|
51
51
|
[ scenario.feature.name.split("\n").first,
|
52
52
|
scenario.name.split("\n").first
|
53
53
|
].join("/")
|
54
|
+
elsif scenario.location.lines.min == scenario.location.lines.max
|
55
|
+
# test case from a regular scenario in cucumber version 4
|
56
|
+
[ scenario.location.file.split("/").last.split(".").first,
|
57
|
+
scenario.name.split("\n").first
|
58
|
+
].join("/")
|
59
|
+
else
|
60
|
+
# test case from a scenario with examples ("scenario outline") in cucumber version 4
|
61
|
+
[ scenario.location.file.split("/").last.split(".").first,
|
62
|
+
scenario.name.split("\n").first,
|
63
|
+
"Example at line #{scenario.location.lines.max}"
|
64
|
+
].join("/")
|
54
65
|
end
|
55
66
|
else
|
56
67
|
"cucumber_tags/#{tag_name.gsub(/\A@/, '')}"
|
@@ -5,27 +5,30 @@ module VCR
|
|
5
5
|
module Metadata
|
6
6
|
extend self
|
7
7
|
|
8
|
+
def vcr_cassette_name_for(metadata)
|
9
|
+
description =
|
10
|
+
if metadata[:description].empty?
|
11
|
+
# we have an "it { is_expected.to be something }" block
|
12
|
+
metadata[:scoped_id]
|
13
|
+
else
|
14
|
+
metadata[:description]
|
15
|
+
end
|
16
|
+
example_group =
|
17
|
+
if metadata.key?(:example_group)
|
18
|
+
metadata[:example_group]
|
19
|
+
else
|
20
|
+
metadata[:parent_example_group]
|
21
|
+
end
|
22
|
+
|
23
|
+
if example_group
|
24
|
+
[vcr_cassette_name_for(example_group), description].join('/')
|
25
|
+
else
|
26
|
+
description
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
8
30
|
def configure!
|
9
31
|
::RSpec.configure do |config|
|
10
|
-
vcr_cassette_name_for = lambda do |metadata|
|
11
|
-
description = if metadata[:description].empty?
|
12
|
-
# we have an "it { is_expected.to be something }" block
|
13
|
-
metadata[:scoped_id]
|
14
|
-
else
|
15
|
-
metadata[:description]
|
16
|
-
end
|
17
|
-
example_group = if metadata.key?(:example_group)
|
18
|
-
metadata[:example_group]
|
19
|
-
else
|
20
|
-
metadata[:parent_example_group]
|
21
|
-
end
|
22
|
-
|
23
|
-
if example_group
|
24
|
-
[vcr_cassette_name_for[example_group], description].join('/')
|
25
|
-
else
|
26
|
-
description
|
27
|
-
end
|
28
|
-
end
|
29
32
|
|
30
33
|
when_tagged_with_vcr = { :vcr => lambda { |v| !!v } }
|
31
34
|
|
@@ -45,7 +48,7 @@ module VCR
|
|
45
48
|
end
|
46
49
|
|
47
50
|
cassette_name ||= options.delete(:cassette_name) ||
|
48
|
-
|
51
|
+
VCR::RSpec::Metadata.vcr_cassette_name_for(example.metadata)
|
49
52
|
VCR.insert_cassette(cassette_name, options)
|
50
53
|
end
|
51
54
|
|
data/lib/vcr/version.rb
CHANGED
@@ -10,7 +10,7 @@ module VCR
|
|
10
10
|
# * `parts` [Array<Integer>] List of the version parts.
|
11
11
|
def version
|
12
12
|
@version ||= begin
|
13
|
-
string = '6.
|
13
|
+
string = +'6.2.0'
|
14
14
|
|
15
15
|
def string.parts
|
16
16
|
split('.').map { |p| p.to_i }
|
@@ -28,7 +28,7 @@ module VCR
|
|
28
28
|
parts[2]
|
29
29
|
end
|
30
30
|
|
31
|
-
string
|
31
|
+
string.freeze
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
data/lib/vcr.rb
CHANGED
@@ -52,7 +52,7 @@ module VCR
|
|
52
52
|
# Inserts the named cassette using the given cassette options.
|
53
53
|
# New HTTP interactions, if allowed by the cassette's `:record` option, will
|
54
54
|
# be recorded to the cassette. The cassette's existing HTTP interactions
|
55
|
-
# will be used to stub requests, unless prevented by the
|
55
|
+
# will be used to stub requests, unless prevented by the cassette's
|
56
56
|
# `:record` option.
|
57
57
|
#
|
58
58
|
# @example
|
@@ -266,6 +266,7 @@ module VCR
|
|
266
266
|
# @see #turn_off!
|
267
267
|
# @see #turn_on!
|
268
268
|
# @see #turned_on?
|
269
|
+
# @see #turned_on
|
269
270
|
def turned_off(options = {})
|
270
271
|
turn_off!(options)
|
271
272
|
|
@@ -301,11 +302,28 @@ module VCR
|
|
301
302
|
set_context_value(:turned_off, true)
|
302
303
|
end
|
303
304
|
|
305
|
+
# Turns on VCR, for the duration of a block.
|
306
|
+
# @param (see #turn_off!)
|
307
|
+
# @return [void]
|
308
|
+
# @see #turn_off!
|
309
|
+
# @see #turned_off
|
310
|
+
# @see #turned_on?
|
311
|
+
def turned_on(options = {})
|
312
|
+
turn_on!
|
313
|
+
|
314
|
+
begin
|
315
|
+
yield
|
316
|
+
ensure
|
317
|
+
turn_off!(options)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
304
321
|
# Turns on VCR, if it has previously been turned off.
|
305
322
|
# @return [void]
|
306
323
|
# @see #turn_off!
|
307
324
|
# @see #turned_off
|
308
325
|
# @see #turned_on?
|
326
|
+
# @see #turned_on
|
309
327
|
def turn_on!
|
310
328
|
set_context_value(:turned_off, false)
|
311
329
|
end
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vcr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Myron Marston
|
8
8
|
- Kurtis Rainbolt-Greene
|
9
9
|
- Olle Jonsson
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2023-06-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -46,28 +46,28 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 3.
|
49
|
+
version: 3.4.4
|
50
50
|
type: :development
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
54
|
- - "~>"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: 3.
|
56
|
+
version: 3.4.4
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
58
|
name: rake
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
|
-
- - "
|
61
|
+
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version:
|
63
|
+
version: 12.3.3
|
64
64
|
type: :development
|
65
65
|
prerelease: false
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
|
-
- - "
|
68
|
+
- - ">="
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version:
|
70
|
+
version: 12.3.3
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: pry
|
73
73
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,14 +178,14 @@ dependencies:
|
|
178
178
|
requirements:
|
179
179
|
- - "~>"
|
180
180
|
- !ruby/object:Gem::Version
|
181
|
-
version: '
|
181
|
+
version: '7.0'
|
182
182
|
type: :development
|
183
183
|
prerelease: false
|
184
184
|
version_requirements: !ruby/object:Gem::Requirement
|
185
185
|
requirements:
|
186
186
|
- - "~>"
|
187
187
|
- !ruby/object:Gem::Version
|
188
|
-
version: '
|
188
|
+
version: '7.0'
|
189
189
|
- !ruby/object:Gem::Dependency
|
190
190
|
name: aruba
|
191
191
|
requirement: !ruby/object:Gem::Requirement
|
@@ -346,7 +346,6 @@ files:
|
|
346
346
|
- lib/vcr/library_hooks/excon.rb
|
347
347
|
- lib/vcr/library_hooks/faraday.rb
|
348
348
|
- lib/vcr/library_hooks/typhoeus.rb
|
349
|
-
- lib/vcr/library_hooks/typhoeus_0.4.rb
|
350
349
|
- lib/vcr/library_hooks/webmock.rb
|
351
350
|
- lib/vcr/linked_cassette.rb
|
352
351
|
- lib/vcr/middleware/excon.rb
|
@@ -366,12 +365,12 @@ files:
|
|
366
365
|
- lib/vcr/util/variable_args_block_caller.rb
|
367
366
|
- lib/vcr/util/version_checker.rb
|
368
367
|
- lib/vcr/version.rb
|
369
|
-
homepage: https://
|
368
|
+
homepage: https://benoittgt.github.io/vcr
|
370
369
|
licenses:
|
371
370
|
- Hippocratic-2.1
|
372
371
|
- MIT
|
373
372
|
metadata: {}
|
374
|
-
post_install_message:
|
373
|
+
post_install_message:
|
375
374
|
rdoc_options: []
|
376
375
|
require_paths:
|
377
376
|
- lib
|
@@ -379,15 +378,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
379
378
|
requirements:
|
380
379
|
- - ">="
|
381
380
|
- !ruby/object:Gem::Version
|
382
|
-
version: '2.
|
381
|
+
version: '2.7'
|
383
382
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
384
383
|
requirements:
|
385
384
|
- - ">="
|
386
385
|
- !ruby/object:Gem::Version
|
387
386
|
version: '0'
|
388
387
|
requirements: []
|
389
|
-
rubygems_version: 3.
|
390
|
-
signing_key:
|
388
|
+
rubygems_version: 3.4.14
|
389
|
+
signing_key:
|
391
390
|
specification_version: 4
|
392
391
|
summary: Record your test suite's HTTP interactions and replay them during future
|
393
392
|
test runs for fast, deterministic, accurate tests.
|
@@ -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
|
-
|