mustwin-vcr 2.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. checksums.yaml +7 -0
  2. data/features/about_these_examples.md +18 -0
  3. data/features/cassettes/allow_unused_http_interactions.feature +100 -0
  4. data/features/cassettes/automatic_re_recording.feature +72 -0
  5. data/features/cassettes/decompress.feature +74 -0
  6. data/features/cassettes/dynamic_erb.feature +100 -0
  7. data/features/cassettes/exclusive.feature +126 -0
  8. data/features/cassettes/format.feature +323 -0
  9. data/features/cassettes/freezing_time.feature +68 -0
  10. data/features/cassettes/naming.feature +28 -0
  11. data/features/cassettes/no_cassette.feature +152 -0
  12. data/features/cassettes/update_content_length_header.feature +112 -0
  13. data/features/configuration/allow_http_connections_when_no_cassette.feature +55 -0
  14. data/features/configuration/cassette_library_dir.feature +31 -0
  15. data/features/configuration/debug_logging.feature +59 -0
  16. data/features/configuration/default_cassette_options.feature +100 -0
  17. data/features/configuration/filter_sensitive_data.feature +153 -0
  18. data/features/configuration/hook_into.feature +172 -0
  19. data/features/configuration/ignore_request.feature +192 -0
  20. data/features/configuration/preserve_exact_body_bytes.feature +108 -0
  21. data/features/configuration/query_parser.feature +84 -0
  22. data/features/configuration/uri_parser.feature +89 -0
  23. data/features/getting_started.md +82 -0
  24. data/features/hooks/after_http_request.feature +58 -0
  25. data/features/hooks/around_http_request.feature +57 -0
  26. data/features/hooks/before_http_request.feature +63 -0
  27. data/features/hooks/before_playback.feature +184 -0
  28. data/features/hooks/before_record.feature +172 -0
  29. data/features/http_libraries/em_http_request.feature +250 -0
  30. data/features/http_libraries/net_http.feature +179 -0
  31. data/features/middleware/faraday.feature +56 -0
  32. data/features/middleware/rack.feature +92 -0
  33. data/features/record_modes/all.feature +82 -0
  34. data/features/record_modes/new_episodes.feature +79 -0
  35. data/features/record_modes/none.feature +72 -0
  36. data/features/record_modes/once.feature +95 -0
  37. data/features/request_matching/README.md +30 -0
  38. data/features/request_matching/body.feature +91 -0
  39. data/features/request_matching/body_as_json.feature +90 -0
  40. data/features/request_matching/custom_matcher.feature +135 -0
  41. data/features/request_matching/headers.feature +85 -0
  42. data/features/request_matching/host.feature +95 -0
  43. data/features/request_matching/identical_request_sequence.feature +89 -0
  44. data/features/request_matching/method.feature +96 -0
  45. data/features/request_matching/path.feature +96 -0
  46. data/features/request_matching/playback_repeats.feature +98 -0
  47. data/features/request_matching/query.feature +97 -0
  48. data/features/request_matching/uri.feature +94 -0
  49. data/features/request_matching/uri_without_param.feature +101 -0
  50. data/features/step_definitions/cli_steps.rb +193 -0
  51. data/features/support/env.rb +44 -0
  52. data/features/support/http_lib_filters.rb +53 -0
  53. data/features/test_frameworks/cucumber.feature +211 -0
  54. data/features/test_frameworks/rspec_macro.feature +81 -0
  55. data/features/test_frameworks/rspec_metadata.feature +150 -0
  56. data/features/test_frameworks/test_unit.feature +49 -0
  57. data/lib/vcr.rb +347 -0
  58. data/lib/vcr/cassette.rb +291 -0
  59. data/lib/vcr/cassette/erb_renderer.rb +55 -0
  60. data/lib/vcr/cassette/http_interaction_list.rb +108 -0
  61. data/lib/vcr/cassette/migrator.rb +118 -0
  62. data/lib/vcr/cassette/persisters.rb +42 -0
  63. data/lib/vcr/cassette/persisters/file_system.rb +64 -0
  64. data/lib/vcr/cassette/serializers.rb +57 -0
  65. data/lib/vcr/cassette/serializers/json.rb +48 -0
  66. data/lib/vcr/cassette/serializers/psych.rb +48 -0
  67. data/lib/vcr/cassette/serializers/syck.rb +61 -0
  68. data/lib/vcr/cassette/serializers/yaml.rb +50 -0
  69. data/lib/vcr/configuration.rb +555 -0
  70. data/lib/vcr/deprecations.rb +109 -0
  71. data/lib/vcr/errors.rb +266 -0
  72. data/lib/vcr/extensions/net_http_response.rb +36 -0
  73. data/lib/vcr/library_hooks.rb +18 -0
  74. data/lib/vcr/library_hooks/excon.rb +27 -0
  75. data/lib/vcr/library_hooks/fakeweb.rb +196 -0
  76. data/lib/vcr/library_hooks/faraday.rb +51 -0
  77. data/lib/vcr/library_hooks/typhoeus.rb +120 -0
  78. data/lib/vcr/library_hooks/typhoeus_0.4.rb +103 -0
  79. data/lib/vcr/library_hooks/webmock.rb +164 -0
  80. data/lib/vcr/middleware/excon.rb +221 -0
  81. data/lib/vcr/middleware/excon/legacy_methods.rb +33 -0
  82. data/lib/vcr/middleware/faraday.rb +118 -0
  83. data/lib/vcr/middleware/rack.rb +79 -0
  84. data/lib/vcr/request_handler.rb +114 -0
  85. data/lib/vcr/request_ignorer.rb +43 -0
  86. data/lib/vcr/request_matcher_registry.rb +149 -0
  87. data/lib/vcr/structs.rb +578 -0
  88. data/lib/vcr/tasks/vcr.rake +9 -0
  89. data/lib/vcr/test_frameworks/cucumber.rb +64 -0
  90. data/lib/vcr/test_frameworks/rspec.rb +47 -0
  91. data/lib/vcr/util/hooks.rb +61 -0
  92. data/lib/vcr/util/internet_connection.rb +43 -0
  93. data/lib/vcr/util/logger.rb +59 -0
  94. data/lib/vcr/util/variable_args_block_caller.rb +13 -0
  95. data/lib/vcr/util/version_checker.rb +48 -0
  96. data/lib/vcr/version.rb +34 -0
  97. data/spec/acceptance/threading_spec.rb +34 -0
  98. data/spec/fixtures/cassette_spec/1_x_cassette.yml +110 -0
  99. data/spec/fixtures/cassette_spec/empty.yml +0 -0
  100. data/spec/fixtures/cassette_spec/example.yml +111 -0
  101. data/spec/fixtures/cassette_spec/with_localhost_requests.yml +111 -0
  102. data/spec/fixtures/fake_example_responses.yml +110 -0
  103. data/spec/fixtures/match_requests_on.yml +187 -0
  104. data/spec/lib/vcr/cassette/erb_renderer_spec.rb +53 -0
  105. data/spec/lib/vcr/cassette/http_interaction_list_spec.rb +295 -0
  106. data/spec/lib/vcr/cassette/migrator_spec.rb +195 -0
  107. data/spec/lib/vcr/cassette/persisters/file_system_spec.rb +69 -0
  108. data/spec/lib/vcr/cassette/persisters_spec.rb +39 -0
  109. data/spec/lib/vcr/cassette/serializers_spec.rb +176 -0
  110. data/spec/lib/vcr/cassette_spec.rb +618 -0
  111. data/spec/lib/vcr/configuration_spec.rb +326 -0
  112. data/spec/lib/vcr/deprecations_spec.rb +85 -0
  113. data/spec/lib/vcr/errors_spec.rb +162 -0
  114. data/spec/lib/vcr/extensions/net_http_response_spec.rb +86 -0
  115. data/spec/lib/vcr/library_hooks/excon_spec.rb +104 -0
  116. data/spec/lib/vcr/library_hooks/fakeweb_spec.rb +169 -0
  117. data/spec/lib/vcr/library_hooks/faraday_spec.rb +68 -0
  118. data/spec/lib/vcr/library_hooks/typhoeus_0.4_spec.rb +36 -0
  119. data/spec/lib/vcr/library_hooks/typhoeus_spec.rb +162 -0
  120. data/spec/lib/vcr/library_hooks/webmock_spec.rb +118 -0
  121. data/spec/lib/vcr/library_hooks_spec.rb +51 -0
  122. data/spec/lib/vcr/middleware/faraday_spec.rb +182 -0
  123. data/spec/lib/vcr/middleware/rack_spec.rb +115 -0
  124. data/spec/lib/vcr/request_ignorer_spec.rb +70 -0
  125. data/spec/lib/vcr/request_matcher_registry_spec.rb +345 -0
  126. data/spec/lib/vcr/structs_spec.rb +732 -0
  127. data/spec/lib/vcr/test_frameworks/cucumber_spec.rb +107 -0
  128. data/spec/lib/vcr/test_frameworks/rspec_spec.rb +83 -0
  129. data/spec/lib/vcr/util/hooks_spec.rb +158 -0
  130. data/spec/lib/vcr/util/internet_connection_spec.rb +37 -0
  131. data/spec/lib/vcr/util/version_checker_spec.rb +31 -0
  132. data/spec/lib/vcr/version_spec.rb +27 -0
  133. data/spec/lib/vcr_spec.rb +349 -0
  134. data/spec/monkey_patches.rb +182 -0
  135. data/spec/spec_helper.rb +62 -0
  136. data/spec/support/configuration_stubbing.rb +8 -0
  137. data/spec/support/cucumber_helpers.rb +35 -0
  138. data/spec/support/fixnum_extension.rb +10 -0
  139. data/spec/support/http_library_adapters.rb +289 -0
  140. data/spec/support/limited_uri.rb +21 -0
  141. data/spec/support/ruby_interpreter.rb +7 -0
  142. data/spec/support/shared_example_groups/excon.rb +63 -0
  143. data/spec/support/shared_example_groups/hook_into_http_library.rb +594 -0
  144. data/spec/support/shared_example_groups/request_hooks.rb +59 -0
  145. data/spec/support/sinatra_app.rb +86 -0
  146. data/spec/support/vcr_localhost_server.rb +76 -0
  147. data/spec/support/vcr_stub_helpers.rb +17 -0
  148. metadata +677 -0
