vcr 0.4.1 → 1.0.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/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
|