vcr 2.0.0.beta2 → 2.0.0.rc1
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.
- data/.gitignore +1 -0
- data/.travis.yml +0 -2
- data/CHANGELOG.md +22 -1
- data/CONTRIBUTING.md +46 -0
- data/Gemfile +1 -9
- data/README.md +8 -2
- data/Rakefile +12 -1
- data/cucumber.yml +8 -9
- data/features/.nav +10 -4
- data/features/cassettes/format.feature +1 -1
- data/features/cassettes/no_cassette.feature +8 -11
- data/features/configuration/allow_http_connections_when_no_cassette.feature +4 -4
- data/features/configuration/filter_sensitive_data.feature +3 -0
- data/features/configuration/hook_into.feature +4 -8
- data/features/configuration/ignore_request.feature +191 -0
- data/features/getting_started.md +38 -21
- data/features/hooks/after_http_request.feature +44 -0
- data/features/hooks/around_http_request.feature +56 -0
- data/features/hooks/before_http_request.feature +44 -0
- data/features/hooks/before_playback.feature +181 -0
- data/features/hooks/before_record.feature +172 -0
- data/features/middleware/faraday.feature +7 -3
- data/features/record_modes/none.feature +2 -1
- data/features/record_modes/once.feature +2 -1
- data/features/request_matching/body.feature +2 -2
- data/features/request_matching/custom_matcher.feature +2 -2
- data/features/request_matching/headers.feature +2 -2
- data/features/request_matching/host.feature +2 -2
- data/features/request_matching/identical_request_sequence.feature +2 -2
- data/features/request_matching/method.feature +2 -2
- data/features/request_matching/path.feature +2 -2
- data/features/request_matching/playback_repeats.feature +2 -1
- data/features/request_matching/uri.feature +2 -2
- data/features/support/env.rb +21 -12
- data/features/test_frameworks/cucumber.feature +9 -4
- data/features/test_frameworks/{rspec.feature → rspec_macro.feature} +7 -7
- data/features/test_frameworks/rspec_metadata.feature +90 -0
- data/lib/vcr.rb +1 -1
- data/lib/vcr/cassette.rb +3 -3
- data/lib/vcr/cassette/http_interaction_list.rb +13 -9
- data/lib/vcr/cassette/migrator.rb +1 -1
- data/lib/vcr/configuration.rb +37 -0
- data/lib/vcr/errors.rb +172 -6
- data/lib/vcr/library_hooks.rb +4 -6
- data/lib/vcr/library_hooks/excon.rb +23 -11
- data/lib/vcr/library_hooks/fakeweb.rb +85 -24
- data/lib/vcr/library_hooks/faraday.rb +30 -2
- data/lib/vcr/library_hooks/typhoeus.rb +25 -3
- data/lib/vcr/library_hooks/webmock.rb +25 -36
- data/lib/vcr/middleware/faraday.rb +23 -5
- data/lib/vcr/request_handler.rb +12 -1
- data/lib/vcr/request_ignorer.rb +12 -1
- data/lib/vcr/request_matcher_registry.rb +1 -9
- data/lib/vcr/structs.rb +32 -2
- data/lib/vcr/test_frameworks/rspec.rb +28 -0
- data/lib/vcr/util/hooks.rb +12 -4
- data/lib/vcr/util/version_checker.rb +2 -0
- data/lib/vcr/version.rb +1 -1
- data/spec/fixtures/cassette_spec/example.yml +1 -1
- data/spec/fixtures/{fake_example.com_responses.yml → fake_example_responses.yml} +0 -0
- data/spec/monkey_patches.rb +1 -1
- data/spec/spec_helper.rb +3 -1
- data/spec/support/http_library_adapters.rb +4 -3
- data/spec/support/shared_example_groups/hook_into_http_library.rb +194 -12
- data/spec/support/shared_example_groups/request_hooks.rb +58 -0
- data/spec/support/shared_example_groups/version_checking.rb +5 -0
- data/spec/support/sinatra_app.rb +17 -9
- data/spec/support/vcr_stub_helpers.rb +17 -0
- data/spec/vcr/cassette/http_interaction_list_spec.rb +28 -29
- data/spec/vcr/cassette/migrator_spec.rb +6 -7
- data/spec/vcr/cassette_spec.rb +5 -5
- data/spec/vcr/configuration_spec.rb +51 -32
- data/spec/vcr/deprecations_spec.rb +0 -8
- data/spec/vcr/errors_spec.rb +129 -0
- data/spec/vcr/library_hooks/excon_spec.rb +21 -4
- data/spec/vcr/library_hooks/fakeweb_spec.rb +71 -3
- data/spec/vcr/library_hooks/faraday_spec.rb +45 -0
- data/spec/vcr/library_hooks/typhoeus_spec.rb +31 -1
- data/spec/vcr/library_hooks/webmock_spec.rb +26 -3
- data/spec/vcr/middleware/faraday_spec.rb +84 -1
- data/spec/vcr/request_ignorer_spec.rb +16 -0
- data/spec/vcr/request_matcher_registry_spec.rb +0 -26
- data/spec/vcr/structs_spec.rb +61 -1
- data/spec/vcr/test_frameworks/rspec_spec.rb +32 -0
- data/spec/vcr/util/hooks_spec.rb +73 -63
- data/spec/vcr_spec.rb +2 -2
- data/vcr.gemspec +5 -5
- metadata +51 -31
- data/features/configuration/hooks.feature +0 -270
- data/features/configuration/ignore_hosts.feature +0 -61
- data/features/configuration/ignore_localhost.feature +0 -97
data/features/getting_started.md
CHANGED
@@ -9,10 +9,9 @@ Create a file named `vcr_setup.rb` with content like:
|
|
9
9
|
|
10
10
|
require 'vcr'
|
11
11
|
|
12
|
-
VCR.
|
12
|
+
VCR.configure do |c|
|
13
13
|
c.cassette_library_dir = 'vcr_cassettes'
|
14
|
-
c.
|
15
|
-
c.default_cassette_options = { :record => :once }
|
14
|
+
c.hook_into :fakeweb
|
16
15
|
end
|
17
16
|
|
18
17
|
Ensure this file is required by your test suite before any
|
@@ -23,10 +22,26 @@ of the tests are run.
|
|
23
22
|
Run your tests. Any tests that make HTTP requests using Net::HTTP will
|
24
23
|
raise errors like:
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
+
================================================================================
|
30
45
|
|
31
46
|
Find one of these tests (preferably one that uses the same HTTP method and
|
32
47
|
request URL every time--if not, you'll have to configure the request matcher).
|
@@ -41,23 +56,25 @@ Run this test. It will record the HTTP request to disk as a cassette (a
|
|
41
56
|
test fixture), with content like:
|
42
57
|
|
43
58
|
---
|
44
|
-
|
45
|
-
|
46
|
-
method:
|
47
|
-
uri: http://example.com
|
48
|
-
body:
|
49
|
-
headers:
|
50
|
-
response:
|
51
|
-
status:
|
59
|
+
http_interactions:
|
60
|
+
- request:
|
61
|
+
method: get
|
62
|
+
uri: http://example.com/
|
63
|
+
body: ''
|
64
|
+
headers: {}
|
65
|
+
response:
|
66
|
+
status:
|
52
67
|
code: 200
|
53
68
|
message: OK
|
54
|
-
headers:
|
55
|
-
|
69
|
+
headers:
|
70
|
+
Content-Type:
|
56
71
|
- text/html;charset=utf-8
|
57
|
-
|
58
|
-
-
|
59
|
-
body: This is the response body
|
60
|
-
http_version:
|
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
|
61
78
|
|
62
79
|
Disconnect your computer from the internet. Run the test again.
|
63
80
|
It should pass since VCR is automatically replaying the recorded
|
@@ -0,0 +1,44 @@
|
|
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
|
+
Scenario Outline: log all requests and responses using after_http_request hook
|
11
|
+
Given a file named "after_http_request.rb" with:
|
12
|
+
"""ruby
|
13
|
+
include_http_adapter_for("<http_lib>")
|
14
|
+
|
15
|
+
start_sinatra_app(:port => 7777) do
|
16
|
+
get('/') { "Hello World" }
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'vcr'
|
20
|
+
|
21
|
+
VCR.configure do |c|
|
22
|
+
<configuration>
|
23
|
+
c.cassette_library_dir = 'cassettes'
|
24
|
+
c.ignore_localhost = true
|
25
|
+
c.after_http_request do |request, response|
|
26
|
+
puts "Response for #{request.method} #{request.uri}: #{response.body}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
make_http_request(:get, "http://localhost:7777/")
|
31
|
+
"""
|
32
|
+
When I run `ruby after_http_request.rb`
|
33
|
+
Then it should pass with "Response for get http://localhost:7777/: Hello World"
|
34
|
+
|
35
|
+
Examples:
|
36
|
+
| configuration | http_lib |
|
37
|
+
| c.hook_into :fakeweb | net/http |
|
38
|
+
| c.hook_into :webmock | net/http |
|
39
|
+
| c.hook_into :webmock | httpclient |
|
40
|
+
| c.hook_into :webmock | curb |
|
41
|
+
| c.hook_into :typhoeus | typhoeus |
|
42
|
+
| c.hook_into :excon | excon |
|
43
|
+
| c.hook_into :faraday | faraday (w/ net_http) |
|
44
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
@exclude-18
|
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
|
+
start_sinatra_app(:port => 7777) 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.around_http_request do |request|
|
32
|
+
VCR.use_cassette('global', :record => :new_episodes, &request)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
puts "Response for request 1: " + response_body_for(:get, "http://localhost:7777/")
|
37
|
+
puts "Response for request 2: " + response_body_for(:get, "http://localhost:7777/")
|
38
|
+
"""
|
39
|
+
When I run `ruby globally_handle_requests.rb`
|
40
|
+
Then it should pass with:
|
41
|
+
"""
|
42
|
+
Response for request 1: Response 1
|
43
|
+
Response for request 2: Response 1
|
44
|
+
"""
|
45
|
+
And the file "cassettes/global.yml" should contain "body: Response 1"
|
46
|
+
|
47
|
+
Examples:
|
48
|
+
| configuration | http_lib |
|
49
|
+
| c.hook_into :fakeweb | net/http |
|
50
|
+
| c.hook_into :webmock | net/http |
|
51
|
+
| c.hook_into :webmock | httpclient |
|
52
|
+
| c.hook_into :webmock | curb |
|
53
|
+
| c.hook_into :typhoeus | typhoeus |
|
54
|
+
| c.hook_into :excon | excon |
|
55
|
+
| c.hook_into :faraday | faraday (w/ net_http) |
|
56
|
+
|
@@ -0,0 +1,44 @@
|
|
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
|
+
Scenario Outline: log all requests using a before_http_request hook
|
11
|
+
Given a file named "before_http_request.rb" with:
|
12
|
+
"""ruby
|
13
|
+
include_http_adapter_for("<http_lib>")
|
14
|
+
|
15
|
+
start_sinatra_app(:port => 7777) do
|
16
|
+
get('/') { "Hello World" }
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'vcr'
|
20
|
+
|
21
|
+
VCR.configure do |c|
|
22
|
+
<configuration>
|
23
|
+
c.cassette_library_dir = 'cassettes'
|
24
|
+
c.ignore_localhost = true
|
25
|
+
c.before_http_request do |request|
|
26
|
+
puts "before request: #{request.method} #{request.uri}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
make_http_request(:get, "http://localhost:7777/")
|
31
|
+
"""
|
32
|
+
When I run `ruby before_http_request.rb`
|
33
|
+
Then it should pass with "before request: get http://localhost:7777/"
|
34
|
+
|
35
|
+
Examples:
|
36
|
+
| configuration | http_lib |
|
37
|
+
| c.hook_into :fakeweb | net/http |
|
38
|
+
| c.hook_into :webmock | net/http |
|
39
|
+
| c.hook_into :webmock | httpclient |
|
40
|
+
| c.hook_into :webmock | curb |
|
41
|
+
| c.hook_into :typhoeus | typhoeus |
|
42
|
+
| c.hook_into :excon | excon |
|
43
|
+
| c.hook_into :faraday | faraday (w/ net_http) |
|
44
|
+
|
@@ -0,0 +1,181 @@
|
|
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
|
+
If you don't your hook to apply to all cassettes, you can use tags for
|
14
|
+
this purpose. Consider this code:
|
15
|
+
|
16
|
+
VCR.configure do |c|
|
17
|
+
c.before_playback(:twitter) { ... } # modify the interactions somehow
|
18
|
+
end
|
19
|
+
|
20
|
+
VCR.use_cassette('cassette_1', :tag => :twitter) { ... }
|
21
|
+
VCR.use_cassette('cassette_2') { ... }
|
22
|
+
|
23
|
+
In this example, the hook would apply to the first cassette but not the
|
24
|
+
second cassette.
|
25
|
+
|
26
|
+
Background:
|
27
|
+
Given a previously recorded cassette file "cassettes/example.yml" with:
|
28
|
+
"""
|
29
|
+
---
|
30
|
+
http_interactions:
|
31
|
+
- request:
|
32
|
+
method: get
|
33
|
+
uri: http://localhost:7777/
|
34
|
+
body: ''
|
35
|
+
headers: {}
|
36
|
+
response:
|
37
|
+
status:
|
38
|
+
code: 200
|
39
|
+
message: OK
|
40
|
+
headers:
|
41
|
+
Content-Type:
|
42
|
+
- text/html;charset=utf-8
|
43
|
+
Content-Length:
|
44
|
+
- '20'
|
45
|
+
body: previously recorded response
|
46
|
+
http_version: '1.1'
|
47
|
+
recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
|
48
|
+
recorded_with: VCR 2.0.0
|
49
|
+
"""
|
50
|
+
|
51
|
+
Scenario: Modify played back response
|
52
|
+
Given a file named "before_playback_example.rb" with:
|
53
|
+
"""ruby
|
54
|
+
require 'vcr'
|
55
|
+
|
56
|
+
VCR.configure do |c|
|
57
|
+
c.hook_into :fakeweb
|
58
|
+
c.cassette_library_dir = 'cassettes'
|
59
|
+
|
60
|
+
c.before_playback do |interaction|
|
61
|
+
interaction.response.body = 'response from before_playback'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
VCR.use_cassette('example') do
|
66
|
+
response = Net::HTTP.get_response('localhost', '/', 7777)
|
67
|
+
puts "Response: #{response.body}"
|
68
|
+
end
|
69
|
+
"""
|
70
|
+
When I run `ruby before_playback_example.rb`
|
71
|
+
Then it should pass with "Response: response from before_playback"
|
72
|
+
|
73
|
+
Scenario: Modify played back response based on the cassette
|
74
|
+
Given a file named "before_playback_example.rb" with:
|
75
|
+
"""ruby
|
76
|
+
require 'vcr'
|
77
|
+
|
78
|
+
VCR.configure do |c|
|
79
|
+
c.hook_into :fakeweb
|
80
|
+
c.cassette_library_dir = 'cassettes'
|
81
|
+
|
82
|
+
c.before_playback do |interaction, cassette|
|
83
|
+
interaction.response.body = "response for #{cassette.name} cassette"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
VCR.use_cassette('example') do
|
88
|
+
response = Net::HTTP.get_response('localhost', '/', 7777)
|
89
|
+
puts "Response: #{response.body}"
|
90
|
+
end
|
91
|
+
"""
|
92
|
+
When I run `ruby before_playback_example.rb`
|
93
|
+
Then it should pass with "Response: response for example cassette"
|
94
|
+
|
95
|
+
Scenario: Prevent playback by ignoring interaction in before_playback hook
|
96
|
+
Given a file named "before_playback_ignore.rb" with:
|
97
|
+
"""ruby
|
98
|
+
start_sinatra_app(:port => 7777) do
|
99
|
+
get('/') { "sinatra response" }
|
100
|
+
end
|
101
|
+
|
102
|
+
require 'vcr'
|
103
|
+
|
104
|
+
VCR.configure do |c|
|
105
|
+
c.hook_into :fakeweb
|
106
|
+
c.cassette_library_dir = 'cassettes'
|
107
|
+
c.before_playback { |i| i.ignore! }
|
108
|
+
end
|
109
|
+
|
110
|
+
VCR.use_cassette('localhost', :record => :new_episodes) do
|
111
|
+
response = Net::HTTP.get_response('localhost', '/', 7777)
|
112
|
+
puts "Response: #{response.body}"
|
113
|
+
end
|
114
|
+
"""
|
115
|
+
When I run `ruby before_playback_ignore.rb`
|
116
|
+
Then it should pass with "Response: sinatra response"
|
117
|
+
|
118
|
+
Scenario: Multiple hooks are run in order
|
119
|
+
Given a file named "multiple_hooks.rb" with:
|
120
|
+
"""ruby
|
121
|
+
require 'vcr'
|
122
|
+
|
123
|
+
VCR.configure do |c|
|
124
|
+
c.hook_into :fakeweb
|
125
|
+
c.cassette_library_dir = 'cassettes'
|
126
|
+
|
127
|
+
c.before_playback { puts "In before_playback hook 1" }
|
128
|
+
c.before_playback { puts "In before_playback hook 2" }
|
129
|
+
end
|
130
|
+
|
131
|
+
VCR.use_cassette('example', :record => :new_episodes) do
|
132
|
+
response = Net::HTTP.get_response('localhost', '/', 7777)
|
133
|
+
puts "Response: #{response.body}"
|
134
|
+
end
|
135
|
+
"""
|
136
|
+
When I run `ruby multiple_hooks.rb`
|
137
|
+
Then it should pass with:
|
138
|
+
"""
|
139
|
+
In before_playback hook 1
|
140
|
+
In before_playback hook 2
|
141
|
+
Response: previously recorded response
|
142
|
+
"""
|
143
|
+
|
144
|
+
Scenario: Use tagging to apply hooks to only certain cassettes
|
145
|
+
Given a file named "tagged_hooks.rb" with:
|
146
|
+
"""ruby
|
147
|
+
require 'vcr'
|
148
|
+
|
149
|
+
VCR.configure do |c|
|
150
|
+
c.hook_into :fakeweb
|
151
|
+
c.cassette_library_dir = 'cassettes'
|
152
|
+
|
153
|
+
c.before_playback(:tag_2) do |i|
|
154
|
+
puts "In before_playback hook for tag_2"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
[:tag_1, :tag_2, nil].each do |tag|
|
159
|
+
puts
|
160
|
+
puts "Using tag: #{tag.inspect}"
|
161
|
+
|
162
|
+
VCR.use_cassette('example', :record => :new_episodes, :tag => tag) do
|
163
|
+
response = Net::HTTP.get_response('localhost', '/', 7777)
|
164
|
+
puts "Response: #{response.body}"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
"""
|
168
|
+
When I run `ruby tagged_hooks.rb`
|
169
|
+
Then it should pass with:
|
170
|
+
"""
|
171
|
+
Using tag: :tag_1
|
172
|
+
Response: previously recorded response
|
173
|
+
|
174
|
+
Using tag: :tag_2
|
175
|
+
In before_playback hook for tag_2
|
176
|
+
Response: previously recorded response
|
177
|
+
|
178
|
+
Using tag: nil
|
179
|
+
Response: previously recorded response
|
180
|
+
"""
|
181
|
+
|
@@ -0,0 +1,172 @@
|
|
1
|
+
Feature: before_record hook
|
2
|
+
|
3
|
+
The `before_record` hook is called before a cassette is written to disk.
|
4
|
+
This can be used to modify the HTTP interaction before it is recorded.
|
5
|
+
|
6
|
+
Your block should accept up to 2 arguments. The first argument will be
|
7
|
+
the HTTP interaction that is about to be written to disk. 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 recording it.
|
12
|
+
|
13
|
+
If you don't your hook to apply to all cassettes, you can use tags for
|
14
|
+
this purpose. Consider this code:
|
15
|
+
|
16
|
+
VCR.configure do |c|
|
17
|
+
c.before_record(:twitter) { ... } # modify the interactions somehow
|
18
|
+
end
|
19
|
+
|
20
|
+
VCR.use_cassette('cassette_1', :tag => :twitter) { ... }
|
21
|
+
VCR.use_cassette('cassette_2') { ... }
|
22
|
+
|
23
|
+
In this example, the hook would apply to the first cassette but not the
|
24
|
+
second cassette.
|
25
|
+
|
26
|
+
Scenario: Modify recorded response
|
27
|
+
Given a file named "before_record_example.rb" with:
|
28
|
+
"""ruby
|
29
|
+
start_sinatra_app(:port => 7777) do
|
30
|
+
get('/') { "Hello Earth" }
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'vcr'
|
34
|
+
|
35
|
+
VCR.configure do |c|
|
36
|
+
c.hook_into :fakeweb
|
37
|
+
c.cassette_library_dir = 'cassettes'
|
38
|
+
|
39
|
+
c.before_record do |i|
|
40
|
+
i.response.body.sub!('Earth', 'World')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
VCR.use_cassette('recording_example') do
|
45
|
+
Net::HTTP.get_response('localhost', '/', 7777)
|
46
|
+
end
|
47
|
+
"""
|
48
|
+
When I run `ruby before_record_example.rb`
|
49
|
+
Then the file "cassettes/recording_example.yml" should contain "body: Hello World"
|
50
|
+
And the file "cassettes/recording_example.yml" should not contain "Earth"
|
51
|
+
|
52
|
+
Scenario: Modify recorded response based on the cassette
|
53
|
+
Given a file named "before_record_example.rb" with:
|
54
|
+
"""ruby
|
55
|
+
start_sinatra_app(:port => 7777) do
|
56
|
+
get('/') { "Hello Earth" }
|
57
|
+
end
|
58
|
+
|
59
|
+
require 'vcr'
|
60
|
+
|
61
|
+
VCR.configure do |c|
|
62
|
+
c.hook_into :fakeweb
|
63
|
+
c.cassette_library_dir = 'cassettes'
|
64
|
+
|
65
|
+
c.before_record do |interaction, cassette|
|
66
|
+
interaction.response.body << " (#{cassette.name})"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
VCR.use_cassette('recording_example') do
|
71
|
+
Net::HTTP.get_response('localhost', '/', 7777)
|
72
|
+
end
|
73
|
+
"""
|
74
|
+
When I run `ruby before_record_example.rb`
|
75
|
+
Then the file "cassettes/recording_example.yml" should contain "body: Hello Earth (recording_example)"
|
76
|
+
|
77
|
+
Scenario: Prevent recording by ignoring interaction in before_record hook
|
78
|
+
Given a file named "before_record_ignore.rb" with:
|
79
|
+
"""ruby
|
80
|
+
start_sinatra_app(:port => 7777) do
|
81
|
+
get('/') { "Hello World" }
|
82
|
+
end
|
83
|
+
|
84
|
+
require 'vcr'
|
85
|
+
|
86
|
+
VCR.configure do |c|
|
87
|
+
c.hook_into :fakeweb
|
88
|
+
c.cassette_library_dir = 'cassettes'
|
89
|
+
c.before_record { |i| i.ignore! }
|
90
|
+
end
|
91
|
+
|
92
|
+
VCR.use_cassette('recording_example') do
|
93
|
+
response = Net::HTTP.get_response('localhost', '/', 7777)
|
94
|
+
puts "Response: #{response.body}"
|
95
|
+
end
|
96
|
+
"""
|
97
|
+
When I run `ruby before_record_ignore.rb`
|
98
|
+
Then it should pass with "Response: Hello World"
|
99
|
+
And the file "cassettes/recording_example.yml" should not exist
|
100
|
+
|
101
|
+
Scenario: Multiple hooks are run in order
|
102
|
+
Given a file named "multiple_hooks.rb" with:
|
103
|
+
"""ruby
|
104
|
+
start_sinatra_app(:port => 7777) do
|
105
|
+
get('/') { "Hello World" }
|
106
|
+
end
|
107
|
+
|
108
|
+
require 'vcr'
|
109
|
+
|
110
|
+
VCR.configure do |c|
|
111
|
+
c.hook_into :fakeweb
|
112
|
+
c.cassette_library_dir = 'cassettes'
|
113
|
+
|
114
|
+
c.before_record { puts "In before_record hook 1" }
|
115
|
+
c.before_record { puts "In before_record hook 2" }
|
116
|
+
end
|
117
|
+
|
118
|
+
VCR.use_cassette('example', :record => :new_episodes) do
|
119
|
+
response = Net::HTTP.get_response('localhost', '/', 7777)
|
120
|
+
puts "Response: #{response.body}"
|
121
|
+
end
|
122
|
+
"""
|
123
|
+
When I run `ruby multiple_hooks.rb`
|
124
|
+
Then it should pass with:
|
125
|
+
"""
|
126
|
+
Response: Hello World
|
127
|
+
In before_record hook 1
|
128
|
+
In before_record hook 2
|
129
|
+
"""
|
130
|
+
|
131
|
+
Scenario: Use tagging to apply hook to only certain cassettes
|
132
|
+
Given a file named "tagged_hooks.rb" with:
|
133
|
+
"""ruby
|
134
|
+
start_sinatra_app(:port => 7777) do
|
135
|
+
get('/') { "Hello World" }
|
136
|
+
end
|
137
|
+
|
138
|
+
require 'vcr'
|
139
|
+
|
140
|
+
VCR.configure do |c|
|
141
|
+
c.hook_into :fakeweb
|
142
|
+
c.cassette_library_dir = 'cassettes'
|
143
|
+
|
144
|
+
c.before_record(:tag_1) do
|
145
|
+
puts "In before_record hook for tag_1"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
[:tag_1, :tag_2, nil].each do |tag|
|
150
|
+
puts
|
151
|
+
puts "Using tag: #{tag.inspect}"
|
152
|
+
|
153
|
+
VCR.use_cassette('example', :record => :new_episodes, :tag => tag) do
|
154
|
+
response = Net::HTTP.get_response('localhost', '/', 7777)
|
155
|
+
puts "Response: #{response.body}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
"""
|
159
|
+
When I run `ruby tagged_hooks.rb`
|
160
|
+
Then it should pass with:
|
161
|
+
"""
|
162
|
+
Using tag: :tag_1
|
163
|
+
Response: Hello World
|
164
|
+
In before_record hook for tag_1
|
165
|
+
|
166
|
+
Using tag: :tag_2
|
167
|
+
Response: Hello World
|
168
|
+
|
169
|
+
Using tag: nil
|
170
|
+
Response: Hello World
|
171
|
+
"""
|
172
|
+
|