@@ -0,0 +1,55 @@
1
+ require 'erb'
2
+
3
+ module VCR
4
+ class Cassette
5
+ # @private
6
+ class ERBRenderer
7
+ def initialize(raw_template, erb, cassette_name=nil)
8
+ @raw_template, @erb, @cassette_name = raw_template, erb, cassette_name
9
+ end
10
+
11
+ def render
12
+ return @raw_template if @raw_template.nil? || !use_erb?
13
+ binding = binding_for_variables if erb_variables
14
+ template.result(binding)
15
+ rescue NameError => e
16
+ handle_name_error(e)
17
+ end
18
+
19
+ private
20
+
21
+ def handle_name_error(e)
22
+ example_hash = (erb_variables || {}).merge(e.name => 'some value')
23
+
24
+ raise Errors::MissingERBVariableError.new(
25
+ "The ERB in the #{@cassette_name} cassette file references undefined variable #{e.name}. " +
26
+ "Pass it to the cassette using :erb => #{ example_hash.inspect }."
27
+ )
28
+ end
29
+
30
+ def use_erb?
31
+ !!@erb
32
+ end
33
+
34
+ def erb_variables
35
+ @erb if @erb.is_a?(Hash)
36
+ end
37
+
38
+ def template
39
+ @template ||= ERB.new(@raw_template)
40
+ end
41
+
42
+ @@struct_cache = Hash.new do |hash, attributes|
43
+ hash[attributes] = Struct.new(*attributes)
44
+ end
45
+
46
+ def variables_object
47
+ @variables_object ||= @@struct_cache[erb_variables.keys].new(*erb_variables.values)
48
+ end
49
+
50
+ def binding_for_variables
51
+ @binding_for_variables ||= variables_object.instance_eval { binding }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,108 @@
1
+ module VCR
2
+ class Cassette
3
+ # @private
4
+ class HTTPInteractionList
5
+ include Logger::Mixin
6
+
7
+ # @private
8
+ module NullList
9
+ extend self
10
+ def response_for(*a); nil; end
11
+ def has_interaction_matching?(*a); false; end
12
+ def has_used_interaction_matching?(*a); false; end
13
+ def remaining_unused_interaction_count(*a); 0; end
14
+ end
15
+
16
+ attr_reader :interactions, :request_matchers, :allow_playback_repeats, :parent_list
17
+
18
+ def initialize(interactions, request_matchers, allow_playback_repeats = false, parent_list = NullList, log_prefix = '')
19
+ @interactions = interactions.dup
20
+ @request_matchers = request_matchers
21
+ @allow_playback_repeats = allow_playback_repeats
22
+ @parent_list = parent_list
23
+ @used_interactions = []
24
+ @log_prefix = log_prefix
25
+
26
+ interaction_summaries = interactions.map { |i| "#{request_summary(i.request)} => #{response_summary(i.response)}" }
27
+ log "Initialized HTTPInteractionList with request matchers #{request_matchers.inspect} and #{interactions.size} interaction(s): { #{interaction_summaries.join(', ')} }", 1
28
+ end
29
+
30
+ 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)
40
+ end
41
+ end
42
+
43
+ def has_interaction_matching?(request)
44
+ !!matching_interaction_index_for(request) ||
45
+ !!matching_used_interaction_for(request) ||
46
+ @parent_list.has_interaction_matching?(request)
47
+ end
48
+
49
+ def has_used_interaction_matching?(request)
50
+ @used_interactions.any? { |i| interaction_matches_request?(request, i) }
51
+ end
52
+
53
+ def remaining_unused_interaction_count
54
+ @interactions.size
55
+ end
56
+
57
+ # Checks if there are no unused interactions left.
58
+ #
59
+ # @raise [VCR::Errors::UnusedHTTPInteractionError] if not all interactions were played back.
60
+ def assert_no_unused_interactions!
61
+ return unless has_unused_interactions?
62
+ logger = Logger.new(nil)
63
+
64
+ descriptions = @interactions.map do |i|
65
+ " - #{logger.request_summary(i.request, @request_matchers)} => #{logger.response_summary(i.response)}"
66
+ end.join("\n")
67
+
68
+ raise Errors::UnusedHTTPInteractionError, "There are unused HTTP interactions left in the cassette:\n#{descriptions}"
69
+ end
70
+
71
+ private
72
+
73
+ # @return [Boolean] Whether or not there are unused interactions left in the list.
74
+ def has_unused_interactions?
75
+ @interactions.size > 0
76
+ end
77
+
78
+ def request_summary(request)
79
+ super(request, @request_matchers)
80
+ end
81
+
82
+ def matching_interaction_index_for(request)
83
+ @interactions.index { |i| interaction_matches_request?(request, i) }
84
+ end
85
+
86
+ def matching_used_interaction_for(request)
87
+ return nil unless @allow_playback_repeats
88
+ @used_interactions.find { |i| interaction_matches_request?(request, i) }
89
+ end
90
+
91
+ def interaction_matches_request?(request, interaction)
92
+ log "Checking if #{request_summary(request)} matches #{request_summary(interaction.request)} using #{@request_matchers.inspect}", 1
93
+ @request_matchers.all? do |matcher_name|
94
+ matcher = VCR.request_matchers[matcher_name]
95
+ matcher.matches?(request, interaction.request).tap do |matched|
96
+ matched = matched ? 'matched' : 'did not match'
97
+ log "#{matcher_name} (#{matched}): current request #{request_summary(request)} vs #{request_summary(interaction.request)}", 2
98
+ end
99
+ end
100
+ end
101
+
102
+ def log_prefix
103
+ @log_prefix
104
+ end
105
+ end
106
+ end
107
+ end
108
+
@@ -0,0 +1,118 @@
1
+ require 'vcr'
2
+
3
+ module VCR
4
+ class Cassette
5
+ # @private
6
+ class Migrator
7
+ def initialize(dir, out = $stdout)
8
+ @dir, @out = dir, out
9
+ @yaml_load_errors = yaml_load_errors
10
+ end
11
+
12
+ def migrate!
13
+ @out.puts "Migrating VCR cassettes in #{@dir}..."
14
+ Dir["#{@dir}/**/*.yml"].each do |cassette|
15
+ migrate_cassette(cassette)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def migrate_cassette(cassette)
22
+ unless http_interactions = load_yaml(cassette)
23
+ @out.puts " - Ignored #{relative_casssette_name(cassette)} since it could not be parsed as YAML (does it have some ERB?)"
24
+ return
25
+ end
26
+
27
+ unless valid_vcr_1_cassette?(http_interactions)
28
+ @out.puts " - Ignored #{relative_casssette_name(cassette)} since it does not appear to be a valid VCR 1.x cassette"
29
+ return
30
+ end
31
+
32
+ http_interactions.map! do |interaction|
33
+ interaction.response.adapter_metadata = {}
34
+ interaction.recorded_at = File.mtime(cassette)
35
+ remove_unnecessary_standard_port(interaction)
36
+ denormalize_http_header_keys(interaction.request)
37
+ denormalize_http_header_keys(interaction.response)
38
+ normalize_body(interaction.request)
39
+ normalize_body(interaction.response)
40
+ interaction.to_hash
41
+ end
42
+
43
+ hash = {
44
+ "http_interactions" => http_interactions,
45
+ "recorded_with" => "VCR #{VCR.version}"
46
+ }
47
+
48
+ def hash.each
49
+ yield 'http_interactions', self['http_interactions']
50
+ yield 'recorded_with', self['recorded_with']
51
+ end
52
+
53
+ File.open(cassette, 'w') { |f| f.write ::YAML.dump(hash) }
54
+ @out.puts " - Migrated #{relative_casssette_name(cassette)}"
55
+ end
56
+
57
+ def load_yaml(cassette)
58
+ ::YAML.load_file(cassette)
59
+ rescue *@yaml_load_errors
60
+ return nil
61
+ end
62
+
63
+ def yaml_load_errors
64
+ [ArgumentError].tap do |errors|
65
+ errors << Psych::SyntaxError if defined?(Psych::SyntaxError)
66
+ end
67
+ end
68
+
69
+ def relative_casssette_name(cassette)
70
+ cassette.gsub(%r|\A#{Regexp.escape(@dir)}/?|, '')
71
+ end
72
+
73
+ def valid_vcr_1_cassette?(content)
74
+ content.is_a?(Array) &&
75
+ content.map(&:class).uniq == [HTTPInteraction]
76
+ end
77
+
78
+ def remove_unnecessary_standard_port(interaction)
79
+ uri = VCR.configuration.uri_parser.parse(interaction.request.uri)
80
+ if uri.scheme == 'http' && uri.port == 80 ||
81
+ uri.scheme == 'https' && uri.port == 443
82
+ uri.port = nil
83
+ interaction.request.uri = uri.to_s
84
+ end
85
+ rescue URI::InvalidURIError
86
+ # ignore this URI.
87
+ # This can occur when the user uses the filter_sensitive_data option
88
+ # to put a substitution string in their URI
89
+ end
90
+
91
+ def denormalize_http_header_keys(object)
92
+ object.headers = {}.tap do |denormalized|
93
+ object.headers.each do |k, v|
94
+ denormalized[denormalize_header_key(k)] = v
95
+ end if object.headers
96
+ end
97
+ end
98
+
99
+ def denormalize_header_key(key)
100
+ key.split('-'). # 'user-agent' => %w(user agent)
101
+ each { |w| w.capitalize! }. # => %w(User Agent)
102
+ join('-')
103
+ end
104
+
105
+ EMPTY_STRING = if String.method_defined?(:force_encoding)
106
+ ''.force_encoding("US-ASCII")
107
+ else
108
+ ''
109
+ end
110
+
111
+ def normalize_body(object)
112
+ object.body = EMPTY_STRING if object.body.nil?
113
+ end
114
+
115
+ end
116
+ end
117
+ end
118
+
@@ -0,0 +1,42 @@
1
+ module VCR
2
+ class Cassette
3
+ # Keeps track of the cassette persisters in a hash-like object.
4
+ class Persisters
5
+ autoload :FileSystem, 'vcr/cassette/persisters/file_system'
6
+
7
+ # @private
8
+ def initialize
9
+ @persisters = {}
10
+ end
11
+
12
+ # Gets the named persister.
13
+ #
14
+ # @param name [Symbol] the name of the persister
15
+ # @return the named persister
16
+ # @raise [ArgumentError] if there is not a persister for the given name
17
+ def [](name)
18
+ @persisters.fetch(name) do |_|
19
+ @persisters[name] = case name
20
+ when :file_system then FileSystem
21
+ else raise ArgumentError, "The requested VCR cassette persister " +
22
+ "(#{name.inspect}) is not registered."
23
+ end
24
+ end
25
+ end
26
+
27
+ # Registers a persister.
28
+ #
29
+ # @param name [Symbol] the name of the persister
30
+ # @param value [#[], #[]=] the persister object. It must implement `[]` and `[]=`.
31
+ def []=(name, value)
32
+ if @persisters.has_key?(name)
33
+ warn "WARNING: There is already a VCR cassette persister " +
34
+ "registered for #{name.inspect}. Overriding it."
35
+ end
36
+
37
+ @persisters[name] = value
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,64 @@
1
+ require 'fileutils'
2
+
3
+ module VCR
4
+ class Cassette
5
+ class Persisters
6
+ # The only built-in cassette persister. Persists cassettes to the file system.
7
+ module FileSystem
8
+ extend self
9
+
10
+ # @private
11
+ attr_reader :storage_location
12
+
13
+ # @private
14
+ def storage_location=(dir)
15
+ FileUtils.mkdir_p(dir) if dir
16
+ @storage_location = dir ? absolute_path_for(dir) : nil
17
+ end
18
+
19
+ # Gets the cassette for the given storage key (file name).
20
+ #
21
+ # @param [String] file_name the file name
22
+ # @return [String] the cassette content
23
+ def [](file_name)
24
+ path = absolute_path_to_file(file_name)
25
+ return nil unless File.exist?(path)
26
+ File.read(path)
27
+ end
28
+
29
+ # Sets the cassette for the given storage key (file name).
30
+ #
31
+ # @param [String] file_name the file name
32
+ # @param [String] content the content to store
33
+ def []=(file_name, content)
34
+ path = absolute_path_to_file(file_name)
35
+ directory = File.dirname(path)
36
+ FileUtils.mkdir_p(directory) unless File.exist?(directory)
37
+ File.open(path, 'w') { |f| f.write(content) }
38
+ end
39
+
40
+ # @private
41
+ def absolute_path_to_file(file_name)
42
+ return nil unless storage_location
43
+ File.join(storage_location, sanitized_file_name_from(file_name))
44
+ end
45
+
46
+ private
47
+
48
+ def absolute_path_for(path)
49
+ Dir.chdir(path) { Dir.pwd }
50
+ end
51
+
52
+ def sanitized_file_name_from(file_name)
53
+ parts = file_name.to_s.split('.')
54
+
55
+ if parts.size > 1 && !parts.last.include?(File::SEPARATOR)
56
+ file_extension = '.' + parts.pop
57
+ end
58
+
59
+ parts.join('.').gsub(/[^\w\-\/]+/, '_') + file_extension.to_s
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,57 @@
1
+ module VCR
2
+ class Cassette
3
+ # Keeps track of the cassette serializers in a hash-like object.
4
+ class Serializers
5
+ autoload :YAML, 'vcr/cassette/serializers/yaml'
6
+ autoload :Syck, 'vcr/cassette/serializers/syck'
7
+ autoload :Psych, 'vcr/cassette/serializers/psych'
8
+ autoload :JSON, 'vcr/cassette/serializers/json'
9
+
10
+ # @private
11
+ def initialize
12
+ @serializers = {}
13
+ end
14
+
15
+ # Gets the named serializer.
16
+ #
17
+ # @param name [Symbol] the name of the serializer
18
+ # @return the named serializer
19
+ # @raise [ArgumentError] if there is not a serializer for the given name
20
+ def [](name)
21
+ @serializers.fetch(name) do |_|
22
+ @serializers[name] = case name
23
+ when :yaml then YAML
24
+ when :syck then Syck
25
+ when :psych then Psych
26
+ when :json then JSON
27
+ else raise ArgumentError.new("The requested VCR cassette serializer (#{name.inspect}) is not registered.")
28
+ end
29
+ end
30
+ end
31
+
32
+ # Registers a serializer.
33
+ #
34
+ # @param name [Symbol] the name of the serializer
35
+ # @param value [#file_extension, #serialize, #deserialize] the serializer object. It must implement
36
+ # `file_extension()`, `serialize(Hash)` and `deserialize(String)`.
37
+ def []=(name, value)
38
+ if @serializers.has_key?(name)
39
+ warn "WARNING: There is already a VCR cassette serializer registered for #{name.inspect}. Overriding it."
40
+ end
41
+
42
+ @serializers[name] = value
43
+ end
44
+ end
45
+
46
+ # @private
47
+ module EncodingErrorHandling
48
+ def handle_encoding_errors
49
+ yield
50
+ rescue *self::ENCODING_ERRORS => e
51
+ e.message << "\nNote: Using VCR's `:preserve_exact_body_bytes` option may help prevent this error in the future."
52
+ raise
53
+ end
54
+ end
55
+ end
56
+ end
57
+