vcr 0.2.0 → 0.3.0
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/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
|