vcr 0.4.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +34 -0
- data/README.md +89 -21
- data/lib/vcr.rb +12 -1
- data/lib/vcr/cassette.rb +50 -27
- data/lib/vcr/config.rb +9 -0
- data/lib/vcr/deprecations.rb +15 -42
- data/lib/vcr/extensions/net_http.rb +13 -20
- data/lib/vcr/extensions/net_http_response.rb +6 -13
- data/lib/vcr/http_stubbing_adapters/fakeweb.rb +21 -3
- data/lib/vcr/http_stubbing_adapters/webmock.rb +34 -4
- data/lib/vcr/version.rb +16 -0
- metadata +90 -108
- data/.document +0 -5
- data/.gitignore +0 -22
- data/Rakefile +0 -67
- data/VERSION +0 -1
- data/benchmarks/http_stubbing_libraries.rb +0 -59
- data/features/fixtures/vcr_cassettes/1.8.6/cucumber_tags/replay_cassette1.yml +0 -43
- data/features/fixtures/vcr_cassettes/1.8.6/cucumber_tags/replay_cassette2.yml +0 -47
- data/features/fixtures/vcr_cassettes/1.8.6/cucumber_tags/replay_cassette3.yml +0 -85
- data/features/fixtures/vcr_cassettes/1.8.6/nested_replay_cassette.yml +0 -24
- data/features/fixtures/vcr_cassettes/1.8.6/not_the_real_response.yml +0 -43
- data/features/fixtures/vcr_cassettes/1.8.7/cucumber_tags/replay_cassette1.yml +0 -43
- data/features/fixtures/vcr_cassettes/1.8.7/cucumber_tags/replay_cassette2.yml +0 -47
- data/features/fixtures/vcr_cassettes/1.8.7/cucumber_tags/replay_cassette3.yml +0 -85
- data/features/fixtures/vcr_cassettes/1.8.7/nested_replay_cassette.yml +0 -24
- data/features/fixtures/vcr_cassettes/1.8.7/not_the_real_response.yml +0 -43
- data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette1.yml +0 -43
- data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette2.yml +0 -63
- data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette3.yml +0 -85
- data/features/fixtures/vcr_cassettes/1.9.1/nested_replay_cassette.yml +0 -32
- data/features/fixtures/vcr_cassettes/1.9.1/not_the_real_response.yml +0 -43
- data/features/record_response.feature +0 -77
- data/features/replay_recorded_response.feature +0 -69
- data/features/step_definitions/vcr_steps.rb +0 -144
- data/features/support/env.rb +0 -64
- data/lib/vcr/extensions/fake_web.rb +0 -20
- data/lib/vcr/extensions/net_read_adapter.rb +0 -22
- data/spec/cassette_spec.rb +0 -213
- data/spec/config_spec.rb +0 -49
- data/spec/cucumber_tags_spec.rb +0 -71
- data/spec/deprecations_spec.rb +0 -67
- data/spec/extensions/net_http_response_spec.rb +0 -86
- data/spec/extensions/net_http_spec.rb +0 -72
- data/spec/extensions/net_read_adapter_spec.rb +0 -10
- data/spec/fixtures/1.8.6/0_3_1_cassette.yml +0 -29
- data/spec/fixtures/1.8.6/cassette_spec/example.yml +0 -110
- data/spec/fixtures/1.8.6/example_net_http.yml +0 -14
- data/spec/fixtures/1.8.6/example_net_http_request.yml +0 -12
- data/spec/fixtures/1.8.6/example_net_http_response.yml +0 -25
- data/spec/fixtures/1.8.6/fake_example.com_responses.yml +0 -90
- data/spec/fixtures/1.8.7/0_3_1_cassette.yml +0 -29
- data/spec/fixtures/1.8.7/cassette_spec/example.yml +0 -110
- data/spec/fixtures/1.8.7/example_net_http.yml +0 -14
- data/spec/fixtures/1.8.7/example_net_http_request.yml +0 -12
- data/spec/fixtures/1.8.7/example_net_http_response.yml +0 -25
- data/spec/fixtures/1.8.7/fake_example.com_responses.yml +0 -90
- data/spec/fixtures/1.9.1/0_3_1_cassette.yml +0 -29
- data/spec/fixtures/1.9.1/cassette_spec/example.yml +0 -110
- data/spec/fixtures/1.9.1/example_net_http.yml +0 -14
- data/spec/fixtures/1.9.1/example_net_http_request.yml +0 -12
- data/spec/fixtures/1.9.1/example_net_http_response.yml +0 -25
- data/spec/fixtures/1.9.1/fake_example.com_responses.yml +0 -90
- data/spec/http_stubbing_adapters/fakeweb_spec.rb +0 -24
- data/spec/http_stubbing_adapters/webmock_spec.rb +0 -23
- data/spec/spec.opts +0 -2
- data/spec/spec_helper.rb +0 -35
- data/spec/structs_spec.rb +0 -95
- data/spec/support/deprecated.rb +0 -18
- data/spec/support/disable_warnings.rb +0 -12
- data/spec/support/http_stubbing_adapter.rb +0 -113
- data/spec/support/temp_cassette_library_dir.rb +0 -16
- data/spec/task_runner_spec.rb +0 -59
- data/spec/vcr_spec.rb +0 -119
- data/vcr.gemspec +0 -147
@@ -1,77 +0,0 @@
|
|
1
|
-
Feature: Record response
|
2
|
-
In order to have deterministic, fast tests that do not depend on an internet connection
|
3
|
-
As a TDD/BDD developer
|
4
|
-
I want to record responses for new requests so I can replay them in future test runs
|
5
|
-
|
6
|
-
Scenario: Record a response using VCR.use_cassette
|
7
|
-
Given we do not have a "temp/cassette" cassette
|
8
|
-
When I make an HTTP get request to "http://example.com" within the "temp/cassette" 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
|
-
|
11
|
-
@record_cassette1
|
12
|
-
Scenario: Record a response using a tagged scenario
|
13
|
-
Given we do not have a "cucumber_tags/record_cassette1" cassette
|
14
|
-
And this scenario is tagged with the vcr cassette tag: "@record_cassette1"
|
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 ejected
|
17
|
-
|
18
|
-
Scenario: Check the recorded response for the previous scenario
|
19
|
-
Given the previous scenario was tagged with the vcr cassette tag: "@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
|
-
|
22
|
-
@record_cassette2
|
23
|
-
Scenario: Use both a tagged scenario cassette and a nested cassette within a single step definition
|
24
|
-
Given we do not have a "cucumber_tags/record_cassette2" cassette
|
25
|
-
And we do not have a "temp/nested" cassette
|
26
|
-
And this scenario is tagged with the vcr cassette tag: "@record_cassette2"
|
27
|
-
When I make an HTTP get request to "http://example.com/before_nested"
|
28
|
-
And I make an HTTP get request to "http://example.com/nested" within the "temp/nested" cassette
|
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 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
|
-
|
33
|
-
Scenario: Check the recorded response for the previous scenario
|
34
|
-
Given the previous scenario was tagged with the vcr cassette tag: "@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
|
-
|
38
|
-
Scenario: Make an HTTP request in a cassette with record mode set to :all
|
39
|
-
Given we do not have a "temp/record_all_cassette" cassette
|
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" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
|
42
|
-
|
43
|
-
Scenario: Make an HTTP request in a cassette with record mode set to :none
|
44
|
-
Given we do not have a "temp/record_none_cassette" cassette
|
45
|
-
When I make an HTTP get request to "http://example.com" within the "temp/record_none_cassette" none cassette
|
46
|
-
Then the HTTP get request to "http://example.com" should result in an error that mentions VCR
|
47
|
-
And there should not be a "temp/record_none_cassette" library file
|
48
|
-
|
49
|
-
@copy_not_the_real_response_to_temp
|
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
|
-
|
57
|
-
Scenario: Record an asynchronous request (such as for mechanize)
|
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" 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
|
-
|
62
|
-
Scenario: Record a recursive post request
|
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" 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
|
-
|
68
|
-
Scenario: Make an allowed HTTP request in a cassette with record mode set to :none
|
69
|
-
Given we do not have a "temp/record_none_cassette" cassette
|
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
|
-
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" library file
|
73
|
-
|
74
|
-
Scenario: Record a request with a block with a return statement
|
75
|
-
Given we do not have a "temp/block_with_a_return" cassette
|
76
|
-
When I make a returning block HTTP get request to "http://example.com" within the "temp/block_with_a_return" new_episodes cassette
|
77
|
-
Then the "temp/block_with_a_return" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
|
@@ -1,69 +0,0 @@
|
|
1
|
-
Feature: Replay recorded response
|
2
|
-
In order to have deterministic, fast tests that do not depend on an internet connection
|
3
|
-
As a TDD/BDD developer
|
4
|
-
I want to replay responses for requests I have previously recorded
|
5
|
-
|
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
|
-
When I make an HTTP get request to "http://example.com" within the "not_the_real_response" cassette
|
9
|
-
Then the response for "http://example.com" should match /This is not the real response from example\.com/
|
10
|
-
|
11
|
-
@replay_cassette1
|
12
|
-
Scenario: Replay recorded response for a request within a tagged scenario
|
13
|
-
Given this scenario is tagged with the vcr cassette tag: "@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
|
-
When I make an HTTP get request to "http://example.com"
|
16
|
-
Then the response for "http://example.com" should match /This is not the real response from example\.com/
|
17
|
-
|
18
|
-
@replay_cassette2
|
19
|
-
Scenario: Use both a tagged scenario cassette and a nested cassette within a single step definition
|
20
|
-
Given this scenario is tagged with the vcr cassette tag: "@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
|
-
When I make an HTTP get request to "http://example.com/before_nested"
|
25
|
-
And I make an HTTP get request to "http://example.com/nested" within the "nested_replay_cassette" cassette
|
26
|
-
And I make an HTTP get request to "http://example.com/after_nested"
|
27
|
-
Then the response for "http://example.com/before_nested" should match /The before_nested response/
|
28
|
-
And the response for "http://example.com/nested" should match /The nested response/
|
29
|
-
And the response for "http://example.com/after_nested" should match /The after_nested response/
|
30
|
-
|
31
|
-
@copy_not_the_real_response_to_temp
|
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" 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
|
-
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
|
-
Then the response for "http://example.com" should match /You have reached this web page by typing.*example\.com/
|
37
|
-
And the response for "http://example.com/foo" should match /The requested URL \/foo was not found/
|
38
|
-
|
39
|
-
@copy_not_the_real_response_to_temp
|
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" 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
|
-
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
|
-
Then the response for "http://example.com" should match /This is not the real response from example\.com/
|
45
|
-
And the HTTP get request to "http://example.com/foo" should result in an error that mentions VCR
|
46
|
-
|
47
|
-
@copy_not_the_real_response_to_temp
|
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
|
-
Then the response for "http://example.com" should match /This is not the real response from example\.com/
|
53
|
-
And the response for "http://example.com/foo" should match /The requested URL \/foo was not found/
|
54
|
-
|
55
|
-
@replay_cassette3
|
56
|
-
Scenario: Replay multiple different recorded responses for requests to the same URL
|
57
|
-
Given this scenario is tagged with the vcr cassette tag: "@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
|
-
When I make an HTTP get request to "http://example.com"
|
61
|
-
And I make an HTTP get request to "http://example.com"
|
62
|
-
Then response 1 for "http://example.com" should match /This is not the real response from example\.com/
|
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/
|
@@ -1,144 +0,0 @@
|
|
1
|
-
require 'tmpdir'
|
2
|
-
|
3
|
-
module VCRHelpers
|
4
|
-
def have_expected_response(url, regex_str)
|
5
|
-
simple_matcher("a response from #{url} that matches /#{regex_str}/") do |responses|
|
6
|
-
regex = /#{regex_str}/i
|
7
|
-
responses = responses.select { |r| URI.parse(r.uri) == URI.parse(url) }
|
8
|
-
responses.detect { |r| r.response.body =~ regex }
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def recorded_interactions_for(cassette_name)
|
13
|
-
yaml_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
|
14
|
-
yaml = File.open(yaml_file, 'r') { |f| f.read }
|
15
|
-
interactions = YAML.load(yaml)
|
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
|
29
|
-
|
30
|
-
def perform_get_with_returning_block(uri, path)
|
31
|
-
Net::HTTP.new(uri.host, uri.port).request(Net::HTTP::Get.new(path, {})) do |response|
|
32
|
-
return response
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
World(VCRHelpers)
|
37
|
-
|
38
|
-
Given /^we do not have a "([^\"]*)" cassette$/ do |cassette_name|
|
39
|
-
fixture_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
|
40
|
-
File.exist?(fixture_file).should be_false
|
41
|
-
end
|
42
|
-
|
43
|
-
Given /^we have a "([^\"]*)" library file with (a|no) previously recorded response for "([^\"]*)"$/ do |file_name, a_or_no, url|
|
44
|
-
fixture_file = File.join(VCR::Config.cassette_library_dir, "#{file_name}.yml")
|
45
|
-
File.exist?(fixture_file).should be_true
|
46
|
-
responses = File.open(fixture_file, 'r') { |f| YAML.load(f.read) }
|
47
|
-
should_method = a_or_no == 'a' ? :should : :should_not
|
48
|
-
responses.map{ |r| URI.parse(r.uri) }.send(should_method, include(URI.parse(url)))
|
49
|
-
end
|
50
|
-
|
51
|
-
Given /^the "([^\"]*)" library file has a response for "([^\"]*)" that matches \/(.+)\/$/ do |cassette_name, url, regex_str|
|
52
|
-
Given %{we have a "#{cassette_name}" library file with a previously recorded response for "#{url}"}
|
53
|
-
Then %{the "#{cassette_name}" library file should have a response for "#{url}" that matches /#{regex_str}/}
|
54
|
-
end
|
55
|
-
|
56
|
-
Given /^this scenario is tagged with the vcr cassette tag: "([^\"]+)"$/ do |tag|
|
57
|
-
VCR.current_cucumber_scenario.should be_tagged_with(tag)
|
58
|
-
VCR::CucumberTags.tags.should include(tag)
|
59
|
-
end
|
60
|
-
|
61
|
-
Given /^the previous scenario was tagged with the vcr cassette tag: "([^\"]*)"$/ do |tag|
|
62
|
-
last_scenario = VCR.completed_cucumber_scenarios.last
|
63
|
-
last_scenario.should_not be_nil
|
64
|
-
last_scenario.should be_tagged_with(tag)
|
65
|
-
VCR::CucumberTags.tags.should include(tag)
|
66
|
-
end
|
67
|
-
|
68
|
-
When /^I make (?:an )?HTTP get request to "([^\"]*)"$/ do |url|
|
69
|
-
capture_response(url) do |uri, path|
|
70
|
-
Net::HTTP.get_response(uri)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
When /^I make an asynchronous HTTP get request to "([^\"]*)"$/ do |url|
|
75
|
-
capture_response(url) do |uri, path|
|
76
|
-
result = Net::HTTP.new(uri.host, uri.port).request_get(path) { |r| r.read_body { } }
|
77
|
-
result.body.should be_a(Net::ReadAdapter)
|
78
|
-
result
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
When /^I make a replayed asynchronous HTTP get request to "([^\"]*)"$/ do |url|
|
83
|
-
capture_response(url) do |uri, path|
|
84
|
-
result_body = ''
|
85
|
-
result = Net::HTTP.new(uri.host, uri.port).request_get(path) { |r| r.read_body { |fragment| result_body << fragment } }
|
86
|
-
result.body.should == result_body
|
87
|
-
result
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
When /^I make a recursive HTTP post request to "([^\"]*)"$/ do |url|
|
92
|
-
capture_response(url) do |uri, path|
|
93
|
-
Net::HTTP.new(uri.host, uri.port).post(path, nil)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
When /^I make a returning block HTTP get request to "([^\"]*)"$/ do |url|
|
98
|
-
capture_response(url) do |uri, path|
|
99
|
-
perform_get_with_returning_block(uri, path)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
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|
|
104
|
-
options = { :record => (record_mode ? record_mode.to_sym : :new_episodes) }
|
105
|
-
options[:allow_real_http] = lambda { |uri| uri.to_s =~ /#{allowed}/ } if allowed.to_s.size > 0
|
106
|
-
urls = [url1, url2].select { |u| u.to_s.size > 0 }
|
107
|
-
VCR.use_cassette(cassette_name, options) do
|
108
|
-
urls.each do |url|
|
109
|
-
When %{I make #{http_request_type} request to "#{url}"}
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
Then /^the "([^\"]*)" library file should have a response for "([^\"]*)" that matches \/(.+)\/$/ do |cassette_name, url, regex_str|
|
115
|
-
interactions = recorded_interactions_for(cassette_name)
|
116
|
-
interactions.should have_expected_response(url, regex_str)
|
117
|
-
end
|
118
|
-
|
119
|
-
Then /^the "([^\"]*)" library file should have exactly (\d+) response$/ do |cassette_name, response_count|
|
120
|
-
interactions = recorded_interactions_for(cassette_name)
|
121
|
-
interactions.should have(response_count.to_i).responses
|
122
|
-
end
|
123
|
-
|
124
|
-
Then /^I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been ejected$/ do
|
125
|
-
# do nothing...
|
126
|
-
end
|
127
|
-
|
128
|
-
Then /^the HTTP get request to "([^\"]*)" should result in an error that mentions VCR$/ do |url|
|
129
|
-
result = @http_requests[url][0]
|
130
|
-
result.should be_a(StandardError)
|
131
|
-
result.message.should =~ /VCR/
|
132
|
-
end
|
133
|
-
|
134
|
-
Then /^(?:the )?response(?: (\d+))? for "([^\"]*)" should match \/(.+)\/$/ do |response_num, url, regex_str|
|
135
|
-
response_num = response_num.to_i || 0
|
136
|
-
response_num -= 1 if response_num > 0 # translate to 0-based array index.
|
137
|
-
regex = /#{regex_str}/i
|
138
|
-
@http_requests[url][response_num].body.should =~ regex
|
139
|
-
end
|
140
|
-
|
141
|
-
Then /^there should not be a "([^\"]*)" library file$/ do |cassette_name|
|
142
|
-
yaml_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
|
143
|
-
File.exist?(yaml_file).should be_false
|
144
|
-
end
|
data/features/support/env.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
|
2
|
-
require 'vcr'
|
3
|
-
|
4
|
-
begin
|
5
|
-
require 'ruby-debug'
|
6
|
-
Debugger.start
|
7
|
-
Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
|
8
|
-
rescue LoadError
|
9
|
-
# ruby-debug wasn't available so neither can the debugging be
|
10
|
-
end
|
11
|
-
|
12
|
-
require 'spec/expectations'
|
13
|
-
|
14
|
-
VCR.config do |c|
|
15
|
-
c.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes', RUBY_VERSION)
|
16
|
-
c.http_stubbing_library = if ENV['HTTP_STUBBING_ADAPTER'].to_s == ''
|
17
|
-
warn "Using fakeweb for VCR's cucumber features since the adapter was not specified. Set HTTP_STUBBING_ADAPTER to specify."
|
18
|
-
:fakeweb
|
19
|
-
else
|
20
|
-
ENV['HTTP_STUBBING_ADAPTER'].to_sym
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
VCR.module_eval do
|
25
|
-
def self.completed_cucumber_scenarios
|
26
|
-
@completed_cucumber_scenarios ||= []
|
27
|
-
end
|
28
|
-
|
29
|
-
class << self
|
30
|
-
attr_accessor :current_cucumber_scenario
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
After do |scenario|
|
35
|
-
if raised_error = (@http_requests || {}).values.flatten.detect { |result| result.is_a?(Exception) && result.message !~ /VCR/ }
|
36
|
-
raise raised_error
|
37
|
-
end
|
38
|
-
VCR.completed_cucumber_scenarios << scenario
|
39
|
-
end
|
40
|
-
|
41
|
-
Before do |scenario|
|
42
|
-
VCR.current_cucumber_scenario = scenario
|
43
|
-
temp_dir = File.join(VCR::Config.cassette_library_dir, 'temp')
|
44
|
-
FileUtils.rm_rf(temp_dir) if File.exist?(temp_dir)
|
45
|
-
end
|
46
|
-
|
47
|
-
Before('@copy_not_the_real_response_to_temp') do
|
48
|
-
orig_file = File.join(VCR::Config.cassette_library_dir, 'not_the_real_response.yml')
|
49
|
-
temp_file = File.join(VCR::Config.cassette_library_dir, 'temp', 'not_the_real_response.yml')
|
50
|
-
FileUtils.mkdir_p(File.join(VCR::Config.cassette_library_dir, 'temp'))
|
51
|
-
FileUtils.cp orig_file, temp_file
|
52
|
-
end
|
53
|
-
|
54
|
-
at_exit do
|
55
|
-
%w(record_cassette1 record_cassette2).each do |tag|
|
56
|
-
file = File.join(VCR::Config.cassette_library_dir, 'cucumber_tags', "#{tag}.yml")
|
57
|
-
FileUtils.rm_rf(file) if File.exist?(file)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
VCR.cucumber_tags do |t|
|
62
|
-
t.tags '@record_cassette1', '@record_cassette2', :record => :new_episodes
|
63
|
-
t.tags '@replay_cassette1', '@replay_cassette2', '@replay_cassette3', :record => :none
|
64
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'fakeweb'
|
2
|
-
|
3
|
-
module FakeWeb
|
4
|
-
def self.request_uri(net_http, request)
|
5
|
-
# Copied from: http://github.com/chrisk/fakeweb/blob/fakeweb-1.2.8/lib/fake_web/ext/net_http.rb#L39-52
|
6
|
-
protocol = net_http.use_ssl? ? "https" : "http"
|
7
|
-
|
8
|
-
path = request.path
|
9
|
-
path = URI.parse(request.path).request_uri if request.path =~ /^http/
|
10
|
-
|
11
|
-
if request["authorization"] =~ /^Basic /
|
12
|
-
userinfo = FakeWeb::Utility.decode_userinfo_from_header(request["authorization"])
|
13
|
-
userinfo = FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) + "@"
|
14
|
-
else
|
15
|
-
userinfo = ""
|
16
|
-
end
|
17
|
-
|
18
|
-
"#{protocol}://#{userinfo}#{net_http.address}:#{net_http.port}#{path}"
|
19
|
-
end
|
20
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
|
3
|
-
module VCR
|
4
|
-
module NetReadAdapter
|
5
|
-
def new(*args, &block)
|
6
|
-
super.extend Extension
|
7
|
-
end
|
8
|
-
|
9
|
-
module Extension
|
10
|
-
def <<(str)
|
11
|
-
(@__body_for_vcr__ ||= '') << str
|
12
|
-
super
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_yaml(*args)
|
16
|
-
@__body_for_vcr__.to_yaml(*args)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
Net::ReadAdapter.extend VCR::NetReadAdapter
|
data/spec/cassette_spec.rb
DELETED
@@ -1,213 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
describe VCR::Cassette do
|
4
|
-
describe '#file' do
|
5
|
-
temp_dir File.expand_path(File.dirname(__FILE__) + '/fixtures/file'), :assign_to_cassette_library_dir => true
|
6
|
-
|
7
|
-
it 'combines the cassette_library_dir with the cassette name' do
|
8
|
-
cassette = VCR::Cassette.new('the_file')
|
9
|
-
cassette.file.should == File.join(VCR::Config.cassette_library_dir, 'the_file.yml')
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'strips out disallowed characters so that it is a valid file name with no spaces' do
|
13
|
-
cassette = VCR::Cassette.new("\nthis \t! is-the_13212_file name")
|
14
|
-
cassette.file.should =~ /#{Regexp.escape('_this_is-the_13212_file_name.yml')}$/
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'keeps any path separators' do
|
18
|
-
cassette = VCR::Cassette.new("dir/file_name")
|
19
|
-
cassette.file.should =~ /#{Regexp.escape('dir/file_name.yml')}$/
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'returns nil if the cassette_library_dir is not set' do
|
23
|
-
VCR::Config.cassette_library_dir = nil
|
24
|
-
cassette = VCR::Cassette.new('the_file')
|
25
|
-
cassette.file.should be_nil
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe '#record_http_interaction' do
|
30
|
-
it 'adds the interaction to #recorded_interactions' do
|
31
|
-
cassette = VCR::Cassette.new(:test_cassette)
|
32
|
-
cassette.recorded_interactions.should == []
|
33
|
-
cassette.record_http_interaction(:the_interaction)
|
34
|
-
cassette.recorded_interactions.should == [:the_interaction]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe 'on creation' do
|
39
|
-
it 'raises an error with a helpful message when loading an old unsupported cassette' do
|
40
|
-
VCR::Config.cassette_library_dir = File.expand_path(File.dirname(__FILE__) + "/fixtures/#{RUBY_VERSION}")
|
41
|
-
lambda { VCR::Cassette.new('0_3_1_cassette') }.should raise_error(/The VCR cassette 0_3_1_cassette uses an old format that is now deprecated/)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "raises an error if given an invalid record mode" do
|
45
|
-
lambda { VCR::Cassette.new(:test, :record => :not_a_record_mode) }.should raise_error(ArgumentError)
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'creates a stubs checkpoint on the http_stubbing_adapter' do
|
49
|
-
VCR.http_stubbing_adapter.should_receive(:create_stubs_checkpoint).with('example').once
|
50
|
-
VCR::Cassette.new('example')
|
51
|
-
end
|
52
|
-
|
53
|
-
VCR::Cassette::VALID_RECORD_MODES.each do |mode|
|
54
|
-
it "defaults the record mode to #{mode} when VCR::Config.default_cassette_options[:record] is #{mode}" do
|
55
|
-
VCR::Config.default_cassette_options = { :record => mode }
|
56
|
-
cassette = VCR::Cassette.new(:test)
|
57
|
-
cassette.record_mode.should == mode
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
{ :new_episodes => true, :all => true, :none => false }.each do |record_mode, http_connections_allowed|
|
62
|
-
it "sets http_connections_allowed to #{http_connections_allowed} on the http stubbing adapter when the record mode is #{record_mode}" do
|
63
|
-
VCR.http_stubbing_adapter.should_receive(:http_connections_allowed=).with(http_connections_allowed)
|
64
|
-
VCR::Cassette.new(:name, :record => record_mode)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
{ :new_episodes => true, :all => false, :none => true }.each do |record_mode, load_interactions|
|
69
|
-
it "#{load_interactions ? 'loads' : 'does not load'} the recorded interactions from the library yml file when the record mode is #{record_mode}" do
|
70
|
-
VCR::Config.cassette_library_dir = File.expand_path(File.dirname(__FILE__) + "/fixtures/#{RUBY_VERSION}/cassette_spec")
|
71
|
-
cassette = VCR::Cassette.new('example', :record => record_mode)
|
72
|
-
|
73
|
-
if load_interactions
|
74
|
-
cassette.should have(3).recorded_interactions
|
75
|
-
|
76
|
-
i1, i2, i3 = *cassette.recorded_interactions
|
77
|
-
|
78
|
-
i1.request.method.should == :get
|
79
|
-
i1.request.uri.should == 'http://example.com:80/'
|
80
|
-
i1.response.body.should =~ /You have reached this web page by typing.+example\.com/
|
81
|
-
|
82
|
-
i2.request.method.should == :get
|
83
|
-
i2.request.uri.should == 'http://example.com:80/foo'
|
84
|
-
i2.response.body.should =~ /foo was not found on this server/
|
85
|
-
|
86
|
-
i3.request.method.should == :get
|
87
|
-
i3.request.uri.should == 'http://example.com:80/'
|
88
|
-
i3.response.body.should =~ /Another example\.com response/
|
89
|
-
else
|
90
|
-
cassette.should have(0).recorded_interactions
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
it "#{load_interactions ? 'stubs' : 'does not stub'} the recorded requests with the http stubbing adapter when the record mode is #{record_mode}" do
|
95
|
-
VCR::Config.cassette_library_dir = File.expand_path(File.dirname(__FILE__) + "/fixtures/#{RUBY_VERSION}/cassette_spec")
|
96
|
-
|
97
|
-
if load_interactions
|
98
|
-
VCR.http_stubbing_adapter.should_receive(:stub_requests).with([an_instance_of(VCR::HTTPInteraction)]*3)
|
99
|
-
else
|
100
|
-
VCR.http_stubbing_adapter.should_receive(:stub_requests).never
|
101
|
-
end
|
102
|
-
|
103
|
-
cassette = VCR::Cassette.new('example', :record => record_mode)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
describe '#allow_real_http_requests_to?' do
|
109
|
-
it 'delegates to the :allow_real_http lambda' do
|
110
|
-
[true, false].each do |value|
|
111
|
-
yielded_uri = nil
|
112
|
-
c = VCR::Cassette.new('example', :allow_real_http => lambda { |uri| yielded_uri = uri; value })
|
113
|
-
c.allow_real_http_requests_to?(:the_uri).should == value
|
114
|
-
yielded_uri.should == :the_uri
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'returns true for localhost requests when the :allow_real_http option is set to :localhost' do
|
119
|
-
c = VCR::Cassette.new('example', :allow_real_http => :localhost)
|
120
|
-
c.allow_real_http_requests_to?(URI('http://localhost')).should be_true
|
121
|
-
c.allow_real_http_requests_to?(URI('http://example.com')).should be_false
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'returns false when no option is set' do
|
125
|
-
c = VCR::Cassette.new('example')
|
126
|
-
c.allow_real_http_requests_to?(URI('http://localhost')).should be_false
|
127
|
-
c.allow_real_http_requests_to?(URI('http://example.com')).should be_false
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'delegates to the default :allow_real_http lambda' do
|
131
|
-
[true, false].each do |value|
|
132
|
-
yielded_uri = nil
|
133
|
-
VCR::Config.default_cassette_options.merge!(:allow_real_http => lambda { |uri| yielded_uri = uri; value })
|
134
|
-
c = VCR::Cassette.new('example')
|
135
|
-
c.allow_real_http_requests_to?(:the_uri).should == value
|
136
|
-
yielded_uri.should == :the_uri
|
137
|
-
end
|
138
|
-
|
139
|
-
VCR::Config.default_cassette_options.merge!(:allow_real_http => :localhost)
|
140
|
-
c = VCR::Cassette.new('example')
|
141
|
-
c.allow_real_http_requests_to?(URI('http://localhost')).should be_true
|
142
|
-
c.allow_real_http_requests_to?(URI('http://example.com')).should be_false
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
describe '#eject' do
|
147
|
-
temp_dir File.expand_path(File.dirname(__FILE__) + '/fixtures/cassette_spec_eject'), :assign_to_cassette_library_dir => true
|
148
|
-
|
149
|
-
[true, false].each do |orig_http_connections_allowed|
|
150
|
-
it "resets #{orig_http_connections_allowed} on the http stubbing adapter if it was originally #{orig_http_connections_allowed}" do
|
151
|
-
VCR.http_stubbing_adapter.should_receive(:http_connections_allowed?).and_return(orig_http_connections_allowed)
|
152
|
-
cassette = VCR::Cassette.new(:name)
|
153
|
-
VCR.http_stubbing_adapter.should_receive(:http_connections_allowed=).with(orig_http_connections_allowed)
|
154
|
-
cassette.eject
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
it "writes the recorded interactions to disk as yaml" do
|
159
|
-
recorded_interactions = [
|
160
|
-
VCR::HTTPInteraction.new(:req_sig_1, :response_1),
|
161
|
-
VCR::HTTPInteraction.new(:req_sig_2, :response_2),
|
162
|
-
VCR::HTTPInteraction.new(:req_sig_3, :response_3)
|
163
|
-
]
|
164
|
-
|
165
|
-
cassette = VCR::Cassette.new(:eject_test)
|
166
|
-
cassette.stub!(:recorded_interactions).and_return(recorded_interactions)
|
167
|
-
|
168
|
-
lambda { cassette.eject }.should change { File.exist?(cassette.file) }.from(false).to(true)
|
169
|
-
saved_recorded_interactions = File.open(cassette.file, "r") { |f| YAML.load(f.read) }
|
170
|
-
saved_recorded_interactions.should == recorded_interactions
|
171
|
-
end
|
172
|
-
|
173
|
-
it "writes the recorded interactions to a subdirectory if the cassette name includes a directory" do
|
174
|
-
recorded_interactions = [VCR::HTTPInteraction.new(:the_request, :the_response)]
|
175
|
-
cassette = VCR::Cassette.new('subdirectory/test_cassette')
|
176
|
-
cassette.stub!(:recorded_interactions).and_return(recorded_interactions)
|
177
|
-
|
178
|
-
lambda { cassette.eject }.should change { File.exist?(cassette.file) }.from(false).to(true)
|
179
|
-
saved_recorded_interactions = File.open(cassette.file, "r") { |f| YAML.load(f.read) }
|
180
|
-
saved_recorded_interactions.should == recorded_interactions
|
181
|
-
end
|
182
|
-
|
183
|
-
it "writes both old and new recorded interactions to disk" do
|
184
|
-
file = File.expand_path(File.dirname(__FILE__) + "/fixtures/#{RUBY_VERSION}/cassette_spec/example.yml")
|
185
|
-
FileUtils.cp file, File.join(@temp_dir, 'previously_recorded_interactions.yml')
|
186
|
-
cassette = VCR::Cassette.new('previously_recorded_interactions')
|
187
|
-
cassette.should have(3).recorded_interactions
|
188
|
-
new_recorded_interaction = VCR::HTTPInteraction.new(:the_request, :the_response)
|
189
|
-
cassette.record_http_interaction(new_recorded_interaction)
|
190
|
-
cassette.eject
|
191
|
-
saved_recorded_interactions = File.open(cassette.file, "r") { |f| YAML.load(f.read) }
|
192
|
-
saved_recorded_interactions.should have(4).recorded_interactions
|
193
|
-
saved_recorded_interactions.last.should == new_recorded_interaction
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
describe '#eject for a cassette with previously recorded interactions' do
|
198
|
-
it "restore the stubs checkpoint on the http stubbing adapter" do
|
199
|
-
VCR::Config.cassette_library_dir = File.expand_path(File.dirname(__FILE__) + "/fixtures/#{RUBY_VERSION}/cassette_spec")
|
200
|
-
cassette = VCR::Cassette.new('example', :record => :none)
|
201
|
-
VCR.http_stubbing_adapter.should_receive(:restore_stubs_checkpoint).with('example')
|
202
|
-
cassette.eject
|
203
|
-
end
|
204
|
-
|
205
|
-
it "does not re-write to disk the previously recorded interactions if there are no new ones" do
|
206
|
-
VCR::Config.cassette_library_dir = File.expand_path(File.dirname(__FILE__) + "/fixtures/#{RUBY_VERSION}/cassette_spec")
|
207
|
-
yaml_file = File.join(VCR::Config.cassette_library_dir, 'example.yml')
|
208
|
-
cassette = VCR::Cassette.new('example', :record => :none)
|
209
|
-
File.should_not_receive(:open).with(cassette.file, 'w')
|
210
|
-
lambda { cassette.eject }.should_not change { File.mtime(yaml_file) }
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|