vcr 4.0.0 → 6.0.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/http_interaction_list.rb +14 -9
- data/lib/vcr/cassette/migrator.rb +0 -5
- 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 +7 -7
- data/lib/vcr/cassette/serializers/psych.rb +3 -1
- data/lib/vcr/cassette/serializers/yaml.rb +3 -1
- data/lib/vcr/cassette.rb +38 -11
- data/lib/vcr/configuration.rb +17 -3
- data/lib/vcr/errors.rb +1 -12
- data/lib/vcr/library_hooks/excon.rb +8 -0
- data/lib/vcr/linked_cassette.rb +4 -4
- data/lib/vcr/middleware/faraday.rb +5 -0
- data/lib/vcr/request_ignorer.rb +4 -1
- data/lib/vcr/request_matcher_registry.rb +1 -1
- data/lib/vcr/structs.rb +47 -31
- data/lib/vcr/test_frameworks/cucumber.rb +4 -4
- data/lib/vcr/test_frameworks/rspec.rb +12 -3
- data/lib/vcr/util/internet_connection.rb +15 -21
- data/lib/vcr/version.rb +1 -1
- data/lib/vcr.rb +25 -10
- metadata +41 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 79ff7c5f67afb190b63450e117a7dbda6709340fbab8c17680c36b2bb5a8a6f6
|
4
|
+
data.tar.gz: a6a17620c6c63d9a596a39e2700f3f1becddb26bfa63f862e42ef0dfabb783d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f43f626bae24850a8b5f912203dba5ee7e38ef39ecb3d325382ca2cbfb24ff789c3e630edd628588fdd59b0a8b10919bedd820675a039b5d619f1c779dc186b
|
7
|
+
data.tar.gz: ffc8534bbab227c6f8f4636306644c1c28d1ac8c2d29d47551d1b84c04cd5c37979acfb44803b18c54ee558e961d92826a38e6a75b93d8002af6adde5f2e7d05
|
@@ -22,21 +22,26 @@ module VCR
|
|
22
22
|
@parent_list = parent_list
|
23
23
|
@used_interactions = []
|
24
24
|
@log_prefix = log_prefix
|
25
|
+
@mutex = Mutex.new
|
25
26
|
|
26
27
|
interaction_summaries = interactions.map { |i| "#{request_summary(i.request)} => #{response_summary(i.response)}" }
|
27
28
|
log "Initialized HTTPInteractionList with request matchers #{request_matchers.inspect} and #{interactions.size} interaction(s): { #{interaction_summaries.join(', ')} }", 1
|
28
29
|
end
|
29
30
|
|
30
31
|
def response_for(request)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
# Without this mutex, under threaded access, the wrong response may be removed
|
33
|
+
# out of the (remaining) interactions list (and other problems).
|
34
|
+
@mutex.synchronize do
|
35
|
+
if index = matching_interaction_index_for(request)
|
36
|
+
interaction = @interactions.delete_at(index)
|
37
|
+
@used_interactions.unshift interaction
|
38
|
+
log "Found matching interaction for #{request_summary(request)} at index #{index}: #{response_summary(interaction.response)}", 1
|
39
|
+
interaction.response
|
40
|
+
elsif interaction = matching_used_interaction_for(request)
|
41
|
+
interaction.response
|
42
|
+
else
|
43
|
+
@parent_list.response_for(request)
|
44
|
+
end
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
@@ -45,11 +45,6 @@ module VCR
|
|
45
45
|
"recorded_with" => "VCR #{VCR.version}"
|
46
46
|
}
|
47
47
|
|
48
|
-
def hash.each
|
49
|
-
yield 'http_interactions', self['http_interactions']
|
50
|
-
yield 'recorded_with', self['recorded_with']
|
51
|
-
end
|
52
|
-
|
53
48
|
File.open(cassette, 'w') { |f| f.write ::YAML.dump(hash) }
|
54
49
|
@out.puts " - Migrated #{relative_casssette_name(cassette)}"
|
55
50
|
end
|
@@ -55,7 +55,15 @@ module VCR
|
|
55
55
|
file_extension = '.' + parts.pop
|
56
56
|
end
|
57
57
|
|
58
|
-
parts.join('.').gsub(/[^[:word:]\-\/]+/, '_') + file_extension.to_s
|
58
|
+
file_name = parts.join('.').gsub(/[^[:word:]\-\/]+/, '_') + file_extension.to_s
|
59
|
+
file_name.downcase! if downcase_cassette_names?
|
60
|
+
file_name
|
61
|
+
end
|
62
|
+
|
63
|
+
def downcase_cassette_names?
|
64
|
+
!!VCR.configuration
|
65
|
+
.default_cassette_options
|
66
|
+
.dig(:persister_options, :downcase_cassette_names)
|
59
67
|
end
|
60
68
|
end
|
61
69
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'json'
|
2
2
|
|
3
3
|
module VCR
|
4
4
|
class Cassette
|
@@ -13,8 +13,8 @@ module VCR
|
|
13
13
|
extend EncodingErrorHandling
|
14
14
|
|
15
15
|
# @private
|
16
|
-
ENCODING_ERRORS = [
|
17
|
-
ENCODING_ERRORS <<
|
16
|
+
ENCODING_ERRORS = [ArgumentError]
|
17
|
+
ENCODING_ERRORS << ::JSON::GeneratorError
|
18
18
|
|
19
19
|
# The file extension to use for this serializer.
|
20
20
|
#
|
@@ -23,23 +23,23 @@ module VCR
|
|
23
23
|
"json"
|
24
24
|
end
|
25
25
|
|
26
|
-
# Serializes the given hash using `
|
26
|
+
# Serializes the given hash using `JSON`.
|
27
27
|
#
|
28
28
|
# @param [Hash] hash the object to serialize
|
29
29
|
# @return [String] the JSON string
|
30
30
|
def serialize(hash)
|
31
31
|
handle_encoding_errors do
|
32
|
-
|
32
|
+
::JSON.generate(hash)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
# Deserializes the given string using `
|
36
|
+
# Deserializes the given string using `JSON`.
|
37
37
|
#
|
38
38
|
# @param [String] string the JSON string
|
39
39
|
# @return [Hash] the deserialized object
|
40
40
|
def deserialize(string)
|
41
41
|
handle_encoding_errors do
|
42
|
-
|
42
|
+
::JSON.parse(string)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -28,7 +28,9 @@ module VCR
|
|
28
28
|
# @return [String] the YAML string
|
29
29
|
def serialize(hash)
|
30
30
|
handle_encoding_errors do
|
31
|
-
::Psych.dump(hash)
|
31
|
+
result = ::Psych.dump(hash)
|
32
|
+
result.gsub!(": \n", ": null\n") # set canonical null value in order to avoid trailing whitespaces
|
33
|
+
result
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
@@ -30,7 +30,9 @@ module VCR
|
|
30
30
|
# @return [String] the YAML string
|
31
31
|
def serialize(hash)
|
32
32
|
handle_encoding_errors do
|
33
|
-
::YAML.dump(hash)
|
33
|
+
result = ::YAML.dump(hash)
|
34
|
+
result.gsub!(": \n", ": null\n") # set canonical null value in order to avoid trailing whitespaces
|
35
|
+
result
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
data/lib/vcr/cassette.rb
CHANGED
@@ -24,6 +24,13 @@ module VCR
|
|
24
24
|
# plays them back, or does both.
|
25
25
|
attr_reader :record_mode
|
26
26
|
|
27
|
+
# @return [Boolean] The cassette's record_on_error mode. When the code that uses the cassette
|
28
|
+
# raises an error (for example a test failure) and record_on_error is set to false, no
|
29
|
+
# cassette will be recorded. This is useful when you are TDD'ing an API integration: when
|
30
|
+
# an error is raised that often means your request is invalid, so you don't want the cassette
|
31
|
+
# to be recorded.
|
32
|
+
attr_reader :record_on_error
|
33
|
+
|
27
34
|
# @return [Array<Symbol, #call>] List of request matchers. Used to find a response from an
|
28
35
|
# existing HTTP interaction to play back.
|
29
36
|
attr_reader :match_requests_on
|
@@ -48,6 +55,7 @@ module VCR
|
|
48
55
|
def initialize(name, options = {})
|
49
56
|
@name = name
|
50
57
|
@options = VCR.configuration.default_cassette_options.merge(options)
|
58
|
+
@mutex = Mutex.new
|
51
59
|
|
52
60
|
assert_valid_options!
|
53
61
|
extract_options
|
@@ -65,21 +73,40 @@ module VCR
|
|
65
73
|
# @param (see VCR#eject_casssette)
|
66
74
|
# @see VCR#eject_cassette
|
67
75
|
def eject(options = {})
|
68
|
-
write_recorded_interactions_to_disk
|
76
|
+
write_recorded_interactions_to_disk if should_write_recorded_interactions_to_disk?
|
69
77
|
|
70
78
|
if should_assert_no_unused_interactions? && !options[:skip_no_unused_interactions_assertion]
|
71
79
|
http_interactions.assert_no_unused_interactions!
|
72
80
|
end
|
73
81
|
end
|
74
82
|
|
83
|
+
# @private
|
84
|
+
def run_failed!
|
85
|
+
@run_failed = true
|
86
|
+
end
|
87
|
+
|
88
|
+
# @private
|
89
|
+
def run_failed?
|
90
|
+
@run_failed = false unless defined?(@run_failed)
|
91
|
+
@run_failed
|
92
|
+
end
|
93
|
+
|
94
|
+
def should_write_recorded_interactions_to_disk?
|
95
|
+
!run_failed? || record_on_error
|
96
|
+
end
|
97
|
+
|
75
98
|
# @private
|
76
99
|
def http_interactions
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
@
|
81
|
-
|
82
|
-
|
100
|
+
# Without this mutex, under threaded access, an HTTPInteractionList will overwrite
|
101
|
+
# the first.
|
102
|
+
@mutex.synchronize do
|
103
|
+
@http_interactions ||= HTTPInteractionList.new \
|
104
|
+
should_stub_requests? ? previously_recorded_interactions : [],
|
105
|
+
match_requests_on,
|
106
|
+
@allow_playback_repeats,
|
107
|
+
@parent_list,
|
108
|
+
log_prefix
|
109
|
+
end
|
83
110
|
end
|
84
111
|
|
85
112
|
# @private
|
@@ -146,10 +173,10 @@ module VCR
|
|
146
173
|
|
147
174
|
def assert_valid_options!
|
148
175
|
invalid_options = @options.keys - [
|
149
|
-
:record, :erb, :match_requests_on, :re_record_interval, :tag, :tags,
|
176
|
+
:record, :record_on_error, :erb, :match_requests_on, :re_record_interval, :tag, :tags,
|
150
177
|
:update_content_length_header, :allow_playback_repeats, :allow_unused_http_interactions,
|
151
178
|
:exclusive, :serialize_with, :preserve_exact_body_bytes, :decode_compressed_response,
|
152
|
-
:persist_with, :clean_outdated_http_interactions
|
179
|
+
:recompress_response, :persist_with, :persister_options, :clean_outdated_http_interactions
|
153
180
|
]
|
154
181
|
|
155
182
|
if invalid_options.size > 0
|
@@ -158,7 +185,7 @@ module VCR
|
|
158
185
|
end
|
159
186
|
|
160
187
|
def extract_options
|
161
|
-
[:erb, :match_requests_on, :re_record_interval, :clean_outdated_http_interactions,
|
188
|
+
[:record_on_error, :erb, :match_requests_on, :re_record_interval, :clean_outdated_http_interactions,
|
162
189
|
:allow_playback_repeats, :allow_unused_http_interactions, :exclusive].each do |name|
|
163
190
|
instance_variable_set("@#{name}", @options[name])
|
164
191
|
end
|
@@ -175,7 +202,7 @@ module VCR
|
|
175
202
|
def assign_tags
|
176
203
|
@tags = Array(@options.fetch(:tags) { @options[:tag] })
|
177
204
|
|
178
|
-
[:update_content_length_header, :preserve_exact_body_bytes, :decode_compressed_response].each do |tag|
|
205
|
+
[:update_content_length_header, :preserve_exact_body_bytes, :decode_compressed_response, :recompress_response].each do |tag|
|
179
206
|
@tags << tag if @options[tag]
|
180
207
|
end
|
181
208
|
end
|
data/lib/vcr/configuration.rb
CHANGED
@@ -77,6 +77,15 @@ module VCR
|
|
77
77
|
end
|
78
78
|
alias ignore_host ignore_hosts
|
79
79
|
|
80
|
+
# Specifies host(s) that VCR should stop ignoring.
|
81
|
+
#
|
82
|
+
# @param hosts [Array<String>] List of hosts to unignore
|
83
|
+
# @see #ignore_hosts
|
84
|
+
def unignore_hosts(*hosts)
|
85
|
+
VCR.request_ignorer.unignore_hosts(*hosts)
|
86
|
+
end
|
87
|
+
alias unignore_host unignore_hosts
|
88
|
+
|
80
89
|
# Sets whether or not VCR should ignore localhost requests.
|
81
90
|
#
|
82
91
|
# @param value [Boolean] the value to set
|
@@ -222,7 +231,7 @@ module VCR
|
|
222
231
|
|
223
232
|
before_playback(tag) do |interaction|
|
224
233
|
orig_text = call_block(block, interaction)
|
225
|
-
log "before_playback: replacing #{
|
234
|
+
log "before_playback: replacing #{orig_text.inspect} with #{placeholder.inspect}"
|
226
235
|
interaction.filter!(placeholder, orig_text)
|
227
236
|
end
|
228
237
|
end
|
@@ -483,10 +492,12 @@ module VCR
|
|
483
492
|
@rspec_metadata_configured = false
|
484
493
|
@default_cassette_options = {
|
485
494
|
:record => :once,
|
495
|
+
:record_on_error => true,
|
486
496
|
:match_requests_on => RequestMatcherRegistry::DEFAULT_MATCHERS,
|
487
497
|
:allow_unused_http_interactions => true,
|
488
498
|
:serialize_with => :yaml,
|
489
|
-
:persist_with => :file_system
|
499
|
+
:persist_with => :file_system,
|
500
|
+
:persister_options => {}
|
490
501
|
}
|
491
502
|
|
492
503
|
self.uri_parser = URI
|
@@ -550,6 +561,10 @@ module VCR
|
|
550
561
|
end
|
551
562
|
|
552
563
|
def register_built_in_hooks
|
564
|
+
before_playback(:recompress_response) do |interaction|
|
565
|
+
interaction.response.recompress if interaction.response.vcr_decompressed?
|
566
|
+
end
|
567
|
+
|
553
568
|
before_playback(:update_content_length_header) do |interaction|
|
554
569
|
interaction.response.update_content_length_header
|
555
570
|
end
|
@@ -571,4 +586,3 @@ module VCR
|
|
571
586
|
define_hook :after_library_hooks_loaded
|
572
587
|
end
|
573
588
|
end
|
574
|
-
|
data/lib/vcr/errors.rb
CHANGED
@@ -88,18 +88,7 @@ module VCR
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def current_cassettes
|
91
|
-
@cassettes ||=
|
92
|
-
cassettes = VCR.cassettes.to_a.reverse
|
93
|
-
|
94
|
-
begin
|
95
|
-
loop do
|
96
|
-
break unless VCR.eject_cassette
|
97
|
-
end
|
98
|
-
rescue EjectLinkedCassetteError
|
99
|
-
end
|
100
|
-
|
101
|
-
cassettes
|
102
|
-
end
|
91
|
+
@cassettes ||= VCR.cassettes.to_a.reverse
|
103
92
|
end
|
104
93
|
|
105
94
|
def request_description
|
@@ -22,6 +22,14 @@ VCR.configuration.after_library_hooks_loaded do
|
|
22
22
|
# (i.e. to double record requests or whatever).
|
23
23
|
if defined?(WebMock::HttpLibAdapters::ExconAdapter)
|
24
24
|
WebMock::HttpLibAdapters::ExconAdapter.disable!
|
25
|
+
|
26
|
+
if defined?(::RSpec)
|
27
|
+
::RSpec.configure do |config|
|
28
|
+
config.before(:suite) do
|
29
|
+
WebMock::HttpLibAdapters::ExconAdapter.disable!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
25
33
|
end
|
26
34
|
end
|
27
35
|
|
data/lib/vcr/linked_cassette.rb
CHANGED
@@ -9,8 +9,8 @@ module VCR
|
|
9
9
|
include Enumerable
|
10
10
|
|
11
11
|
# Creates a new list of context-owned cassettes and linked cassettes
|
12
|
-
# @param [Array] context-owned cassettes
|
13
|
-
# @param [Array] context-unowned (linked) cassettes
|
12
|
+
# @param cassettes [Array] context-owned cassettes
|
13
|
+
# @param linked_cassettes [Array] context-unowned (linked) cassettes
|
14
14
|
def initialize(cassettes, linked_cassettes)
|
15
15
|
@cassettes = cassettes
|
16
16
|
@linked_cassettes = linked_cassettes
|
@@ -52,8 +52,8 @@ module VCR
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# Create a new CassetteList
|
55
|
-
# @param [Array] context-owned cassettes
|
56
|
-
# @param [Array] context-unowned (linked) cassettes
|
55
|
+
# @param cassettes [Array] context-owned cassettes
|
56
|
+
# @param linked_cassettes [Array] context-unowned (linked) cassettes
|
57
57
|
def self.list(cassettes, linked_cassettes)
|
58
58
|
CassetteList.new(cassettes, linked_cassettes)
|
59
59
|
end
|
data/lib/vcr/request_ignorer.rb
CHANGED
@@ -29,6 +29,10 @@ module VCR
|
|
29
29
|
ignored_hosts.merge(hosts)
|
30
30
|
end
|
31
31
|
|
32
|
+
def unignore_hosts(*hosts)
|
33
|
+
ignored_hosts.subtract(hosts)
|
34
|
+
end
|
35
|
+
|
32
36
|
def ignore?(request)
|
33
37
|
invoke_hook(:ignore_request, request).any?
|
34
38
|
end
|
@@ -40,4 +44,3 @@ module VCR
|
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
43
|
-
|
data/lib/vcr/structs.rb
CHANGED
@@ -62,7 +62,7 @@ module VCR
|
|
62
62
|
super
|
63
63
|
|
64
64
|
if body && !body.is_a?(String)
|
65
|
-
raise ArgumentError, "#{self.class} initialized with an invalid body: #{body.inspect}."
|
65
|
+
raise ArgumentError, "#{self.class} initialized with an invalid (non-String) body of class #{body.class}: #{body.inspect}."
|
66
66
|
end
|
67
67
|
|
68
68
|
# Ensure that the body is a raw string, in case the string instance
|
@@ -167,25 +167,6 @@ module VCR
|
|
167
167
|
end
|
168
168
|
end
|
169
169
|
|
170
|
-
# @private
|
171
|
-
module OrderedHashSerializer
|
172
|
-
def each
|
173
|
-
@ordered_keys.each do |key|
|
174
|
-
yield key, self[key] if has_key?(key)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
if RUBY_VERSION.to_f > 1.8
|
179
|
-
# 1.9+ hashes are already ordered.
|
180
|
-
def self.apply_to(*args); end
|
181
|
-
else
|
182
|
-
def self.apply_to(hash, keys)
|
183
|
-
hash.instance_variable_set(:@ordered_keys, keys)
|
184
|
-
hash.extend self
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
170
|
# The request of an {HTTPInteraction}.
|
190
171
|
#
|
191
172
|
# @attr [Symbol] method the HTTP method (i.e. :head, :options, :get, :post, :put, :patch or :delete)
|
@@ -219,7 +200,7 @@ module VCR
|
|
219
200
|
'uri' => uri,
|
220
201
|
'body' => serializable_body,
|
221
202
|
'headers' => headers
|
222
|
-
}
|
203
|
+
}
|
223
204
|
end
|
224
205
|
|
225
206
|
# Constructs a new instance from a hash.
|
@@ -365,11 +346,10 @@ module VCR
|
|
365
346
|
{
|
366
347
|
'status' => status.to_hash,
|
367
348
|
'headers' => headers,
|
368
|
-
'body' => serializable_body
|
369
|
-
'http_version' => http_version
|
349
|
+
'body' => serializable_body
|
370
350
|
}.tap do |hash|
|
351
|
+
hash['http_version'] = http_version if http_version
|
371
352
|
hash['adapter_metadata'] = adapter_metadata unless adapter_metadata.empty?
|
372
|
-
OrderedHashSerializer.apply_to(hash, members)
|
373
353
|
end
|
374
354
|
end
|
375
355
|
|
@@ -403,6 +383,11 @@ module VCR
|
|
403
383
|
%w[ gzip deflate ].include? content_encoding
|
404
384
|
end
|
405
385
|
|
386
|
+
# Checks if VCR decompressed the response body
|
387
|
+
def vcr_decompressed?
|
388
|
+
adapter_metadata['vcr_decompressed']
|
389
|
+
end
|
390
|
+
|
406
391
|
# Decodes the compressed body and deletes evidence that it was ever compressed.
|
407
392
|
#
|
408
393
|
# @return self
|
@@ -412,11 +397,43 @@ module VCR
|
|
412
397
|
self.class.decompress(body, content_encoding) { |new_body|
|
413
398
|
self.body = new_body
|
414
399
|
update_content_length_header
|
400
|
+
adapter_metadata['vcr_decompressed'] = content_encoding
|
415
401
|
delete_header('Content-Encoding')
|
416
402
|
}
|
417
403
|
return self
|
418
404
|
end
|
419
405
|
|
406
|
+
# Recompresses the decompressed body according to adapter metadata.
|
407
|
+
#
|
408
|
+
# @raise [VCR::Errors::UnknownContentEncodingError] if the content encoding
|
409
|
+
# stored in the adapter metadata is unknown
|
410
|
+
def recompress
|
411
|
+
type = adapter_metadata['vcr_decompressed']
|
412
|
+
new_body = begin
|
413
|
+
case type
|
414
|
+
when 'gzip'
|
415
|
+
body_str = ''
|
416
|
+
args = [StringIO.new(body_str)]
|
417
|
+
args << { :encoding => 'ASCII-8BIT' } if ''.respond_to?(:encoding)
|
418
|
+
writer = Zlib::GzipWriter.new(*args)
|
419
|
+
writer.write(body)
|
420
|
+
writer.close
|
421
|
+
body_str
|
422
|
+
when 'deflate'
|
423
|
+
Zlib::Deflate.inflate(body)
|
424
|
+
when 'identity', NilClass
|
425
|
+
nil
|
426
|
+
else
|
427
|
+
raise Errors::UnknownContentEncodingError, "unknown content encoding: #{type}"
|
428
|
+
end
|
429
|
+
end
|
430
|
+
if new_body
|
431
|
+
self.body = new_body
|
432
|
+
update_content_length_header
|
433
|
+
headers['Content-Encoding'] = type
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
420
437
|
begin
|
421
438
|
require 'zlib'
|
422
439
|
require 'stringio'
|
@@ -437,9 +454,10 @@ module VCR
|
|
437
454
|
|
438
455
|
case type
|
439
456
|
when 'gzip'
|
440
|
-
|
441
|
-
|
442
|
-
yield Zlib::GzipReader.new(
|
457
|
+
gzip_reader_options = {}
|
458
|
+
gzip_reader_options[:encoding] = 'ASCII-8BIT' if ''.respond_to?(:encoding)
|
459
|
+
yield Zlib::GzipReader.new(StringIO.new(body),
|
460
|
+
**gzip_reader_options).read
|
443
461
|
when 'deflate'
|
444
462
|
yield Zlib::Inflate.inflate(body)
|
445
463
|
when 'identity', NilClass
|
@@ -463,7 +481,7 @@ module VCR
|
|
463
481
|
def to_hash
|
464
482
|
{
|
465
483
|
'code' => code, 'message' => message
|
466
|
-
}
|
484
|
+
}
|
467
485
|
end
|
468
486
|
|
469
487
|
# Constructs a new instance from a hash.
|
@@ -496,9 +514,7 @@ module VCR
|
|
496
514
|
'request' => request.to_hash,
|
497
515
|
'response' => response.to_hash,
|
498
516
|
'recorded_at' => recorded_at.httpdate
|
499
|
-
}
|
500
|
-
OrderedHashSerializer.apply_to(hash, members)
|
501
|
-
end
|
517
|
+
}
|
502
518
|
end
|
503
519
|
|
504
520
|
# Constructs a new instance from a hash.
|
@@ -23,10 +23,10 @@ module VCR
|
|
23
23
|
# Adds `Before` and `After` cucumber hooks for the named tags that
|
24
24
|
# will cause a VCR cassette to be used for scenarios with matching tags.
|
25
25
|
#
|
26
|
-
# @param [Array<String>]
|
27
|
-
#
|
28
|
-
# `:use_scenario_name => true` to automatically name the
|
29
|
-
#
|
26
|
+
# @param tag_names [Array<String,Hash>] the cucumber scenario tags. If
|
27
|
+
# the last argument is a hash it is treated as cassette options.
|
28
|
+
# - `:use_scenario_name => true` to automatically name the
|
29
|
+
# cassette according to the scenario name.
|
30
30
|
def tags(*tag_names)
|
31
31
|
original_options = tag_names.last.is_a?(::Hash) ? tag_names.pop : {}
|
32
32
|
tag_names.each do |tag_name|
|
@@ -32,10 +32,19 @@ module VCR
|
|
32
32
|
config.before(:each, when_tagged_with_vcr) do |ex|
|
33
33
|
example = ex.respond_to?(:metadata) ? ex : ex.example
|
34
34
|
|
35
|
+
cassette_name = nil
|
35
36
|
options = example.metadata[:vcr]
|
36
|
-
options =
|
37
|
-
|
38
|
-
|
37
|
+
options = case options
|
38
|
+
when Hash #=> vcr: { cassette_name: 'foo' }
|
39
|
+
options.dup
|
40
|
+
when String #=> vcr: 'bar'
|
41
|
+
cassette_name = options.dup
|
42
|
+
{}
|
43
|
+
else #=> :vcr or vcr: true
|
44
|
+
{}
|
45
|
+
end
|
46
|
+
|
47
|
+
cassette_name ||= options.delete(:cassette_name) ||
|
39
48
|
vcr_cassette_name_for[example.metadata]
|
40
49
|
VCR.insert_cassette(cassette_name, options)
|
41
50
|
end
|
@@ -1,31 +1,25 @@
|
|
1
1
|
module VCR
|
2
2
|
# Ruby 1.8 provides Ping.pingecho, but it was removed in 1.9.
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
Ping = ::Ping
|
7
|
-
rescue LoadError
|
8
|
-
# This is copied, verbatim, from Ruby 1.8.7's ping.rb.
|
9
|
-
require 'timeout'
|
10
|
-
require "socket"
|
3
|
+
# This is copied, verbatim, from Ruby 1.8.7's ping.rb.
|
4
|
+
require 'timeout'
|
5
|
+
require "socket"
|
11
6
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
rescue Errno::ECONNREFUSED
|
21
|
-
return true
|
22
|
-
rescue Timeout::Error, StandardError
|
23
|
-
return false
|
7
|
+
# @private
|
8
|
+
module Ping
|
9
|
+
def pingecho(host, timeout=5, service="echo")
|
10
|
+
begin
|
11
|
+
Timeout.timeout(timeout) do
|
12
|
+
s = TCPSocket.new(host, service)
|
13
|
+
s.close
|
24
14
|
end
|
15
|
+
rescue Errno::ECONNREFUSED
|
25
16
|
return true
|
17
|
+
rescue Timeout::Error, StandardError
|
18
|
+
return false
|
26
19
|
end
|
27
|
-
|
20
|
+
return true
|
28
21
|
end
|
22
|
+
module_function :pingecho
|
29
23
|
end
|
30
24
|
|
31
25
|
# @private
|
data/lib/vcr/version.rb
CHANGED
data/lib/vcr.rb
CHANGED
@@ -107,6 +107,12 @@ module VCR
|
|
107
107
|
# @option options :persist_with [Symbol] Which cassette persister to
|
108
108
|
# use. Defaults to :file_system. You can also register and use a
|
109
109
|
# custom persister.
|
110
|
+
# @option options :persister_options [Hash] Pass options to the
|
111
|
+
# persister specified in `persist_with`. Currently available options for the file_system persister:
|
112
|
+
# - `:downcase_cassette_names`: when `true`, names of cassettes will be
|
113
|
+
# normalized in lowercase before reading and writing, which can avoid
|
114
|
+
# confusion when using both case-sensitive and case-insensitive file
|
115
|
+
# systems.
|
110
116
|
# @option options :preserve_exact_body_bytes [Boolean] Whether or not
|
111
117
|
# to base64 encode the bytes of the requests and responses for this cassette
|
112
118
|
# when serializing it. See also `VCR::Configuration#preserve_exact_body_bytes`.
|
@@ -186,6 +192,9 @@ module VCR
|
|
186
192
|
|
187
193
|
begin
|
188
194
|
call_block(block, cassette)
|
195
|
+
rescue StandardError
|
196
|
+
cassette.run_failed!
|
197
|
+
raise
|
189
198
|
ensure
|
190
199
|
eject_cassette
|
191
200
|
end
|
@@ -194,18 +203,21 @@ module VCR
|
|
194
203
|
# Inserts multiple cassettes the given names
|
195
204
|
#
|
196
205
|
# @example
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
200
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
206
|
+
# cassettes = [
|
207
|
+
# { name: 'github' },
|
208
|
+
# { name: 'apple', options: { erb: true } }
|
209
|
+
# ]
|
210
|
+
# VCR.use_cassettes(cassettes) do
|
211
|
+
# # make multiple HTTP requests
|
212
|
+
# end
|
204
213
|
def use_cassettes(cassettes, &block)
|
205
|
-
return use_cassette(cassettes.last[:name]) { block.call } if cassettes.length == 1
|
206
214
|
cassette = cassettes.pop
|
207
|
-
use_cassette(cassette[:name], cassette[:options]) do
|
208
|
-
|
215
|
+
use_cassette(cassette[:name], cassette[:options] || {}) do
|
216
|
+
if cassettes.empty?
|
217
|
+
block.call
|
218
|
+
else
|
219
|
+
use_cassettes(cassettes, &block)
|
220
|
+
end
|
209
221
|
end
|
210
222
|
end
|
211
223
|
|
@@ -305,6 +317,9 @@ module VCR
|
|
305
317
|
# @see #turn_off!
|
306
318
|
# @see #turned_off
|
307
319
|
def turned_on?
|
320
|
+
linked_context = current_context[:linked_context]
|
321
|
+
return !linked_context[:turned_off] if linked_context
|
322
|
+
|
308
323
|
!context_value(:turned_off)
|
309
324
|
end
|
310
325
|
|
metadata
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vcr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Myron Marston
|
8
|
+
- Kurtis Rainbolt-Greene
|
9
|
+
- Olle Jonsson
|
8
10
|
autorequire:
|
9
11
|
bindir: bin
|
10
12
|
cert_chain: []
|
11
|
-
date:
|
13
|
+
date: 2020-05-28 00:00:00.000000000 Z
|
12
14
|
dependencies:
|
13
15
|
- !ruby/object:Gem::Dependency
|
14
16
|
name: bundler
|
@@ -16,14 +18,14 @@ dependencies:
|
|
16
18
|
requirements:
|
17
19
|
- - "~>"
|
18
20
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
21
|
+
version: '2.0'
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
23
25
|
requirements:
|
24
26
|
- - "~>"
|
25
27
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
28
|
+
version: '2.0'
|
27
29
|
- !ruby/object:Gem::Dependency
|
28
30
|
name: rspec
|
29
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,63 +153,75 @@ dependencies:
|
|
151
153
|
- !ruby/object:Gem::Version
|
152
154
|
version: '0'
|
153
155
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
156
|
+
name: hashdiff
|
155
157
|
requirement: !ruby/object:Gem::Requirement
|
156
158
|
requirements:
|
157
|
-
- - "
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: 1.0.0.beta1
|
162
|
+
- - "<"
|
158
163
|
- !ruby/object:Gem::Version
|
159
|
-
version: 2.0.
|
164
|
+
version: 2.0.0
|
160
165
|
type: :development
|
161
166
|
prerelease: false
|
162
167
|
version_requirements: !ruby/object:Gem::Requirement
|
163
168
|
requirements:
|
164
|
-
- - "
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: 1.0.0.beta1
|
172
|
+
- - "<"
|
165
173
|
- !ruby/object:Gem::Version
|
166
|
-
version: 2.0.
|
174
|
+
version: 2.0.0
|
167
175
|
- !ruby/object:Gem::Dependency
|
168
|
-
name:
|
176
|
+
name: cucumber
|
169
177
|
requirement: !ruby/object:Gem::Requirement
|
170
178
|
requirements:
|
171
179
|
- - "~>"
|
172
180
|
- !ruby/object:Gem::Version
|
173
|
-
version:
|
181
|
+
version: '3.1'
|
174
182
|
type: :development
|
175
183
|
prerelease: false
|
176
184
|
version_requirements: !ruby/object:Gem::Requirement
|
177
185
|
requirements:
|
178
186
|
- - "~>"
|
179
187
|
- !ruby/object:Gem::Version
|
180
|
-
version:
|
188
|
+
version: '3.1'
|
181
189
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
190
|
+
name: aruba
|
183
191
|
requirement: !ruby/object:Gem::Requirement
|
184
192
|
requirements:
|
185
193
|
- - "~>"
|
186
194
|
- !ruby/object:Gem::Version
|
187
|
-
version: 0.
|
195
|
+
version: 0.14.14
|
188
196
|
type: :development
|
189
197
|
prerelease: false
|
190
198
|
version_requirements: !ruby/object:Gem::Requirement
|
191
199
|
requirements:
|
192
200
|
- - "~>"
|
193
201
|
- !ruby/object:Gem::Version
|
194
|
-
version: 0.
|
202
|
+
version: 0.14.14
|
195
203
|
- !ruby/object:Gem::Dependency
|
196
|
-
name:
|
204
|
+
name: faraday
|
197
205
|
requirement: !ruby/object:Gem::Requirement
|
198
206
|
requirements:
|
199
207
|
- - ">="
|
200
208
|
- !ruby/object:Gem::Version
|
201
|
-
version:
|
209
|
+
version: 0.11.0
|
210
|
+
- - "<"
|
211
|
+
- !ruby/object:Gem::Version
|
212
|
+
version: 2.0.0
|
202
213
|
type: :development
|
203
214
|
prerelease: false
|
204
215
|
version_requirements: !ruby/object:Gem::Requirement
|
205
216
|
requirements:
|
206
217
|
- - ">="
|
207
218
|
- !ruby/object:Gem::Version
|
208
|
-
version:
|
219
|
+
version: 0.11.0
|
220
|
+
- - "<"
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: 2.0.0
|
209
223
|
- !ruby/object:Gem::Dependency
|
210
|
-
name:
|
224
|
+
name: httpclient
|
211
225
|
requirement: !ruby/object:Gem::Requirement
|
212
226
|
requirements:
|
213
227
|
- - ">="
|
@@ -221,21 +235,21 @@ dependencies:
|
|
221
235
|
- !ruby/object:Gem::Version
|
222
236
|
version: '0'
|
223
237
|
- !ruby/object:Gem::Dependency
|
224
|
-
name:
|
238
|
+
name: excon
|
225
239
|
requirement: !ruby/object:Gem::Requirement
|
226
240
|
requirements:
|
227
241
|
- - ">="
|
228
242
|
- !ruby/object:Gem::Version
|
229
|
-
version:
|
243
|
+
version: 0.62.0
|
230
244
|
type: :development
|
231
245
|
prerelease: false
|
232
246
|
version_requirements: !ruby/object:Gem::Requirement
|
233
247
|
requirements:
|
234
248
|
- - ">="
|
235
249
|
- !ruby/object:Gem::Version
|
236
|
-
version:
|
250
|
+
version: 0.62.0
|
237
251
|
- !ruby/object:Gem::Dependency
|
238
|
-
name:
|
252
|
+
name: timecop
|
239
253
|
requirement: !ruby/object:Gem::Requirement
|
240
254
|
requirements:
|
241
255
|
- - ">="
|
@@ -307,7 +321,7 @@ dependencies:
|
|
307
321
|
description: Record your test suite's HTTP interactions and replay them during future
|
308
322
|
test runs for fast, deterministic, accurate tests.
|
309
323
|
email:
|
310
|
-
-
|
324
|
+
- kurtis@rainbolt-greene.online
|
311
325
|
executables: []
|
312
326
|
extensions: []
|
313
327
|
extra_rdoc_files: []
|
@@ -354,6 +368,7 @@ files:
|
|
354
368
|
- lib/vcr/version.rb
|
355
369
|
homepage: https://relishapp.com/vcr/vcr/docs
|
356
370
|
licenses:
|
371
|
+
- Hippocratic-2.1
|
357
372
|
- MIT
|
358
373
|
metadata: {}
|
359
374
|
post_install_message:
|
@@ -364,15 +379,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
364
379
|
requirements:
|
365
380
|
- - ">="
|
366
381
|
- !ruby/object:Gem::Version
|
367
|
-
version:
|
382
|
+
version: '2.3'
|
368
383
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
369
384
|
requirements:
|
370
385
|
- - ">="
|
371
386
|
- !ruby/object:Gem::Version
|
372
387
|
version: '0'
|
373
388
|
requirements: []
|
374
|
-
|
375
|
-
rubygems_version: 2.6.13
|
389
|
+
rubygems_version: 3.1.3
|
376
390
|
signing_key:
|
377
391
|
specification_version: 4
|
378
392
|
summary: Record your test suite's HTTP interactions and replay them during future
|