mustwin-vcr 2.9.3

Sign up to get free protection for your applications and to get access to all the features.
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,84 @@
1
+ Feature: query_parser
2
+
3
+ By default, VCR will parse query strings using `CGI.parse` from the Ruby
4
+ standard library. This may not be the most optimal or performant library
5
+ available. You can set the `query_parser` configuration option to use a
6
+ different parser (such as `Rack::Utils.method(:parse_query)`) to decode,
7
+ normalize, and/or provide a comparison object for query strings.
8
+
9
+ The configured query parser needs to expose a `.call` method that returns an
10
+ object which is comparable. This instance needs to implement the following
11
+ API:
12
+
13
+ * `#==` => boolean
14
+
15
+ Background:
16
+ Given a file named "cassettes/example.yml" with:
17
+ """
18
+ ---
19
+ http_interactions:
20
+ - request:
21
+ method: get
22
+ uri: http://url.example.com/?bravo=2&alpha=1
23
+ body:
24
+ encoding: UTF-8
25
+ string: ""
26
+ headers: {}
27
+ response:
28
+ status:
29
+ code: 200
30
+ message: OK
31
+ headers:
32
+ Content-Length:
33
+ - "5"
34
+ body:
35
+ encoding: UTF-8
36
+ string: Hello
37
+ http_version: "1.1"
38
+ recorded_at: Tue, 25 Sep 2012 04:58:44 GMT
39
+ recorded_with: VCR 2.2.5
40
+ """
41
+
42
+ Scenario: the VCR query parser gets its value from `query_parser`
43
+ Given a file named "query_parser.rb" with:
44
+ """ruby
45
+ require 'vcr'
46
+ require 'rack'
47
+
48
+ VCR.configure do |c|
49
+ c.query_parser = lambda { |query| raise query.inspect }
50
+ c.default_cassette_options = {:match_requests_on => [:query]}
51
+ c.hook_into :webmock
52
+ c.cassette_library_dir = 'cassettes'
53
+ end
54
+
55
+ uri = URI.parse('http://other-url.example.com/?bravo=2&alpha=1')
56
+ VCR.use_cassette('example') do
57
+ puts Net::HTTP.get_response(uri).body
58
+ end
59
+ """
60
+ When I run `ruby query_parser.rb`
61
+ Then it should fail with an error like:
62
+ """
63
+ "alpha=1&bravo=2"
64
+ """
65
+
66
+
67
+ Scenario: the `query_parser` defaults to the standard library's `CGI.parse`
68
+ Given a file named "query_parser_default.rb" with:
69
+ """ruby
70
+ require 'vcr'
71
+
72
+ VCR.configure do |c|
73
+ c.hook_into :webmock
74
+ c.default_cassette_options = {:match_requests_on => [:query]}
75
+ c.cassette_library_dir = 'cassettes'
76
+ end
77
+
78
+ uri = URI.parse('http://other-url.example.com/?bravo=2&alpha=1')
79
+ VCR.use_cassette('example') do
80
+ puts Net::HTTP.get_response(uri).body
81
+ end
82
+ """
83
+ When I run `ruby query_parser_default.rb`
84
+ Then it should pass with "Hello"
@@ -0,0 +1,89 @@
1
+ Feature: uri_parser
2
+
3
+ By default, VCR will parse URIs using `URI` from the Ruby standard
4
+ library. There are some URIs seen out in the wild that `URI` cannot
5
+ parse properly. You can set the `uri_parser` configuration option
6
+ to use a different parser (such as `Addressable::URI`) to work with
7
+ these URIs.
8
+
9
+ The configured URI parser needs to expose a `.parse` class method
10
+ that returns an instance of the uri. This uri instance needs to
11
+ implement the following API:
12
+
13
+ * `#scheme` => a string
14
+ * `#host` => a string
15
+ * `#port` => a fixnum
16
+ * `#path` => a string
17
+ * `#query` => a string
18
+ * `#to_s` => a string
19
+ * `#port=`
20
+ * `#query=`
21
+ * `#==` => boolean
22
+
23
+ Background:
24
+ Given a file named "cassettes/example.yml" with:
25
+ """
26
+ ---
27
+ http_interactions:
28
+ - request:
29
+ method: get
30
+ uri: http://bad_url.example.com/
31
+ body:
32
+ encoding: UTF-8
33
+ string: ""
34
+ headers: {}
35
+ response:
36
+ status:
37
+ code: 200
38
+ message: OK
39
+ headers:
40
+ Content-Length:
41
+ - "5"
42
+ body:
43
+ encoding: UTF-8
44
+ string: Hello
45
+ http_version: "1.1"
46
+ recorded_at: Tue, 25 Sep 2012 04:58:44 GMT
47
+ recorded_with: VCR 2.2.5
48
+ """
49
+
50
+ Scenario: the VCR uri parser gets its value from `uri_parser`
51
+ Given a file named "uri_parser.rb" with:
52
+ """ruby
53
+ require 'vcr'
54
+ require 'addressable/uri'
55
+
56
+ VCR.configure do |c|
57
+ c.uri_parser = Addressable::URI
58
+ c.hook_into :webmock
59
+ c.cassette_library_dir = 'cassettes'
60
+ end
61
+
62
+ VCR.use_cassette('example') do
63
+ puts Net::HTTP.get_response('bad_url.example.com', '/').body
64
+ end
65
+ """
66
+ When I run `ruby uri_parser.rb`
67
+ Then it should pass with "Hello"
68
+
69
+ Scenario: the `uri_parser` defaults to the standard library's `URI`
70
+ Given a file named "uri_parser_default.rb" with:
71
+ """ruby
72
+ require 'vcr'
73
+ require 'addressable/uri'
74
+
75
+ VCR.configure do |c|
76
+ c.hook_into :webmock
77
+ c.cassette_library_dir = 'cassettes'
78
+ end
79
+
80
+ VCR.use_cassette('example') do
81
+ puts Net::HTTP.get_response('bad_url.example.com', '/').body
82
+ end
83
+ """
84
+ When I run `ruby uri_parser_default.rb`
85
+ Then it should fail with an error like:
86
+ """
87
+ URI::InvalidURIError
88
+ """
89
+
@@ -0,0 +1,82 @@
1
+ ### Install it
2
+
3
+ [sudo] gem install vcr
4
+ [sudo] gem install webmock
5
+
6
+ ### Configure it
7
+
8
+ Create a file named `vcr_setup.rb` with content like:
9
+
10
+ require 'vcr'
11
+
12
+ VCR.configure do |c|
13
+ c.cassette_library_dir = 'vcr_cassettes'
14
+ c.hook_into :webmock
15
+ end
16
+
17
+ Ensure this file is required by your test suite before any
18
+ of the tests are run.
19
+
20
+ ### Use it
21
+
22
+ Run your tests. Any tests that make HTTP requests using Net::HTTP will
23
+ raise errors like:
24
+
25
+ ================================================================================
26
+ An HTTP request has been made that VCR does not know how to handle:
27
+ GET http://example.com/
28
+
29
+ There is currently no cassette in use. There are a few ways
30
+ you can configure VCR to handle this request:
31
+
32
+ * If you want VCR to record this request and play it back during future test
33
+ runs, you should wrap your test (or this portion of your test) in a
34
+ `VCR.use_cassette` block [1].
35
+ * If you only want VCR to handle requests made while a cassette is in use,
36
+ configure `allow_http_connections_when_no_cassette = true`. VCR will
37
+ ignore this request since it is made when there is no cassette [2].
38
+ * If you want VCR to ignore this request (and others like it), you can
39
+ set an `ignore_request` callback [3].
40
+
41
+ [1] https://www.relishapp.com/myronmarston/vcr/v/2-0-0/docs/getting-started
42
+ [2] https://www.relishapp.com/myronmarston/vcr/v/2-0-0/docs/configuration/allow-http-connections-when-no-cassette
43
+ [3] https://www.relishapp.com/myronmarston/vcr/v/2-0-0/docs/configuration/ignore-request
44
+ ================================================================================
45
+
46
+ Find one of these tests (preferably one that uses the same HTTP method and
47
+ request URL every time--if not, you'll have to configure the request matcher).
48
+ Wrap the body of it (or at least the code that makes the HTTP request) in a
49
+ `VCR.use_cassette` block:
50
+
51
+ VCR.use_cassette('whatever cassette name you want') do
52
+ # the body of the test would go here...
53
+ end
54
+
55
+ Run this test. It will record the HTTP request to disk as a cassette (a
56
+ test fixture), with content like:
57
+
58
+ ---
59
+ http_interactions:
60
+ - request:
61
+ method: get
62
+ uri: http://example.com/
63
+ body: ''
64
+ headers: {}
65
+ response:
66
+ status:
67
+ code: 200
68
+ message: OK
69
+ headers:
70
+ Content-Type:
71
+ - text/html;charset=utf-8
72
+ Content-Length:
73
+ - '26'
74
+ body: This is the response body
75
+ http_version: '1.1'
76
+ recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
77
+ recorded_with: VCR 2.0.0
78
+
79
+ Disconnect your computer from the internet. Run the test again.
80
+ It should pass since VCR is automatically replaying the recorded
81
+ response when the request is made.
82
+
@@ -0,0 +1,58 @@
1
+ Feature: after_http_request hook
2
+
3
+ The `after_http_request` hook gets called with each request and response
4
+ just after a request has completed. It can be used for many things:
5
+
6
+ * globally logging requests and responses
7
+ * ejecting the current cassette (i.e. if you inserted it in a
8
+ `before_http_request` hook)
9
+
10
+ You can also pass one or more "filters" to `after_http_request`, to make
11
+ the hook only be called for some requests. Any object that responds to `#to_proc`
12
+ can be a filter. Here are some simple examples:
13
+
14
+ * `:real?` -- only real requests
15
+ * `:stubbed?` -- only stubbed requests
16
+ * `:ignored?` -- only ignored requests
17
+ * `:recordable?` -- only requests that are being recorded
18
+ * `lambda { |req| URI(req.uri).host == 'amazon.com' }` -- only requests to amazon.com.
19
+
20
+ Scenario Outline: log all requests and responses using after_http_request hook
21
+ Given a file named "after_http_request.rb" with:
22
+ """ruby
23
+ include_http_adapter_for("<http_lib>")
24
+
25
+ $server = start_sinatra_app do
26
+ get('/foo') { "Hello World (foo)" }
27
+ get('/bar') { "Hello World (bar)" }
28
+ end
29
+
30
+ require 'vcr'
31
+
32
+ VCR.configure do |c|
33
+ <configuration>
34
+ c.cassette_library_dir = 'cassettes'
35
+ c.ignore_localhost = true
36
+ c.after_http_request(:ignored?, lambda { |req| req.uri =~ /foo/ }) do |request, response|
37
+ uri = request.uri.sub(/:\d+/, ":7777")
38
+ puts "Response for #{request.method} #{uri}: #{response.body}"
39
+ end
40
+ end
41
+
42
+ make_http_request(:get, "http://localhost:#{$server.port}/foo")
43
+ make_http_request(:get, "http://localhost:#{$server.port}/bar")
44
+ """
45
+ When I run `ruby after_http_request.rb`
46
+ Then the output should contain "Response for get http://localhost:7777/foo: Hello World (foo)"
47
+ But the output should not contain "bar"
48
+
49
+ Examples:
50
+ | configuration | http_lib |
51
+ | c.hook_into :fakeweb | net/http |
52
+ | c.hook_into :webmock | net/http |
53
+ | c.hook_into :webmock | httpclient |
54
+ | c.hook_into :webmock | curb |
55
+ | c.hook_into :typhoeus | typhoeus |
56
+ | c.hook_into :excon | excon |
57
+ | c.hook_into :faraday | faraday (w/ net_http) |
58
+
@@ -0,0 +1,57 @@
1
+ @exclude-18 @exclude-1.9.3p327
2
+ Feature: around_http_request hook
3
+
4
+ The `around_http_request` hook wraps each HTTP request. It can be used
5
+ rather than separate `before_http_request` and `after_http_request` hooks
6
+ to simplify wrapping/transactional logic (such as using a VCR cassette).
7
+
8
+ In your block, call `#proceed` on the yielded request to cause it to continue.
9
+ Alternately, you can treat the request as a proc and pass it on to a method that
10
+ expects a block by prefixing it with an ampersand (`&request`).
11
+
12
+ Note that `around_http_request` will not work on Ruby 1.8. It uses a fiber
13
+ under the covers and thus is only available on interpreters that support fibers.
14
+ On 1.8, you can use separate `before_http_request` and `after_http_request` hooks.
15
+
16
+ Scenario Outline: globally handle requests using an around_http_request hook
17
+ Given a file named "globally_handle_requests.rb" with:
18
+ """ruby
19
+ include_http_adapter_for("<http_lib>")
20
+
21
+ request_count = 0
22
+ $server = start_sinatra_app do
23
+ get('/') { "Response #{request_count += 1 }" }
24
+ end
25
+
26
+ require 'vcr'
27
+
28
+ VCR.configure do |c|
29
+ <configuration>
30
+ c.cassette_library_dir = 'cassettes'
31
+ c.default_cassette_options = { :serialize_with => :syck }
32
+ c.around_http_request do |request|
33
+ VCR.use_cassette('global', :record => :new_episodes, &request)
34
+ end
35
+ end
36
+
37
+ puts "Response for request 1: " + response_body_for(:get, "http://localhost:#{$server.port}/")
38
+ puts "Response for request 2: " + response_body_for(:get, "http://localhost:#{$server.port}/")
39
+ """
40
+ When I run `ruby globally_handle_requests.rb`
41
+ Then it should pass with:
42
+ """
43
+ Response for request 1: Response 1
44
+ Response for request 2: Response 1
45
+ """
46
+ And the file "cassettes/global.yml" should contain "Response 1"
47
+
48
+ Examples:
49
+ | configuration | http_lib |
50
+ | c.hook_into :fakeweb | net/http |
51
+ | c.hook_into :webmock | net/http |
52
+ | c.hook_into :webmock | httpclient |
53
+ | c.hook_into :webmock | curb |
54
+ | c.hook_into :typhoeus | typhoeus |
55
+ | c.hook_into :excon | excon |
56
+ | c.hook_into :faraday | faraday (w/ net_http) |
57
+
@@ -0,0 +1,63 @@
1
+ Feature: before_http_request hook
2
+
3
+ The `before_http_request` hook gets called with each request
4
+ just before it proceeds. It can be used for many things:
5
+
6
+ * globally logging requests
7
+ * inserting a particular cassette based on the request URI host
8
+ * raising a timeout error
9
+
10
+ You can also pass one or more "filters" to `before_http_request`, to make
11
+ the hook only be called for some requests. Any object that responds to `#to_proc`
12
+ can be a filter. Here are some simple examples:
13
+
14
+ * `:real?` -- only real requests
15
+ * `:stubbed?` -- only stubbed requests
16
+ * `:ignored?` -- only ignored requests
17
+ * `:recordable?` -- only requests that are being recorded
18
+ * `lambda { |r| URI(r.uri).host == 'amazon.com' }` -- only requests to amazon.com.
19
+
20
+ Scenario Outline: log all requests using a before_http_request hook
21
+ Given a file named "before_http_request.rb" with:
22
+ """ruby
23
+ include_http_adapter_for("<http_lib>")
24
+
25
+ if ARGV.include?('--with-server')
26
+ $server = start_sinatra_app do
27
+ get('/') { "Hello World" }
28
+ end
29
+ end
30
+
31
+ require 'vcr'
32
+
33
+ VCR.configure do |c|
34
+ <configuration>
35
+ c.cassette_library_dir = 'cassettes'
36
+ c.before_http_request(:real?) do |request|
37
+ File.open(ARGV.first, 'w') do |f|
38
+ f.write("before real request: #{request.method} #{request.uri}")
39
+ end
40
+ end
41
+ end
42
+
43
+ VCR.use_cassette('hook_example') do
44
+ port = $server ? $server.port : 0
45
+ make_http_request(:get, "http://localhost:#{port}/")
46
+ end
47
+ """
48
+ When I run `ruby before_http_request.rb run1.log --with-server`
49
+ Given that port numbers in "run1.log" are normalized to "7777"
50
+ Then the file "run1.log" should contain "before real request: get http://localhost:7777/"
51
+ When I run `ruby before_http_request.rb run2.log`
52
+ Then the file "run2.log" should not exist
53
+
54
+ Examples:
55
+ | configuration | http_lib |
56
+ | c.hook_into :fakeweb | net/http |
57
+ | c.hook_into :webmock | net/http |
58
+ | c.hook_into :webmock | httpclient |
59
+ | c.hook_into :webmock | curb |
60
+ | c.hook_into :typhoeus | typhoeus |
61
+ | c.hook_into :excon | excon |
62
+ | c.hook_into :faraday | faraday (w/ net_http) |
63
+
@@ -0,0 +1,184 @@
1
+ Feature: before_playback hook
2
+
3
+ The `before_playback` hook is called before a cassette sets up its
4
+ stubs for playback.
5
+
6
+ Your block should accept up to 2 arguments. The first argument will be
7
+ the HTTP interaction that is about to be used for play back. The second
8
+ argument will be the current cassette.
9
+
10
+ You can also call `#ignore!` on the HTTP interaction to prevent VCR
11
+ from playing it back.
12
+
13
+ You can use tags to specify a cassette, otherwise your hook will apply to all cassettes. Consider this code:
14
+
15
+ VCR.configure do |c|
16
+ c.before_playback(:twitter) { ... } # modify the interactions somehow
17
+ end
18
+
19
+ VCR.use_cassette('cassette_1', :tag => :twitter) { ... }
20
+ VCR.use_cassette('cassette_2') { ... }
21
+
22
+ In this example, the hook would apply to the first cassette but not the
23
+ second cassette.
24
+
25
+ Background:
26
+ Given a previously recorded cassette file "cassettes/example.yml" with:
27
+ """
28
+ ---
29
+ http_interactions:
30
+ - request:
31
+ method: get
32
+ uri: http://localhost:7777/
33
+ body:
34
+ encoding: UTF-8
35
+ string: ""
36
+ headers: {}
37
+ response:
38
+ status:
39
+ code: 200
40
+ message: OK
41
+ headers:
42
+ Content-Type:
43
+ - text/html;charset=utf-8
44
+ Content-Length:
45
+ - "20"
46
+ body:
47
+ encoding: UTF-8
48
+ string: previously recorded response
49
+ http_version: "1.1"
50
+ recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
51
+ recorded_with: VCR 2.0.0
52
+ """
53
+
54
+ Scenario: Modify played back response
55
+ Given a file named "before_playback_example.rb" with:
56
+ """ruby
57
+ require 'vcr'
58
+
59
+ VCR.configure do |c|
60
+ c.hook_into :webmock
61
+ c.cassette_library_dir = 'cassettes'
62
+
63
+ c.before_playback do |interaction|
64
+ interaction.response.body = 'response from before_playback'
65
+ end
66
+ end
67
+
68
+ VCR.use_cassette('example') do
69
+ response = Net::HTTP.get_response('localhost', '/', 7777)
70
+ puts "Response: #{response.body}"
71
+ end
72
+ """
73
+ When I run `ruby before_playback_example.rb`
74
+ Then it should pass with "Response: response from before_playback"
75
+
76
+ Scenario: Modify played back response based on the cassette
77
+ Given a file named "before_playback_example.rb" with:
78
+ """ruby
79
+ require 'vcr'
80
+
81
+ VCR.configure do |c|
82
+ c.hook_into :webmock
83
+ c.cassette_library_dir = 'cassettes'
84
+
85
+ c.before_playback do |interaction, cassette|
86
+ interaction.response.body = "response for #{cassette.name} cassette"
87
+ end
88
+ end
89
+
90
+ VCR.use_cassette('example') do
91
+ response = Net::HTTP.get_response('localhost', '/', 7777)
92
+ puts "Response: #{response.body}"
93
+ end
94
+ """
95
+ When I run `ruby before_playback_example.rb`
96
+ Then it should pass with "Response: response for example cassette"
97
+
98
+ Scenario: Prevent playback by ignoring interaction in before_playback hook
99
+ Given a file named "before_playback_ignore.rb" with:
100
+ """ruby
101
+ $server = start_sinatra_app do
102
+ get('/') { "sinatra response" }
103
+ end
104
+
105
+ require 'vcr'
106
+
107
+ VCR.configure do |c|
108
+ c.hook_into :webmock
109
+ c.cassette_library_dir = 'cassettes'
110
+ c.before_playback { |i| i.ignore! }
111
+ end
112
+
113
+ VCR.use_cassette('localhost', :record => :new_episodes, :match_requests_on => [:method, :host, :path]) do
114
+ response = Net::HTTP.get_response('localhost', '/', $server.port)
115
+ puts "Response: #{response.body}"
116
+ end
117
+ """
118
+ When I run `ruby before_playback_ignore.rb`
119
+ Then it should pass with "Response: sinatra response"
120
+
121
+ Scenario: Multiple hooks are run in order
122
+ Given a file named "multiple_hooks.rb" with:
123
+ """ruby
124
+ require 'vcr'
125
+
126
+ VCR.configure do |c|
127
+ c.hook_into :webmock
128
+ c.cassette_library_dir = 'cassettes'
129
+
130
+ c.before_playback { puts "In before_playback hook 1" }
131
+ c.before_playback { puts "In before_playback hook 2" }
132
+ end
133
+
134
+ VCR.use_cassette('example', :record => :new_episodes) do
135
+ response = Net::HTTP.get_response('localhost', '/', 7777)
136
+ puts "Response: #{response.body}"
137
+ end
138
+ """
139
+ When I run `ruby multiple_hooks.rb`
140
+ Then it should pass with:
141
+ """
142
+ In before_playback hook 1
143
+ In before_playback hook 2
144
+ Response: previously recorded response
145
+ """
146
+
147
+ Scenario: Use tagging to apply hooks to only certain cassettes
148
+ Given a file named "tagged_hooks.rb" with:
149
+ """ruby
150
+ require 'vcr'
151
+
152
+ VCR.configure do |c|
153
+ c.hook_into :webmock
154
+ c.cassette_library_dir = 'cassettes'
155
+
156
+ c.before_playback(:tag_2) do |i|
157
+ puts "In before_playback hook for tag_2"
158
+ end
159
+ end
160
+
161
+ [:tag_1, :tag_2, nil].each do |tag|
162
+ puts
163
+ puts "Using tag: #{tag.inspect}"
164
+
165
+ VCR.use_cassette('example', :record => :new_episodes, :tag => tag) do
166
+ response = Net::HTTP.get_response('localhost', '/', 7777)
167
+ puts "Response: #{response.body}"
168
+ end
169
+ end
170
+ """
171
+ When I run `ruby tagged_hooks.rb`
172
+ Then it should pass with:
173
+ """
174
+ Using tag: :tag_1
175
+ Response: previously recorded response
176
+
177
+ Using tag: :tag_2
178
+ In before_playback hook for tag_2
179
+ Response: previously recorded response
180
+
181
+ Using tag: nil
182
+ Response: previously recorded response
183
+ """
184
+