vcr 4.0.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 806e6d86ccbe7132de58cc1313e0aef6ab0c2d8d
4
- data.tar.gz: e86dd3056697f943fe96721fd2e58163fa900c1e
2
+ SHA256:
3
+ metadata.gz: 79ff7c5f67afb190b63450e117a7dbda6709340fbab8c17680c36b2bb5a8a6f6
4
+ data.tar.gz: a6a17620c6c63d9a596a39e2700f3f1becddb26bfa63f862e42ef0dfabb783d9
5
5
  SHA512:
6
- metadata.gz: 7549fff407299870a1d989c3627a371b1a77d5054ba42b9a3ee52abd1e579acccbe282a1e7077f3f7bf14eceef2ed6a04d8a7a7578895061d6f858436c07be01
7
- data.tar.gz: 427619bde2eb934e06da74ba0888544efc574f437387cd6e00b7e8e3736f760bb5461626e697e4d9725c3d53103d22d9c589f1d809c3aa062550ab9c6fe3d746
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
- if index = matching_interaction_index_for(request)
32
- interaction = @interactions.delete_at(index)
33
- @used_interactions.unshift interaction
34
- log "Found matching interaction for #{request_summary(request)} at index #{index}: #{response_summary(interaction.response)}", 1
35
- interaction.response
36
- elsif interaction = matching_used_interaction_for(request)
37
- interaction.response
38
- else
39
- @parent_list.response_for(request)
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
@@ -17,9 +17,9 @@ module VCR
17
17
 
18
18
  # The file extension to use for this serializer.
19
19
  #
20
- # @return [String] "gz"
20
+ # @return [String] "zz"
21
21
  def file_extension
22
- 'gz'
22
+ 'zz'
23
23
  end
24
24
 
25
25
  # Serializes the given hash using YAML and Zlib.
@@ -1,4 +1,4 @@
1
- require 'multi_json'
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 = [MultiJson::DecodeError, ArgumentError]
17
- ENCODING_ERRORS << EncodingError if defined?(EncodingError)
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 `MultiJson`.
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
- MultiJson.encode(hash)
32
+ ::JSON.generate(hash)
33
33
  end
34
34
  end
35
35
 
36
- # Deserializes the given string using `MultiJson`.
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
- MultiJson.decode(string)
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
- @http_interactions ||= HTTPInteractionList.new \
78
- should_stub_requests? ? previously_recorded_interactions : [],
79
- match_requests_on,
80
- @allow_playback_repeats,
81
- @parent_list,
82
- log_prefix
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
@@ -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 #{placeholder.inspect} with #{orig_text.inspect}"
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 ||= begin
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
 
@@ -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
@@ -31,6 +31,11 @@ module VCR
31
31
  RequestHandler.new(@app, env).handle
32
32
  end
33
33
 
34
+ # Close any persistent connections.
35
+ def close
36
+ @app.close if @app.respond_to?(:close)
37
+ end
38
+
34
39
  # @private
35
40
  class RequestHandler < ::VCR::RequestHandler
36
41
  attr_reader :app, :env
@@ -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
-
@@ -138,7 +138,7 @@ module VCR
138
138
 
139
139
  register(:body_as_json) do |r1, r2|
140
140
  begin
141
- JSON.parse(r1.body) == JSON.parse(r2.body)
141
+ r1.body == r2.body || JSON.parse(r1.body) == JSON.parse(r2.body)
142
142
  rescue JSON::ParserError
143
143
  false
144
144
  end
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
- }.tap { |h| OrderedHashSerializer.apply_to(h, members) }
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
- args = [StringIO.new(body)]
441
- args << { :encoding => 'ASCII-8BIT' } if ''.respond_to?(:encoding)
442
- yield Zlib::GzipReader.new(*args).read
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
- }.tap { |h| OrderedHashSerializer.apply_to(h, members) }
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
- }.tap do |hash|
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>] tag_names the cucumber scenario tags
27
- # @param [(optional) Hash] options the cassette options. Specify
28
- # `:use_scenario_name => true` to automatically name the
29
- # cassette according to the scenario name.
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 = options.is_a?(Hash) ? options.dup : {} # in case it's just :vcr => true
37
-
38
- cassette_name = options.delete(:cassette_name) ||
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
- # So we try requiring it, and if that fails, define it ourselves.
4
- begin
5
- require 'ping'
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
- # @private
13
- module Ping
14
- def pingecho(host, timeout=5, service="echo")
15
- begin
16
- Timeout.timeout(timeout) do
17
- s = TCPSocket.new(host, service)
18
- s.close
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
- module_function :pingecho
20
+ return true
28
21
  end
22
+ module_function :pingecho
29
23
  end
30
24
 
31
25
  # @private
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 = '4.0.0'
13
+ string = '6.0.0'
14
14
 
15
15
  def string.parts
16
16
  split('.').map { |p| p.to_i }
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
- # cassettes = [
198
- # { name: 'github' },
199
- # { name: 'apple', options: { erb: true } }
200
- # ]
201
- # VCR.use_cassettes() do
202
- # # make multiple HTTP requests
203
- # end
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
- use_cassettes(cassettes, &block)
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.0.0
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: 2017-12-04 00:00:00.000000000 Z
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: '1.3'
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: '1.3'
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: cucumber
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.2
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.2
174
+ version: 2.0.0
167
175
  - !ruby/object:Gem::Dependency
168
- name: aruba
176
+ name: cucumber
169
177
  requirement: !ruby/object:Gem::Requirement
170
178
  requirements:
171
179
  - - "~>"
172
180
  - !ruby/object:Gem::Version
173
- version: 0.5.3
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: 0.5.3
188
+ version: '3.1'
181
189
  - !ruby/object:Gem::Dependency
182
- name: faraday
190
+ name: aruba
183
191
  requirement: !ruby/object:Gem::Requirement
184
192
  requirements:
185
193
  - - "~>"
186
194
  - !ruby/object:Gem::Version
187
- version: 0.11.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.11.0
202
+ version: 0.14.14
195
203
  - !ruby/object:Gem::Dependency
196
- name: httpclient
204
+ name: faraday
197
205
  requirement: !ruby/object:Gem::Requirement
198
206
  requirements:
199
207
  - - ">="
200
208
  - !ruby/object:Gem::Version
201
- version: '0'
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: '0'
219
+ version: 0.11.0
220
+ - - "<"
221
+ - !ruby/object:Gem::Version
222
+ version: 2.0.0
209
223
  - !ruby/object:Gem::Dependency
210
- name: excon
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: timecop
238
+ name: excon
225
239
  requirement: !ruby/object:Gem::Requirement
226
240
  requirements:
227
241
  - - ">="
228
242
  - !ruby/object:Gem::Version
229
- version: '0'
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: '0'
250
+ version: 0.62.0
237
251
  - !ruby/object:Gem::Dependency
238
- name: multi_json
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
- - myron.marston@gmail.com
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: 1.9.3
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
- rubyforge_project:
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