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,109 @@
1
+ module VCR
2
+ # @deprecated Use #configure instead.
3
+ # @see #configure
4
+ def config
5
+ warn "WARNING: `VCR.config` is deprecated. Use VCR.configure instead."
6
+ configure { |c| yield c }
7
+ end
8
+
9
+ # @private
10
+ def self.const_missing(const)
11
+ return super unless const == :Config
12
+ warn "WARNING: `VCR::Config` is deprecated. Use VCR.configuration instead."
13
+ configuration
14
+ end
15
+
16
+ # @private
17
+ def Cassette.const_missing(const)
18
+ return super unless const == :MissingERBVariableError
19
+ warn "WARNING: `VCR::Cassette::MissingERBVariableError` is deprecated. Use `VCR::Errors::MissingERBVariableError` instead."
20
+ Errors::MissingERBVariableError
21
+ end
22
+
23
+ class Configuration
24
+ # @deprecated Use #hook_into instead.
25
+ # @see #hook_into
26
+ def stub_with(*adapters)
27
+ warn "WARNING: `VCR.configure { |c| c.stub_with ... }` is deprecated. Use `VCR.configure { |c| c.hook_into ... }` instead."
28
+ hook_into(*adapters)
29
+ end
30
+ end
31
+
32
+ # @private
33
+ module Deprecations
34
+ module Middleware
35
+ # @private
36
+ module Faraday
37
+ def initialize(*args)
38
+ if block_given?
39
+ Kernel.warn "WARNING: Passing a block to `VCR::Middleware::Faraday` is deprecated. \n" +
40
+ "As of VCR 2.0, you need to wrap faraday requests in VCR.use_cassette, just like with any other library hook."
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ module RSpec
48
+ # Contains macro methods to assist with VCR usage. These methods are
49
+ # intended to be used directly in an RSpec example group. To make these
50
+ # available in your RSpec example groups, extend the module in an individual
51
+ # example group, or configure RSpec to extend the module in all example groups.
52
+ #
53
+ # @example
54
+ # RSpec.configure do |c|
55
+ # c.extend VCR::RSpec::Macros
56
+ # end
57
+ #
58
+ module Macros
59
+ def self.extended(base)
60
+ Kernel.warn "WARNING: VCR::RSpec::Macros is deprecated. Use RSpec metadata options instead `:vcr => vcr_options`"
61
+ end
62
+
63
+ # Sets up a `before` and `after` hook that will insert and eject a
64
+ # cassette, respectively.
65
+ #
66
+ # @example
67
+ # describe "Some API Client" do
68
+ # use_vcr_cassette "some_api", :record => :new_episodes
69
+ # end
70
+ #
71
+ # @param [(optional) String] name the cassette name; it will be inferred by the example
72
+ # group descriptions if not given.
73
+ # @param [(optional) Hash] options the cassette options
74
+ # @deprecated Use RSpec metadata options
75
+ def use_vcr_cassette(*args)
76
+ options = args.last.is_a?(Hash) ? args.pop : {}
77
+ name = args.first || infer_cassette_name
78
+
79
+ before(:each) do
80
+ VCR.insert_cassette(name, options)
81
+ end
82
+
83
+ after(:each) do
84
+ VCR.eject_cassette
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def infer_cassette_name
91
+ # RSpec 1 exposes #description_parts; use that if its available
92
+ return description_parts.join("/") if respond_to?(:description_parts)
93
+
94
+ # Otherwise use RSpec 2/3 metadata...
95
+ group_descriptions = []
96
+ klass = self
97
+
98
+ while klass.respond_to?(:metadata) && klass.metadata
99
+ group_descriptions << klass.metadata[:description] ||
100
+ klass.metadata[:example_group][:description]
101
+ klass = klass.superclass
102
+ end
103
+
104
+ group_descriptions.compact.reverse.join('/')
105
+ end
106
+ end
107
+ end
108
+ end
109
+
@@ -0,0 +1,266 @@
1
+ module VCR
2
+ # Namespace for VCR errors.
3
+ module Errors
4
+ # Base class for all VCR errors.
5
+ class Error < StandardError; end
6
+
7
+ # Error raised when VCR is turned off while a cassette is in use.
8
+ # @see VCR#turn_off!
9
+ # @see VCR#turned_off
10
+ class CassetteInUseError < Error; end
11
+
12
+ # Error raised when a VCR cassette is inserted while VCR is turned off.
13
+ # @see VCR#insert_cassette
14
+ # @see VCR#use_cassette
15
+ class TurnedOffError < Error; end
16
+
17
+ # Error raised when an cassette ERB template is rendered and a
18
+ # variable is missing.
19
+ # @see VCR#insert_cassette
20
+ # @see VCR#use_cassette
21
+ class MissingERBVariableError < Error; end
22
+
23
+ # Error raised when the version of one of the libraries that VCR hooks into
24
+ # is too low for VCR to support.
25
+ # @see VCR::Configuration#hook_into
26
+ class LibraryVersionTooLowError < Error; end
27
+
28
+ # Error raised when a request matcher is requested that is not registered.
29
+ class UnregisteredMatcherError < Error; end
30
+
31
+ # Error raised when a VCR 1.x cassette is used with VCR 2.
32
+ class InvalidCassetteFormatError < Error; end
33
+
34
+ # Error raised when an `around_http_request` hook is used improperly.
35
+ # @see VCR::Configuration#around_http_request
36
+ class AroundHTTPRequestHookError < Error; end
37
+
38
+ # Error raised when you attempt to use a VCR feature that is not
39
+ # supported on your ruby interpreter.
40
+ # @see VCR::Configuration#around_http_request
41
+ class NotSupportedError < Error; end
42
+
43
+ # Error raised when you ask VCR to decode a compressed response
44
+ # body but the content encoding isn't one of the known ones.
45
+ # @see VCR::Response#decompress
46
+ class UnknownContentEncodingError < Error; end
47
+
48
+ # Error raised when you eject a cassette before all previously
49
+ # recorded HTTP interactions are played back.
50
+ # @note Only applicable when :allow_episode_skipping is false.
51
+ # @see VCR::HTTPInteractionList#assert_no_unused_interactions!
52
+ class UnusedHTTPInteractionError < Error; end
53
+
54
+ # Error raised when an HTTP request is made that VCR is unable to handle.
55
+ # @note VCR will raise this to force you to do something about the
56
+ # HTTP request. The idea is that you want to handle _every_ HTTP
57
+ # request in your test suite. The error message will give you
58
+ # suggestions for how to deal with the request.
59
+ class UnhandledHTTPRequestError < Error
60
+ # The HTTP request.
61
+ attr_reader :request
62
+
63
+ # Constructs the error.
64
+ #
65
+ # @param [VCR::Request] request the unhandled request.
66
+ def initialize(request)
67
+ @request = request
68
+ super construct_message
69
+ end
70
+
71
+ private
72
+
73
+ def relish_version_slug
74
+ @relish_version_slug ||= VCR.version.gsub(/\W/, '-')
75
+ end
76
+
77
+ def construct_message
78
+ ["", "", "=" * 80,
79
+ "An HTTP request has been made that VCR does not know how to handle:",
80
+ "#{request_description}\n",
81
+ cassette_description,
82
+ formatted_suggestions,
83
+ "=" * 80, "", ""].join("\n")
84
+ end
85
+
86
+ def request_description
87
+ lines = []
88
+
89
+ lines << " #{request.method.to_s.upcase} #{request.uri}"
90
+
91
+ if match_request_on_body?
92
+ lines << " Body: #{request.body}"
93
+ end
94
+
95
+ lines.join("\n")
96
+ end
97
+
98
+ def match_request_on_body?
99
+ current_matchers.include?(:body)
100
+ end
101
+
102
+ def current_matchers
103
+ if VCR.current_cassette
104
+ VCR.current_cassette.match_requests_on
105
+ else
106
+ VCR.configuration.default_cassette_options[:match_requests_on]
107
+ end
108
+ end
109
+
110
+ def cassette_description
111
+ if cassette = VCR.current_cassette
112
+ ["VCR is currently using the following cassette:",
113
+ " - #{cassette.file}",
114
+ " - :record => #{cassette.record_mode.inspect}",
115
+ " - :match_requests_on => #{cassette.match_requests_on.inspect}\n",
116
+ "Under the current configuration VCR can not find a suitable HTTP interaction",
117
+ "to replay and is prevented from recording new requests. There are a few ways",
118
+ "you can deal with this:\n"].join("\n")
119
+ else
120
+ ["There is currently no cassette in use. There are a few ways",
121
+ "you can configure VCR to handle this request:\n"].join("\n")
122
+ end
123
+ end
124
+
125
+ def formatted_suggestions
126
+ formatted_points, formatted_foot_notes = [], []
127
+
128
+ suggestions.each_with_index do |suggestion, index|
129
+ bullet_point, foot_note = suggestion.first, suggestion.last
130
+ formatted_points << format_bullet_point(bullet_point, index)
131
+ formatted_foot_notes << format_foot_note(foot_note, index)
132
+ end
133
+
134
+ [
135
+ formatted_points.join("\n"),
136
+ formatted_foot_notes.join("\n")
137
+ ].join("\n\n")
138
+ end
139
+
140
+ def format_bullet_point(lines, index)
141
+ lines.first.insert(0, " * ")
142
+ lines.last << " [#{index + 1}]."
143
+ lines.join("\n ")
144
+ end
145
+
146
+ def format_foot_note(url, index)
147
+ "[#{index + 1}] #{url % relish_version_slug}"
148
+ end
149
+
150
+ # List of suggestions for how to configure VCR to handle the request.
151
+ ALL_SUGGESTIONS = {
152
+ :use_new_episodes => [
153
+ ["You can use the :new_episodes record mode to allow VCR to",
154
+ "record this new request to the existing cassette"],
155
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/record-modes/new-episodes"
156
+ ],
157
+
158
+ :delete_cassette_for_once => [
159
+ ["The current record mode (:once) does not allow new requests to be recorded",
160
+ "to a previously recorded cassette. You can delete the cassette file and re-run",
161
+ "your tests to allow the cassette to be recorded with this request"],
162
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/record-modes/once"
163
+ ],
164
+
165
+ :deal_with_none => [
166
+ ["The current record mode (:none) does not allow requests to be recorded. You",
167
+ "can temporarily change the record mode to :once, delete the cassette file ",
168
+ "and re-run your tests to allow the cassette to be recorded with this request"],
169
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/record-modes/none"
170
+ ],
171
+
172
+ :use_a_cassette => [
173
+ ["If you want VCR to record this request and play it back during future test",
174
+ "runs, you should wrap your test (or this portion of your test) in a",
175
+ "`VCR.use_cassette` block"],
176
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/getting-started"
177
+ ],
178
+
179
+ :allow_http_connections_when_no_cassette => [
180
+ ["If you only want VCR to handle requests made while a cassette is in use,",
181
+ "configure `allow_http_connections_when_no_cassette = true`. VCR will",
182
+ "ignore this request since it is made when there is no cassette"],
183
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/configuration/allow-http-connections-when-no-cassette"
184
+ ],
185
+
186
+ :ignore_request => [
187
+ ["If you want VCR to ignore this request (and others like it), you can",
188
+ "set an `ignore_request` callback"],
189
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/configuration/ignore-request"
190
+ ],
191
+
192
+ :allow_playback_repeats => [
193
+ ["The cassette contains an HTTP interaction that matches this request,",
194
+ "but it has already been played back. If you wish to allow a single HTTP",
195
+ "interaction to be played back multiple times, set the `:allow_playback_repeats`",
196
+ "cassette option"],
197
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/request-matching/playback-repeats"
198
+ ],
199
+
200
+ :match_requests_on => [
201
+ ["The cassette contains %s not been",
202
+ "played back. If your request is non-deterministic, you may need to",
203
+ "change your :match_requests_on cassette option to be more lenient",
204
+ "or use a custom request matcher to allow it to match"],
205
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/request-matching"
206
+ ],
207
+
208
+ :try_debug_logger => [
209
+ ["If you're surprised VCR is raising this error",
210
+ "and want insight about how VCR attempted to handle the request,",
211
+ "you can use the debug_logger configuration option to log more details"],
212
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/configuration/debug-logging"
213
+ ]
214
+ }
215
+
216
+ def suggestion_for(key)
217
+ bullet_point_lines, url = ALL_SUGGESTIONS[key]
218
+ bullet_point_lines = bullet_point_lines.map(&:dup)
219
+ url = url.dup
220
+ [bullet_point_lines, url]
221
+ end
222
+
223
+ def suggestions
224
+ return no_cassette_suggestions unless cassette = VCR.current_cassette
225
+
226
+ [:try_debug_logger, :use_new_episodes, :ignore_request].tap do |suggestions|
227
+ suggestions.push(*record_mode_suggestion)
228
+ suggestions << :allow_playback_repeats if cassette.http_interactions.has_used_interaction_matching?(request)
229
+ suggestions.map! { |k| suggestion_for(k) }
230
+ suggestions.push(*match_requests_on_suggestion)
231
+ end
232
+ end
233
+
234
+ def no_cassette_suggestions
235
+ [:try_debug_logger, :use_a_cassette, :allow_http_connections_when_no_cassette, :ignore_request].map do |key|
236
+ suggestion_for(key)
237
+ end
238
+ end
239
+
240
+ def record_mode_suggestion
241
+ case VCR.current_cassette.record_mode
242
+ when :none then [:deal_with_none]
243
+ when :once then [:delete_cassette_for_once]
244
+ else []
245
+ end
246
+ end
247
+
248
+ def match_requests_on_suggestion
249
+ num_remaining_interactions = VCR.current_cassette.http_interactions.remaining_unused_interaction_count
250
+ return [] if num_remaining_interactions.zero?
251
+
252
+ interaction_description = if num_remaining_interactions == 1
253
+ "1 HTTP interaction that has"
254
+ else
255
+ "#{num_remaining_interactions} HTTP interactions that have"
256
+ end
257
+
258
+ description_lines, link = suggestion_for(:match_requests_on)
259
+ description_lines[0] = description_lines[0] % interaction_description
260
+ [[description_lines, link]]
261
+ end
262
+
263
+ end
264
+ end
265
+ end
266
+
@@ -0,0 +1,36 @@
1
+ module VCR
2
+ # @private
3
+ module Net
4
+ # A Net::HTTP response that has already been read raises an IOError when #read_body
5
+ # is called with a destination string or block.
6
+ #
7
+ # This causes a problem when VCR records a response--it reads the body before yielding
8
+ # the response, and if the code that is consuming the HTTP requests uses #read_body, it
9
+ # can cause an error.
10
+ #
11
+ # This is a bit of a hack, but it allows a Net::HTTP response to be "re-read"
12
+ # after it has aleady been read. This attemps to preserve the behavior of
13
+ # #read_body, acting just as if it had never been read.
14
+ # @private
15
+ module HTTPResponse
16
+ def self.extended(response)
17
+ response.instance_variable_set(:@__read_body_previously_called, false)
18
+ end
19
+
20
+ def read_body(dest = nil, &block)
21
+ return super if @__read_body_previously_called
22
+ return @body if dest.nil? && block.nil?
23
+ raise ArgumentError.new("both arg and block given for HTTP method") if dest && block
24
+
25
+ if @body
26
+ dest ||= ::Net::ReadAdapter.new(block)
27
+ dest << @body
28
+ @body = dest
29
+ end
30
+ ensure
31
+ # allow subsequent calls to #read_body to proceed as normal, without our hack...
32
+ @__read_body_previously_called = true
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ module VCR
2
+ # @private
3
+ class LibraryHooks
4
+ attr_accessor :exclusive_hook
5
+
6
+ def disabled?(hook)
7
+ ![nil, hook].include?(exclusive_hook)
8
+ end
9
+
10
+ def exclusively_enabled(hook)
11
+ self.exclusive_hook = hook
12
+ yield
13
+ ensure
14
+ self.exclusive_hook = nil
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,27 @@
1
+ require 'vcr/middleware/excon'
2
+
3
+ module VCR
4
+ class LibraryHooks
5
+ module Excon
6
+ # @private
7
+ def self.configure_middleware
8
+ middlewares = ::Excon.defaults[:middlewares]
9
+
10
+ middlewares << VCR::Middleware::Excon::Request
11
+ response_parser_index = middlewares.index(::Excon::Middleware::ResponseParser)
12
+ middlewares.insert(response_parser_index + 1, VCR::Middleware::Excon::Response)
13
+ end
14
+
15
+ configure_middleware
16
+ end
17
+ end
18
+ end
19
+
20
+ VCR.configuration.after_library_hooks_loaded do
21
+ # ensure WebMock's Excon adapter does not conflict with us here
22
+ # (i.e. to double record requests or whatever).
23
+ if defined?(WebMock::HttpLibAdapters::ExconAdapter)
24
+ WebMock::HttpLibAdapters::ExconAdapter.disable!
25
+ end
26
+ end
27
+