vcr 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +11 -0
- data/LICENSE +1 -1
- data/README.rdoc +34 -35
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/features/record_response.feature +22 -22
- data/features/replay_recorded_response.feature +22 -16
- data/features/step_definitions/vcr_steps.rb +54 -33
- data/features/support/env.rb +8 -8
- data/lib/vcr.rb +7 -6
- data/lib/vcr/cassette.rb +11 -12
- data/lib/vcr/config.rb +4 -9
- data/lib/vcr/cucumber_tags.rb +2 -2
- data/lib/vcr/deprecations.rb +54 -0
- data/spec/cassette_spec.rb +37 -37
- data/spec/config_spec.rb +3 -28
- data/spec/cucumber_tags_spec.rb +7 -7
- data/spec/deprecations_spec.rb +67 -0
- data/spec/spec_helper.rb +3 -2
- data/spec/support/deprecated.rb +18 -0
- data/spec/support/{temp_cache_dir.rb → temp_cassette_library_dir.rb} +3 -3
- data/spec/vcr_spec.rb +27 -31
- data/vcr.gemspec +10 -5
- metadata +11 -6
data/History.rdoc
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 0.3.0 March 24, 2010
|
2
|
+
* Renamed a bunch of methods, replacing them with method names that more clearly fit the VCR/cassette metaphor:
|
3
|
+
* VCR.create_cassette! => VCR.insert_cassette
|
4
|
+
* VCR.destroy_cassette! => VCR.eject_cassette
|
5
|
+
* VCR.with_cassette => VCR.use_cassette
|
6
|
+
* VCR::Cassette#destroy! => VCR::Cassette#eject
|
7
|
+
* VCR::Cassette#cache_file => VCR::Cassette#file
|
8
|
+
* VCR::Config.cache_dir => VCR::Config.cassette_library_dir
|
9
|
+
* :unregistered record mode => :new_episodes record mode
|
10
|
+
* All the old methods still work, but you'll get deprecation warnings.
|
11
|
+
|
1
12
|
== 0.2.0 March 9, 2010
|
2
13
|
* Added <tt>:allow_real_http</tt> cassette option, which allows VCR to work with capybara and a javascript driver.
|
3
14
|
Bug reported by {Ben Hutton}[http://github.com/benhutton].
|
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -15,26 +15,26 @@ VCR was inspired by {NetRecorder}[http://github.com/chrisyoung/netrecorder], but
|
|
15
15
|
localized recording and replaying, rather than the global recording and replaying of NetRecorder. In general, I believe that
|
16
16
|
tests should not rely upon anything global. You're coupling your test to something outside of it that may later change and
|
17
17
|
break the test. It's far better to localize things to each test, as much as possible. VCR, in combination with FakeWeb,
|
18
|
-
makes it easy to do this with the recording and
|
18
|
+
makes it easy to do this with the recording and replaying of HTTP responses.
|
19
19
|
|
20
20
|
== Cassettes
|
21
21
|
|
22
22
|
Cassettes are central to the way VCR works. They are a similar to VHS cassettes--your library of cassettes
|
23
|
-
is your library of previously recorded responses that can be replayed. When you
|
23
|
+
is your library of previously recorded responses that can be replayed. When you insert a cassette, it does
|
24
24
|
the following:
|
25
25
|
|
26
|
-
* It loads the previously recorded responses from the
|
26
|
+
* It loads the previously recorded responses from the library file corresponding to the cassette name.
|
27
27
|
* It register these responses with fakeweb (depending on the cassette's :record option--see below)
|
28
28
|
* It sets the <tt>FakeWeb.allow_net_connect</tt> setting based on the cassette's :record option.
|
29
29
|
|
30
30
|
While a cassette is active, any HTTP requests to a URL of a previously recorded response will use
|
31
31
|
the recorded response. New HTTP requests (i.e. HTTP requests that have not been previously recorded)
|
32
|
-
will be recorded to the same
|
32
|
+
will be recorded to the same library file, depending on your :record option. When you eject a cassette,
|
33
33
|
it does the following:
|
34
34
|
|
35
|
-
* It saves all of the recorded responses (both old and new) to a
|
35
|
+
* It saves all of the recorded responses (both old and new) to a yml library file corresponding to the cassette name.
|
36
36
|
* It removes the registrations it made with fakeweb, to prevent "leakage" into other tests.
|
37
|
-
* It reverts the <tt>FakeWeb.allow_net_connect</tt> back to whatever it was before the cassette was
|
37
|
+
* It reverts the <tt>FakeWeb.allow_net_connect</tt> back to whatever it was before the cassette was inserted.
|
38
38
|
|
39
39
|
== Record modes
|
40
40
|
|
@@ -42,20 +42,20 @@ VCR supports 3 record modes, which configure when it records new responses. You
|
|
42
42
|
record mode in your configuration (see below) and a per-cassette record mode when creating a cassette. The record
|
43
43
|
modes are:
|
44
44
|
|
45
|
+
* <tt>:new_episodes</tt> - This will use the previously recorded responses, and record any new requests that are not registered with
|
46
|
+
fakeweb. The previously recorded responses will be registered with fakeweb. <tt>FakeWeb.allow_net_connect</tt> will be
|
47
|
+
set to true, so that VCR will record any new HTTP requests within the cassette. Use this when it's ok for external HTTP
|
48
|
+
requests to be made without you explicitly allowing it. New requests will get saved to the cassette's yml library file, and
|
49
|
+
automatically get used in the future.
|
45
50
|
* <tt>:all</tt> - This will cause VCR to re-record all HTTP requests that occur.
|
46
51
|
When the cassette is created, it will not register any of the cached responses with fakeweb.
|
47
52
|
<tt>FakeWeb.allow_net_connect</tt> will be set to true, so it can record the requests. Use this
|
48
53
|
when you want to re-record all of the HTTP requests for a cassette. Alternately, you can simply
|
49
|
-
delete the corresponding
|
54
|
+
delete the corresponding library file and use the :new_episodes record mode, described above.
|
50
55
|
* <tt>:none</tt> - This will prevent VCR from recording, or even allowing, any new HTTP requests.
|
51
56
|
The previously recorded responses will be registered with fakeweb. <tt>FakeWeb.allow_net_connect</tt> will be set to
|
52
57
|
false, so that no new HTTP connections are allowed. Use this when you want to guarantee that no external
|
53
58
|
HTTP requests will be made while the given cassette is active. Fakeweb will raise an error in this case.
|
54
|
-
* <tt>:unregistered</tt> - This will use the previously recorded responses, and record any new requests that are not registered with
|
55
|
-
fakeweb. The previously recorded responses will be registered with fakeweb. <tt>FakeWeb.allow_net_connect</tt> will be
|
56
|
-
set to true, so that VCR will record any new HTTP requests within the cassette. Use this when it's ok for external HTTP
|
57
|
-
requests to be made without you explicitly allowing it. New requests will get saved to the cassettes yml file, and
|
58
|
-
automatically get used in the future.
|
59
59
|
|
60
60
|
== Configuration
|
61
61
|
|
@@ -66,8 +66,8 @@ modes are:
|
|
66
66
|
FakeWeb.allow_net_connect = false
|
67
67
|
|
68
68
|
VCR.config do |c|
|
69
|
-
# the
|
70
|
-
c.
|
69
|
+
# the cassette_library_dir is where the cassette yml files will be saved.
|
70
|
+
c.cassette_library_dir = File.join(Rails.root, 'features', 'fixtures', 'cassette_library')
|
71
71
|
|
72
72
|
# these options will be used as defaults for your cassettes, but you can override them in each individual cassette.
|
73
73
|
c.default_cassette_options = {
|
@@ -81,33 +81,33 @@ to put it in spec/support/vcr.rb, test/support/vcr.rb or features/support/vcr.rb
|
|
81
81
|
|
82
82
|
== Usage with your favorite test/spec framework
|
83
83
|
|
84
|
-
VCR can easily be used with any ruby test or spec framework. Usually, you'll want to use <tt>VCR.
|
84
|
+
VCR can easily be used with any ruby test or spec framework. Usually, you'll want to use <tt>VCR.use_cassette</tt>:
|
85
85
|
|
86
|
-
VCR.
|
86
|
+
VCR.use_cassette('geocoding/Seattle, WA', :record => :new_episodes) do
|
87
87
|
# do something that causes an HTTP request.
|
88
88
|
end
|
89
89
|
|
90
|
-
Alternately, you can
|
90
|
+
Alternately, you can insert and eject the cassette with individual method calls from setup/before and teardown/after:
|
91
91
|
|
92
92
|
describe "Something that makes an HTTP request" do
|
93
93
|
before(:each) do
|
94
|
-
VCR.
|
94
|
+
VCR.insert_cassette('geocoding/Seattle, WA', :record => :new_episodes)
|
95
95
|
end
|
96
96
|
|
97
97
|
it "should do something that makes an HTTP request"
|
98
98
|
|
99
99
|
after(:each) do
|
100
|
-
VCR.
|
100
|
+
VCR.eject_cassette
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
104
|
In both of these cases, VCR would use the file geocoding/Seattle_WA.yml within the configured
|
105
|
-
|
105
|
+
cassette library dir. The :record setting is optional--if you leave it blank, your configured default will be used.
|
106
106
|
|
107
107
|
Besides the :record option, cassettes also support the :allow_real_http option. You can use this to make the cassette
|
108
108
|
allow some real HTTP requests. You can specify it with a lambda:
|
109
109
|
|
110
|
-
VCR.
|
110
|
+
VCR.use_cassette('my cassette', :allow_real_http => lambda { |uri| uri.host == 'google.com' }) do
|
111
111
|
# do something that causes an HTTP request.
|
112
112
|
end
|
113
113
|
|
@@ -115,7 +115,7 @@ In this case, any google HTTP requests will be made for real, regardless of your
|
|
115
115
|
your current record mode, and whether or not you are recording or replaying this cassette. Non-google requests will do
|
116
116
|
the appropriate recording/replaying as usual. You can also use the special <tt>:localhost</tt> option:
|
117
117
|
|
118
|
-
VCR.
|
118
|
+
VCR.use_cassette('my cassette', :allow_real_http => :localhost) do
|
119
119
|
# do something that causes an HTTP request.
|
120
120
|
end
|
121
121
|
|
@@ -127,7 +127,7 @@ This is needed for using VCR with {capybara}[http://github.com/jnicklas/capybara
|
|
127
127
|
|
128
128
|
== Usage with Cucumber
|
129
129
|
|
130
|
-
VCR provides special support for cucumber. You can of course use <tt>VCR.
|
130
|
+
VCR provides special support for cucumber. You can of course use <tt>VCR.use_cassette</tt> within a step definition,
|
131
131
|
and that's the recommended way for any of your step definitions. But many times I find myself using generic step definitions
|
132
132
|
provided by another library (such as the webrat/capybara web steps generated by cucumber-rails), and I don't want to modify
|
133
133
|
these. VCR provides cucumber tagging support to help in these cases.
|
@@ -147,7 +147,7 @@ Then let VCR know about this tag, in features/support/vcr.rb (or some similar su
|
|
147
147
|
For each of the tags you specify in your cucumber_tags block, VCR will set up the appropriate
|
148
148
|
{Before and After hooks}[http://wiki.github.com/aslakhellesoy/cucumber/hooks] to use a cassette
|
149
149
|
for the entire scenario. The tag (minus the '@') will be used as the cassette name, and it'll
|
150
|
-
go in the cucumber_tags subdirectory of the configured
|
150
|
+
go in the cucumber_tags subdirectory of the configured cassette library dir.
|
151
151
|
|
152
152
|
== Usage with Capybara
|
153
153
|
|
@@ -157,8 +157,7 @@ it'll need to ping the app running on localhost. You can use the <tt>:allow_rea
|
|
157
157
|
== Suggested Workflow
|
158
158
|
|
159
159
|
First, configure VCR and FakeWeb as I have above. I like setting <tt>FakeWeb.allow_net_connect</tt> to <tt>false</tt>
|
160
|
-
and
|
161
|
-
explicitly allowing it.
|
160
|
+
and the default record mode to <tt>:none</tt> so that no new HTTP requests are made without me explicitly allowing it.
|
162
161
|
|
163
162
|
When an HTTP request is made, you'll get an {error from FakeWeb}[http://github.com/chrisk/fakeweb/blob/fakeweb-1.2.8/lib/fake_web/ext/net_http.rb#L62-63],
|
164
163
|
such as:
|
@@ -166,37 +165,37 @@ such as:
|
|
166
165
|
FakeWeb::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: get http://example.com
|
167
166
|
|
168
167
|
Find the place that is making the HTTP request (the backtrace should help here). If you've already recorded this HTTP
|
169
|
-
request to a cassette from a different test, you can simply re-use the cassette. Use <tt>VCR.
|
168
|
+
request to a cassette from a different test, you can simply re-use the cassette. Use <tt>VCR.use_cassette</tt>, as
|
170
169
|
shown above. You may also want to refactor this into a helper method that sets up the VCR cassette and does whatever
|
171
170
|
makes the HTTP request:
|
172
171
|
|
173
172
|
def set_user_address(user, address, city, state)
|
174
|
-
VCR.
|
173
|
+
VCR.use_cassette("geocoding/#{address}, #{city}, #{state}", :record => :new_episodes) do
|
175
174
|
user.address.update_attributes!(:address => address, :city => city, :state => state)
|
176
175
|
end
|
177
176
|
end
|
178
177
|
|
179
178
|
In this case, I've used a dynamic cassette name based on the address being geocoded. That way, each separate address
|
180
179
|
gets a different cassette, and tests that set the same user address will reuse the same cassette. I've also set
|
181
|
-
the record mode to <tt>:
|
180
|
+
the record mode to <tt>:new_episodes</tt> so that VCR will automatically record geocoding requests for a new address
|
182
181
|
to a new cassette, without me having to do anything.
|
183
182
|
|
184
|
-
If the HTTP request that triggered the error is new, you'll have to record it for the first time. Simply use <tt>VCR.
|
185
|
-
with the record mode set to <tt>:
|
183
|
+
If the HTTP request that triggered the error is new, you'll have to record it for the first time. Simply use <tt>VCR.use_cassette</tt>
|
184
|
+
with the record mode set to <tt>:new_episodes</tt> or <tt>:all</tt>. Run the test again, and VCR will record the HTTP response. I usually
|
186
185
|
remove the record mode at this point so that it uses the default of <tt>:none</tt> in the future. Future test runs will use the
|
187
186
|
recorded response, and if your code changes so that it is making a new HTTP request, you'll get the same FakeWeb error as shown above.
|
188
187
|
|
189
188
|
== Ruby Version Compatibility
|
190
189
|
|
191
|
-
|
190
|
+
VCR works on ruby {1.8.6}[http://integrity186.heroku.com/vcr], {1.8.7}[http://integrity187.heroku.com/vcr] and {1.9.1}[http://integrity191.heroku.com/vcr].
|
192
191
|
|
193
192
|
== Notes, etc.
|
194
193
|
|
195
|
-
* The cassette name determines the name of the
|
194
|
+
* The cassette name determines the name of the library file for the given cassette. Strings or symbols are fine,
|
196
195
|
and you can include any characters, but spaces and invalid file name characters will be removed
|
197
|
-
before the cassette reads or writes to
|
196
|
+
before the cassette reads or writes to its library file.
|
198
197
|
* You can use a directory separator (i.e. '/') in your cassette names to cause it to use a subdirectory
|
199
|
-
of the
|
198
|
+
of the cassette_library_dir. The cucumber tagging support uses this.
|
200
199
|
* VCR maintains a simple stack of cassettes. This allows you to nest them as deeply as you want.
|
201
200
|
This is particularly useful when you have a cucumber step definition that uses a cassette, and
|
202
201
|
you also want to use a cassette for the entire scenario using the tagging support.
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ begin
|
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "vcr"
|
8
8
|
gem.summary = %Q{Use VCR to record HTTP responses and replay them using fakeweb.}
|
9
|
-
gem.description = %Q{VCR provides helpers to record HTTP requests for URIs that are not registered with fakeweb, and replay them later. It provides built-in support for cucumber
|
9
|
+
gem.description = %Q{VCR provides helpers to record HTTP requests for URIs that are not registered with fakeweb, and replay them later. It works with any ruby testing framework, and provides built-in support for cucumber.}
|
10
10
|
gem.email = "myron.marston@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/myronmarston/vcr"
|
12
12
|
gem.authors = ["Myron Marston"]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
@@ -3,21 +3,21 @@ Feature: Record response
|
|
3
3
|
As a TDD/BDD developer
|
4
4
|
I want to record responses for requests to URIs that are not registered with fakeweb so I can use them with fakeweb in the future
|
5
5
|
|
6
|
-
Scenario: Record a response using VCR.
|
6
|
+
Scenario: Record a response using VCR.use_cassette
|
7
7
|
Given we do not have a "temp/cassette" cassette
|
8
8
|
When I make an HTTP get request to "http://example.com" within the "temp/cassette" cassette
|
9
|
-
Then the "temp/cassette"
|
9
|
+
Then the "temp/cassette" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
|
10
10
|
|
11
11
|
@record_cassette1
|
12
12
|
Scenario: Record a response using a tagged scenario
|
13
13
|
Given we do not have a "cucumber_tags/record_cassette1" cassette
|
14
14
|
And this scenario is tagged with the vcr cassette tag: "@record_cassette1"
|
15
15
|
When I make an HTTP get request to "http://example.com"
|
16
|
-
Then I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been
|
16
|
+
Then I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been ejected
|
17
17
|
|
18
18
|
Scenario: Check the recorded response for the previous scenario
|
19
19
|
Given the previous scenario was tagged with the vcr cassette tag: "@record_cassette1"
|
20
|
-
Then the "cucumber_tags/record_cassette1"
|
20
|
+
Then the "cucumber_tags/record_cassette1" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
|
21
21
|
|
22
22
|
@record_cassette2
|
23
23
|
Scenario: Use both a tagged scenario cassette and a nested cassette within a single step definition
|
@@ -27,46 +27,46 @@ Feature: Record response
|
|
27
27
|
When I make an HTTP get request to "http://example.com/before_nested"
|
28
28
|
And I make an HTTP get request to "http://example.com/nested" within the "temp/nested" cassette
|
29
29
|
And I make an HTTP get request to "http://example.com/after_nested"
|
30
|
-
Then I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been
|
31
|
-
And the "temp/nested"
|
30
|
+
Then I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been ejected
|
31
|
+
And the "temp/nested" library file should have a response for "http://example.com/nested" that matches /The requested URL \/nested was not found/
|
32
32
|
|
33
33
|
Scenario: Check the recorded response for the previous scenario
|
34
34
|
Given the previous scenario was tagged with the vcr cassette tag: "@record_cassette2"
|
35
|
-
Then the "cucumber_tags/record_cassette2"
|
36
|
-
And the "cucumber_tags/record_cassette2"
|
35
|
+
Then the "cucumber_tags/record_cassette2" library file should have a response for "http://example.com/before_nested" that matches /The requested URL \/before_nested was not found/
|
36
|
+
And the "cucumber_tags/record_cassette2" library file should have a response for "http://example.com/after_nested" that matches /The requested URL \/after_nested was not found/
|
37
37
|
|
38
38
|
Scenario: Make an HTTP request in a cassette with record mode set to :all
|
39
39
|
Given we do not have a "temp/record_all_cassette" cassette
|
40
40
|
When I make an HTTP get request to "http://example.com" within the "temp/record_all_cassette" all cassette
|
41
|
-
Then the "temp/record_all_cassette"
|
41
|
+
Then the "temp/record_all_cassette" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
|
42
42
|
|
43
43
|
Scenario: Make an HTTP request in a cassette with record mode set to :none
|
44
44
|
Given we do not have a "temp/record_none_cassette" cassette
|
45
45
|
When I make an HTTP get request to "http://example.com" within the "temp/record_none_cassette" none cassette
|
46
46
|
Then the HTTP get request to "http://example.com" should result in a fakeweb error that mentions VCR
|
47
|
-
And there should not be a "temp/record_none_cassette"
|
47
|
+
And there should not be a "temp/record_none_cassette" library file
|
48
48
|
|
49
49
|
@copy_not_the_real_response_to_temp
|
50
|
-
Scenario: Make an HTTP request in a cassette with record mode set to :
|
51
|
-
Given we have a "temp/not_the_real_response" file with a previously recorded response for "http://example.com"
|
52
|
-
And we have a "temp/not_the_real_response" file with no previously recorded response for "http://example.com/foo"
|
53
|
-
When I make HTTP get requests to "http://example.com" and "http://example.com/foo" within the "temp/not_the_real_response"
|
54
|
-
Then the "temp/not_the_real_response"
|
55
|
-
And the "temp/not_the_real_response"
|
50
|
+
Scenario: Make an HTTP request in a cassette with record mode set to :new_episodes
|
51
|
+
Given we have a "temp/not_the_real_response" library file with a previously recorded response for "http://example.com"
|
52
|
+
And we have a "temp/not_the_real_response" library file with no previously recorded response for "http://example.com/foo"
|
53
|
+
When I make HTTP get requests to "http://example.com" and "http://example.com/foo" within the "temp/not_the_real_response" new_episodes cassette
|
54
|
+
Then the "temp/not_the_real_response" library file should have a response for "http://example.com" that matches /This is not the real response from example\.com/
|
55
|
+
And the "temp/not_the_real_response" library file should have a response for "http://example.com/foo" that matches /The requested URL \/foo was not found/
|
56
56
|
|
57
57
|
Scenario: Record an asynchronous request (such as for mechanize)
|
58
58
|
Given we do not have a "temp/asynchronous" cassette
|
59
|
-
When I make an asynchronous HTTP get request to "http://example.com" within the "temp/asynchronous"
|
60
|
-
Then the "temp/asynchronous"
|
59
|
+
When I make an asynchronous HTTP get request to "http://example.com" within the "temp/asynchronous" new_episodes cassette
|
60
|
+
Then the "temp/asynchronous" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
|
61
61
|
|
62
62
|
Scenario: Record a recursive post request
|
63
63
|
Given we do not have a "temp/recursive_post" cassette
|
64
|
-
When I make a recursive HTTP post request to "http://example.com" within the "temp/recursive_post"
|
65
|
-
Then the "temp/recursive_post"
|
66
|
-
And the "temp/recursive_post"
|
64
|
+
When I make a recursive HTTP post request to "http://example.com" within the "temp/recursive_post" new_episodes cassette
|
65
|
+
Then the "temp/recursive_post" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
|
66
|
+
And the "temp/recursive_post" library file should have exactly 1 response
|
67
67
|
|
68
68
|
Scenario: Make an allowed HTTP request in a cassette with record mode set to :none
|
69
69
|
Given we do not have a "temp/record_none_cassette" cassette
|
70
70
|
When I make an HTTP get request to "http://example.com" within the "temp/record_none_cassette" none cassette, allowing requests matching /example.com/
|
71
71
|
Then the response for "http://example.com" should match /You have reached this web page by typing.*example\.com/
|
72
|
-
And there should not be a "temp/record_none_cassette"
|
72
|
+
And there should not be a "temp/record_none_cassette" library file
|
@@ -3,24 +3,24 @@ Feature: Replay recorded response
|
|
3
3
|
As a TDD/BDD developer
|
4
4
|
I want to replay responses for requests I have previously recorded
|
5
5
|
|
6
|
-
Scenario: Replay recorded response for a request in a VCR.
|
7
|
-
Given the "not_the_real_response"
|
6
|
+
Scenario: Replay recorded response for a request in a VCR.use_cassette block
|
7
|
+
Given the "not_the_real_response" library file has a response for "http://example.com" that matches /This is not the real response from example\.com/
|
8
8
|
When I make an HTTP get request to "http://example.com" within the "not_the_real_response" cassette
|
9
9
|
Then the response for "http://example.com" should match /This is not the real response from example\.com/
|
10
10
|
|
11
11
|
@replay_cassette1
|
12
12
|
Scenario: Replay recorded response for a request within a tagged scenario
|
13
13
|
Given this scenario is tagged with the vcr cassette tag: "@replay_cassette1"
|
14
|
-
And the "cucumber_tags/replay_cassette1"
|
14
|
+
And the "cucumber_tags/replay_cassette1" library file has a response for "http://example.com" that matches /This is not the real response from example\.com/
|
15
15
|
When I make an HTTP get request to "http://example.com"
|
16
16
|
Then the response for "http://example.com" should match /This is not the real response from example\.com/
|
17
17
|
|
18
18
|
@replay_cassette2
|
19
19
|
Scenario: Use both a tagged scenario cassette and a nested cassette within a single step definition
|
20
20
|
Given this scenario is tagged with the vcr cassette tag: "@replay_cassette2"
|
21
|
-
And the "cucumber_tags/replay_cassette2"
|
22
|
-
And the "nested_replay_cassette"
|
23
|
-
And the "cucumber_tags/replay_cassette2"
|
21
|
+
And the "cucumber_tags/replay_cassette2" library file has a response for "http://example.com/before_nested" that matches /The before_nested response/
|
22
|
+
And the "nested_replay_cassette" library file has a response for "http://example.com/nested" that matches /The nested response/
|
23
|
+
And the "cucumber_tags/replay_cassette2" library file has a response for "http://example.com/after_nested" that matches /The after_nested response/
|
24
24
|
When I make an HTTP get request to "http://example.com/before_nested"
|
25
25
|
And I make an HTTP get request to "http://example.com/nested" within the "nested_replay_cassette" cassette
|
26
26
|
And I make an HTTP get request to "http://example.com/after_nested"
|
@@ -30,34 +30,40 @@ Feature: Replay recorded response
|
|
30
30
|
|
31
31
|
@copy_not_the_real_response_to_temp
|
32
32
|
Scenario: Make an HTTP request in a cassette with record mode set to :all
|
33
|
-
Given we have a "temp/not_the_real_response" file with a previously recorded response for "http://example.com"
|
34
|
-
And we have a "temp/not_the_real_response" file with no previously recorded response for "http://example.com/foo"
|
33
|
+
Given we have a "temp/not_the_real_response" library file with a previously recorded response for "http://example.com"
|
34
|
+
And we have a "temp/not_the_real_response" library file with no previously recorded response for "http://example.com/foo"
|
35
35
|
When I make HTTP get requests to "http://example.com" and "http://example.com/foo" within the "temp/not_the_real_response" all cassette
|
36
36
|
Then the response for "http://example.com" should match /You have reached this web page by typing.*example\.com/
|
37
37
|
And the response for "http://example.com/foo" should match /The requested URL \/foo was not found/
|
38
38
|
|
39
39
|
@copy_not_the_real_response_to_temp
|
40
40
|
Scenario: Make an HTTP request in a cassette with record mode set to :none
|
41
|
-
Given we have a "temp/not_the_real_response" file with a previously recorded response for "http://example.com"
|
42
|
-
And we have a "temp/not_the_real_response" file with no previously recorded response for "http://example.com/foo"
|
41
|
+
Given we have a "temp/not_the_real_response" library file with a previously recorded response for "http://example.com"
|
42
|
+
And we have a "temp/not_the_real_response" library file with no previously recorded response for "http://example.com/foo"
|
43
43
|
When I make HTTP get requests to "http://example.com" and "http://example.com/foo" within the "temp/not_the_real_response" none cassette
|
44
44
|
Then the response for "http://example.com" should match /This is not the real response from example\.com/
|
45
45
|
And the HTTP get request to "http://example.com/foo" should result in a fakeweb error that mentions VCR
|
46
46
|
|
47
47
|
@copy_not_the_real_response_to_temp
|
48
|
-
Scenario: Make an HTTP request in a cassette with record mode set to :
|
49
|
-
Given we have a "temp/not_the_real_response" file with a previously recorded response for "http://example.com"
|
50
|
-
And we have a "temp/not_the_real_response" file with no previously recorded response for "http://example.com/foo"
|
51
|
-
When I make HTTP get requests to "http://example.com" and "http://example.com/foo" within the "temp/not_the_real_response"
|
48
|
+
Scenario: Make an HTTP request in a cassette with record mode set to :new_episodes
|
49
|
+
Given we have a "temp/not_the_real_response" library file with a previously recorded response for "http://example.com"
|
50
|
+
And we have a "temp/not_the_real_response" library file with no previously recorded response for "http://example.com/foo"
|
51
|
+
When I make HTTP get requests to "http://example.com" and "http://example.com/foo" within the "temp/not_the_real_response" new_episodes cassette
|
52
52
|
Then the response for "http://example.com" should match /This is not the real response from example\.com/
|
53
53
|
And the response for "http://example.com/foo" should match /The requested URL \/foo was not found/
|
54
54
|
|
55
55
|
@replay_cassette3
|
56
56
|
Scenario: Replay multiple different recorded responses for requests to the same URL
|
57
57
|
Given this scenario is tagged with the vcr cassette tag: "@replay_cassette3"
|
58
|
-
And the "cucumber_tags/replay_cassette3"
|
59
|
-
And the "cucumber_tags/replay_cassette3"
|
58
|
+
And the "cucumber_tags/replay_cassette3" library file has a response for "http://example.com" that matches /This is not the real response from example\.com/
|
59
|
+
And the "cucumber_tags/replay_cassette3" library file has a response for "http://example.com" that matches /This is another fake response from example\.com/
|
60
60
|
When I make an HTTP get request to "http://example.com"
|
61
61
|
And I make an HTTP get request to "http://example.com"
|
62
62
|
Then response 1 for "http://example.com" should match /This is not the real response from example\.com/
|
63
63
|
And response 2 for "http://example.com" should match /This is another fake response from example\.com/
|
64
|
+
|
65
|
+
@copy_not_the_real_response_to_temp
|
66
|
+
Scenario: Replay a response for an asynchronous request (such as for mechanize)
|
67
|
+
Given the "temp/not_the_real_response" library file has a response for "http://example.com" that matches /This is not the real response from example\.com/
|
68
|
+
When I make a replayed asynchronous HTTP get request to "http://example.com" within the "temp/not_the_real_response" new_episodes cassette
|
69
|
+
Then the response for "http://example.com" should match /This is not the real response from example\.com/
|
@@ -10,29 +10,41 @@ module VCRHelpers
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def recorded_responses_for(cassette_name)
|
13
|
-
yaml_file = File.join(VCR::Config.
|
13
|
+
yaml_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
|
14
14
|
yaml = File.open(yaml_file, 'r') { |f| f.read }
|
15
15
|
responses = YAML.load(yaml)
|
16
16
|
end
|
17
|
+
|
18
|
+
def capture_response(url)
|
19
|
+
@http_requests ||= Hash.new([])
|
20
|
+
uri = URI.parse(url)
|
21
|
+
path = uri.path.to_s == '' ? '/' : uri.path
|
22
|
+
begin
|
23
|
+
result = yield uri, path
|
24
|
+
rescue => e
|
25
|
+
result = e
|
26
|
+
end
|
27
|
+
@http_requests[url] += [result]
|
28
|
+
end
|
17
29
|
end
|
18
30
|
World(VCRHelpers)
|
19
31
|
|
20
32
|
Given /^we do not have a "([^\"]*)" cassette$/ do |cassette_name|
|
21
|
-
fixture_file = File.join(VCR::Config.
|
33
|
+
fixture_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
|
22
34
|
File.exist?(fixture_file).should be_false
|
23
35
|
end
|
24
36
|
|
25
|
-
Given /^we have a "([^\"]*)" file with (a|no) previously recorded response for "([^\"]*)"$/ do |file_name, a_or_no, url|
|
26
|
-
fixture_file = File.join(VCR::Config.
|
37
|
+
Given /^we have a "([^\"]*)" library file with (a|no) previously recorded response for "([^\"]*)"$/ do |file_name, a_or_no, url|
|
38
|
+
fixture_file = File.join(VCR::Config.cassette_library_dir, "#{file_name}.yml")
|
27
39
|
File.exist?(fixture_file).should be_true
|
28
40
|
responses = File.open(fixture_file, 'r') { |f| YAML.load(f.read) }
|
29
41
|
should_method = a_or_no == 'a' ? :should : :should_not
|
30
42
|
responses.map{ |r| URI.parse(r.uri) }.send(should_method, include(URI.parse(url)))
|
31
43
|
end
|
32
44
|
|
33
|
-
Given /^the "([^\"]*)"
|
34
|
-
Given %{we have a "#{cassette_name}" file with a previously recorded response for "#{url}"}
|
35
|
-
Then %{the "#{cassette_name}"
|
45
|
+
Given /^the "([^\"]*)" library file has a response for "([^\"]*)" that matches \/(.+)\/$/ do |cassette_name, url, regex_str|
|
46
|
+
Given %{we have a "#{cassette_name}" library file with a previously recorded response for "#{url}"}
|
47
|
+
Then %{the "#{cassette_name}" library file should have a response for "#{url}" that matches /#{regex_str}/}
|
36
48
|
end
|
37
49
|
|
38
50
|
Given /^this scenario is tagged with the vcr cassette tag: "([^\"]+)"$/ do |tag|
|
@@ -47,48 +59,57 @@ Given /^the previous scenario was tagged with the vcr cassette tag: "([^\"]*)"$/
|
|
47
59
|
VCR::CucumberTags.tags.should include(tag)
|
48
60
|
end
|
49
61
|
|
50
|
-
When /^I make an
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
When /^I make (?:an )?HTTP get request to "([^\"]*)"$/ do |url|
|
63
|
+
capture_response(url) do |uri, path|
|
64
|
+
Net::HTTP.get_response(uri)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
When /^I make an asynchronous HTTP get request to "([^\"]*)"$/ do |url|
|
69
|
+
capture_response(url) do |uri, path|
|
70
|
+
result = Net::HTTP.new(uri.host, uri.port).request_get(path) { |r| r.read_body { } }
|
71
|
+
result.body.should be_a(Net::ReadAdapter)
|
72
|
+
result
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
When /^I make a replayed asynchronous HTTP get request to "([^\"]*)"$/ do |url|
|
77
|
+
capture_response(url) do |uri, path|
|
78
|
+
result_body = ''
|
79
|
+
result = Net::HTTP.new(uri.host, uri.port).request_get(path) { |r| r.read_body { |fragment| result_body << fragment } }
|
80
|
+
result.body.should == result_body
|
81
|
+
result
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
When /^I make a recursive HTTP post request to "([^\"]*)"$/ do |url|
|
86
|
+
capture_response(url) do |uri, path|
|
87
|
+
Net::HTTP.new(uri.host, uri.port).post(path, nil)
|
66
88
|
end
|
67
|
-
@http_requests[url] += [result]
|
68
89
|
end
|
69
90
|
|
70
|
-
When /^I make
|
71
|
-
options = { :record => (record_mode ? record_mode.to_sym : :
|
91
|
+
When /^I make (.*HTTP (?:get|post)) requests? to "([^\"]*)"(?: and "([^\"]*)")? within the "([^\"]*)" ?(#{VCR::Cassette::VALID_RECORD_MODES.join('|')})? cassette(?:, allowing requests matching \/([^\/]+)\/)?$/ do |http_request_type, url1, url2, cassette_name, record_mode, allowed|
|
92
|
+
options = { :record => (record_mode ? record_mode.to_sym : :new_episodes) }
|
72
93
|
options[:allow_real_http] = lambda { |uri| uri.to_s =~ /#{allowed}/ } if allowed.to_s.size > 0
|
73
94
|
urls = [url1, url2].select { |u| u.to_s.size > 0 }
|
74
|
-
VCR.
|
95
|
+
VCR.use_cassette(cassette_name, options) do
|
75
96
|
urls.each do |url|
|
76
|
-
When %{I make
|
97
|
+
When %{I make #{http_request_type} request to "#{url}"}
|
77
98
|
end
|
78
99
|
end
|
79
100
|
end
|
80
101
|
|
81
|
-
Then /^the "([^\"]*)"
|
102
|
+
Then /^the "([^\"]*)" library file should have a response for "([^\"]*)" that matches \/(.+)\/$/ do |cassette_name, url, regex_str|
|
82
103
|
responses = recorded_responses_for(cassette_name)
|
83
104
|
responses.should have_expected_response(url, regex_str)
|
84
105
|
end
|
85
106
|
|
86
|
-
Then /^the "([^\"]*)"
|
107
|
+
Then /^the "([^\"]*)" library file should have exactly (\d+) response$/ do |cassette_name, response_count|
|
87
108
|
responses = recorded_responses_for(cassette_name)
|
88
109
|
responses.should have(response_count.to_i).responses
|
89
110
|
end
|
90
111
|
|
91
|
-
Then /^I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been
|
112
|
+
Then /^I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been ejected$/ do
|
92
113
|
# do nothing...
|
93
114
|
end
|
94
115
|
|
@@ -105,7 +126,7 @@ Then /^(?:the )?response(?: (\d+))? for "([^\"]*)" should match \/(.+)\/$/ do |r
|
|
105
126
|
@http_requests[url][response_num].body.should =~ regex
|
106
127
|
end
|
107
128
|
|
108
|
-
Then /^there should not be a "([^\"]*)"
|
109
|
-
yaml_file = File.join(VCR::Config.
|
129
|
+
Then /^there should not be a "([^\"]*)" library file$/ do |cassette_name|
|
130
|
+
yaml_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
|
110
131
|
File.exist?(yaml_file).should be_false
|
111
132
|
end
|