vcr 3.0.3 → 6.2.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.
- checksums.yaml +5 -5
- data/lib/vcr/cassette/erb_renderer.rb +4 -2
- data/lib/vcr/cassette/http_interaction_list.rb +14 -9
- data/lib/vcr/cassette/migrator.rb +5 -6
- data/lib/vcr/cassette/persisters/file_system.rb +9 -1
- data/lib/vcr/cassette/serializers/compressed.rb +2 -2
- data/lib/vcr/cassette/serializers/json.rb +14 -8
- data/lib/vcr/cassette/serializers/psych.rb +10 -2
- data/lib/vcr/cassette/serializers/syck.rb +7 -1
- data/lib/vcr/cassette/serializers/yaml.rb +14 -2
- data/lib/vcr/cassette/serializers.rb +10 -0
- data/lib/vcr/cassette.rb +63 -16
- data/lib/vcr/configuration.rb +21 -8
- data/lib/vcr/deprecations.rb +0 -62
- data/lib/vcr/errors.rb +17 -12
- data/lib/vcr/library_hooks/excon.rb +8 -0
- data/lib/vcr/library_hooks/typhoeus.rb +91 -79
- data/lib/vcr/library_hooks/webmock.rb +2 -11
- data/lib/vcr/linked_cassette.rb +4 -4
- data/lib/vcr/middleware/excon.rb +1 -1
- data/lib/vcr/middleware/faraday.rb +29 -2
- data/lib/vcr/request_ignorer.rb +8 -1
- data/lib/vcr/request_matcher_registry.rb +3 -3
- data/lib/vcr/structs.rb +48 -32
- data/lib/vcr/test_frameworks/cucumber.rb +16 -5
- data/lib/vcr/test_frameworks/rspec.rb +34 -22
- data/lib/vcr/util/hooks.rb +1 -0
- data/lib/vcr/util/internet_connection.rb +15 -21
- data/lib/vcr/version.rb +2 -2
- data/lib/vcr.rb +52 -2
- metadata +45 -272
- data/features/CHANGELOG.md +0 -710
- data/features/CONTRIBUTING.md +0 -26
- data/features/LICENSE.md +0 -20
- data/features/README.md +0 -339
- data/features/Upgrade.md +0 -289
- data/features/about_these_examples.md +0 -18
- data/features/cassettes/allow_unused_http_interactions.feature +0 -100
- data/features/cassettes/automatic_re_recording.feature +0 -72
- data/features/cassettes/decompress.feature +0 -74
- data/features/cassettes/dynamic_erb.feature +0 -100
- data/features/cassettes/exclusive.feature +0 -126
- data/features/cassettes/format.feature +0 -411
- data/features/cassettes/freezing_time.feature +0 -68
- data/features/cassettes/naming.feature +0 -28
- data/features/cassettes/no_cassette.feature +0 -152
- data/features/cassettes/update_content_length_header.feature +0 -112
- data/features/configuration/allow_http_connections_when_no_cassette.feature +0 -55
- data/features/configuration/cassette_library_dir.feature +0 -31
- data/features/configuration/debug_logging.feature +0 -58
- data/features/configuration/default_cassette_options.feature +0 -100
- data/features/configuration/filter_sensitive_data.feature +0 -153
- data/features/configuration/hook_into.feature +0 -172
- data/features/configuration/ignore_request.feature +0 -192
- data/features/configuration/preserve_exact_body_bytes.feature +0 -108
- data/features/configuration/query_parser.feature +0 -84
- data/features/configuration/uri_parser.feature +0 -93
- data/features/getting_started.md +0 -82
- data/features/hooks/after_http_request.feature +0 -58
- data/features/hooks/around_http_request.feature +0 -57
- data/features/hooks/before_http_request.feature +0 -63
- data/features/hooks/before_playback.feature +0 -184
- data/features/hooks/before_record.feature +0 -172
- data/features/http_libraries/em_http_request.feature +0 -250
- data/features/http_libraries/net_http.feature +0 -179
- data/features/middleware/faraday.feature +0 -56
- data/features/middleware/rack.feature +0 -92
- data/features/record_modes/all.feature +0 -82
- data/features/record_modes/new_episodes.feature +0 -79
- data/features/record_modes/none.feature +0 -72
- data/features/record_modes/once.feature +0 -95
- data/features/request_matching/README.md +0 -30
- data/features/request_matching/body.feature +0 -91
- data/features/request_matching/body_as_json.feature +0 -90
- data/features/request_matching/custom_matcher.feature +0 -135
- data/features/request_matching/headers.feature +0 -85
- data/features/request_matching/host.feature +0 -95
- data/features/request_matching/identical_request_sequence.feature +0 -89
- data/features/request_matching/method.feature +0 -96
- data/features/request_matching/path.feature +0 -96
- data/features/request_matching/playback_repeats.feature +0 -98
- data/features/request_matching/query.feature +0 -97
- data/features/request_matching/uri.feature +0 -94
- data/features/request_matching/uri_without_param.feature +0 -101
- data/features/step_definitions/cli_steps.rb +0 -199
- data/features/support/env.rb +0 -46
- data/features/support/http_lib_filters.rb +0 -46
- data/features/test_frameworks/cucumber.feature +0 -211
- data/features/test_frameworks/rspec_macro.feature +0 -81
- data/features/test_frameworks/rspec_metadata.feature +0 -150
- data/features/test_frameworks/test_unit.feature +0 -49
- data/lib/vcr/extensions/net_http_response.rb +0 -36
- data/lib/vcr/library_hooks/fakeweb.rb +0 -197
- data/lib/vcr/library_hooks/typhoeus_0.4.rb +0 -103
- data/spec/acceptance/concurrency_spec.rb +0 -51
- data/spec/acceptance/threading_spec.rb +0 -34
- data/spec/fixtures/cassette_spec/1_x_cassette.yml +0 -110
- data/spec/fixtures/cassette_spec/empty.yml +0 -0
- data/spec/fixtures/cassette_spec/example.yml +0 -111
- data/spec/fixtures/cassette_spec/with_localhost_requests.yml +0 -111
- data/spec/fixtures/fake_example_responses.yml +0 -110
- data/spec/fixtures/match_requests_on.yml +0 -187
- data/spec/lib/vcr/cassette/erb_renderer_spec.rb +0 -53
- data/spec/lib/vcr/cassette/http_interaction_list_spec.rb +0 -295
- data/spec/lib/vcr/cassette/migrator_spec.rb +0 -196
- data/spec/lib/vcr/cassette/persisters/file_system_spec.rb +0 -75
- data/spec/lib/vcr/cassette/persisters_spec.rb +0 -39
- data/spec/lib/vcr/cassette/serializers_spec.rb +0 -182
- data/spec/lib/vcr/cassette_spec.rb +0 -618
- data/spec/lib/vcr/configuration_spec.rb +0 -326
- data/spec/lib/vcr/deprecations_spec.rb +0 -85
- data/spec/lib/vcr/errors_spec.rb +0 -178
- data/spec/lib/vcr/extensions/net_http_response_spec.rb +0 -86
- data/spec/lib/vcr/library_hooks/excon_spec.rb +0 -104
- data/spec/lib/vcr/library_hooks/fakeweb_spec.rb +0 -169
- data/spec/lib/vcr/library_hooks/faraday_spec.rb +0 -68
- data/spec/lib/vcr/library_hooks/typhoeus_0.4_spec.rb +0 -36
- data/spec/lib/vcr/library_hooks/typhoeus_spec.rb +0 -162
- data/spec/lib/vcr/library_hooks/webmock_spec.rb +0 -117
- data/spec/lib/vcr/library_hooks_spec.rb +0 -51
- data/spec/lib/vcr/middleware/faraday_spec.rb +0 -181
- data/spec/lib/vcr/middleware/rack_spec.rb +0 -115
- data/spec/lib/vcr/request_ignorer_spec.rb +0 -70
- data/spec/lib/vcr/request_matcher_registry_spec.rb +0 -345
- data/spec/lib/vcr/structs_spec.rb +0 -732
- data/spec/lib/vcr/test_frameworks/cucumber_spec.rb +0 -107
- data/spec/lib/vcr/test_frameworks/rspec_spec.rb +0 -94
- data/spec/lib/vcr/util/hooks_spec.rb +0 -158
- data/spec/lib/vcr/util/internet_connection_spec.rb +0 -37
- data/spec/lib/vcr/util/version_checker_spec.rb +0 -31
- data/spec/lib/vcr/version_spec.rb +0 -27
- data/spec/lib/vcr_spec.rb +0 -354
- data/spec/monkey_patches.rb +0 -186
- data/spec/spec_helper.rb +0 -63
- data/spec/support/configuration_stubbing.rb +0 -8
- data/spec/support/cucumber_helpers.rb +0 -39
- data/spec/support/fixnum_extension.rb +0 -10
- data/spec/support/http_library_adapters.rb +0 -289
- data/spec/support/limited_uri.rb +0 -21
- data/spec/support/ruby_interpreter.rb +0 -7
- data/spec/support/shared_example_groups/excon.rb +0 -63
- data/spec/support/shared_example_groups/hook_into_http_library.rb +0 -594
- data/spec/support/shared_example_groups/request_hooks.rb +0 -59
- data/spec/support/sinatra_app.rb +0 -86
- data/spec/support/vcr_localhost_server.rb +0 -76
- data/spec/support/vcr_stub_helpers.rb +0 -17
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
Feature: URI without param(s)
|
|
2
|
-
|
|
3
|
-
A common source of difficulty when using VCR with the default matchers
|
|
4
|
-
are non-deterministic URIs. If the URI changes on every test run (because
|
|
5
|
-
it includes a timestamp parameter, or whatever), the default URI matcher
|
|
6
|
-
will not work well for you.
|
|
7
|
-
|
|
8
|
-
You can write a custom matcher to match URIs however you want, but for the
|
|
9
|
-
common need to match on a URI and ignore particular query parameters, VCR
|
|
10
|
-
provides an easier way:
|
|
11
|
-
|
|
12
|
-
:match_requests_on => [
|
|
13
|
-
:method,
|
|
14
|
-
VCR.request_matchers.uri_without_param(:timestamp)
|
|
15
|
-
]
|
|
16
|
-
|
|
17
|
-
`uri_without_param` also has a plural alias (i.e. `uri_without_params(:timestamp, :session)`)
|
|
18
|
-
|
|
19
|
-
Background:
|
|
20
|
-
Given a previously recorded cassette file "cassettes/example.yml" with:
|
|
21
|
-
"""
|
|
22
|
-
---
|
|
23
|
-
http_interactions:
|
|
24
|
-
- request:
|
|
25
|
-
method: get
|
|
26
|
-
uri: http://example.com/search?q=foo×tamp=1316920490
|
|
27
|
-
body:
|
|
28
|
-
encoding: UTF-8
|
|
29
|
-
string: ""
|
|
30
|
-
headers: {}
|
|
31
|
-
response:
|
|
32
|
-
status:
|
|
33
|
-
code: 200
|
|
34
|
-
message: OK
|
|
35
|
-
headers:
|
|
36
|
-
Content-Length:
|
|
37
|
-
- "12"
|
|
38
|
-
body:
|
|
39
|
-
encoding: UTF-8
|
|
40
|
-
string: foo response
|
|
41
|
-
http_version: "1.1"
|
|
42
|
-
recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
|
|
43
|
-
- request:
|
|
44
|
-
method: get
|
|
45
|
-
uri: http://example.com/search?q=bar×tamp=1296723437
|
|
46
|
-
body:
|
|
47
|
-
encoding: UTF-8
|
|
48
|
-
string: ""
|
|
49
|
-
headers: {}
|
|
50
|
-
response:
|
|
51
|
-
status:
|
|
52
|
-
code: 200
|
|
53
|
-
message: OK
|
|
54
|
-
headers:
|
|
55
|
-
Content-Length:
|
|
56
|
-
- "12"
|
|
57
|
-
body:
|
|
58
|
-
encoding: UTF-8
|
|
59
|
-
string: bar response
|
|
60
|
-
http_version: "1.1"
|
|
61
|
-
recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
|
|
62
|
-
recorded_with: VCR 2.0.0
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
Scenario: Match the URI on all but the timestamp query parameter
|
|
66
|
-
And a file named "uri_without_param_matcher.rb" with:
|
|
67
|
-
"""ruby
|
|
68
|
-
include_http_adapter_for("net/http")
|
|
69
|
-
|
|
70
|
-
require 'vcr'
|
|
71
|
-
|
|
72
|
-
VCR.configure do |c|
|
|
73
|
-
c.hook_into :webmock
|
|
74
|
-
c.cassette_library_dir = 'cassettes'
|
|
75
|
-
c.default_cassette_options = {
|
|
76
|
-
:match_requests_on => [:method,
|
|
77
|
-
VCR.request_matchers.uri_without_param(:timestamp)]
|
|
78
|
-
}
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def search_uri(q)
|
|
82
|
-
"http://example.com/search?q=#{q}×tamp=#{Time.now.to_i}"
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
VCR.use_cassette('example') do
|
|
86
|
-
puts "Response for bar: " +
|
|
87
|
-
response_body_for(:get, search_uri("bar"))
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
VCR.use_cassette('example') do
|
|
91
|
-
puts "Response for foo: " +
|
|
92
|
-
response_body_for(:get, search_uri("foo"))
|
|
93
|
-
end
|
|
94
|
-
"""
|
|
95
|
-
When I run `ruby uri_without_param_matcher.rb`
|
|
96
|
-
Then it should pass with:
|
|
97
|
-
"""
|
|
98
|
-
Response for bar: bar response
|
|
99
|
-
Response for foo: foo response
|
|
100
|
-
"""
|
|
101
|
-
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
require 'vcr'
|
|
2
|
-
require 'multi_json'
|
|
3
|
-
|
|
4
|
-
module VCRHelpers
|
|
5
|
-
|
|
6
|
-
def normalize_cassette_hash(cassette_hash)
|
|
7
|
-
cassette_hash['recorded_with'] = "VCR #{VCR.version}"
|
|
8
|
-
cassette_hash['http_interactions'].map! { |h| normalize_http_interaction(h) }
|
|
9
|
-
cassette_hash
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def normalize_headers(object)
|
|
13
|
-
object.headers = {} and return if object.headers.nil?
|
|
14
|
-
object.headers = {}.tap do |hash|
|
|
15
|
-
object.headers.each do |key, value|
|
|
16
|
-
hash[key.downcase] = value
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def static_timestamp
|
|
22
|
-
@static_timestamp ||= Time.now
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def normalize_http_interaction(hash)
|
|
26
|
-
VCR::HTTPInteraction.from_hash(hash).tap do |i|
|
|
27
|
-
normalize_headers(i.request)
|
|
28
|
-
normalize_headers(i.response)
|
|
29
|
-
|
|
30
|
-
i.recorded_at &&= static_timestamp
|
|
31
|
-
i.request.body ||= ''
|
|
32
|
-
i.response.body ||= ''
|
|
33
|
-
i.response.status.message ||= ''
|
|
34
|
-
i.response.adapter_metadata.clear
|
|
35
|
-
|
|
36
|
-
# Remove non-deterministic headers and headers
|
|
37
|
-
# that get added by a particular HTTP library (but not by others)
|
|
38
|
-
i.response.headers.reject! { |k, v| %w[ server date connection ].include?(k) }
|
|
39
|
-
i.request.headers.reject! { |k, v| %w[ accept user-agent connection expect date ].include?(k) }
|
|
40
|
-
|
|
41
|
-
# Some HTTP libraries include an extra space ("OK " instead of "OK")
|
|
42
|
-
i.response.status.message = i.response.status.message.strip
|
|
43
|
-
|
|
44
|
-
if @scenario_parameters.to_s =~ /excon|faraday/
|
|
45
|
-
# Excon/Faraday do not expose the status message or http version,
|
|
46
|
-
# so we have no way to record these attributes.
|
|
47
|
-
i.response.status.message = nil
|
|
48
|
-
i.response.http_version = nil
|
|
49
|
-
elsif @scenario_parameters.to_s.include?('webmock')
|
|
50
|
-
# WebMock does not expose the HTTP version so we have no way to record it
|
|
51
|
-
i.response.http_version = nil
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def normalize_cassette_content(content)
|
|
57
|
-
return content unless @scenario_parameters.to_s.include?('patron')
|
|
58
|
-
cassette_hash = YAML.load(content)
|
|
59
|
-
cassette_hash['http_interactions'].map! do |hash|
|
|
60
|
-
VCR::HTTPInteraction.from_hash(hash).tap do |i|
|
|
61
|
-
i.request.headers = (i.request.headers || {}).merge!('Expect' => [''])
|
|
62
|
-
end.to_hash
|
|
63
|
-
end
|
|
64
|
-
YAML.dump(cassette_hash)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def modify_file(file_name, orig_text, new_text)
|
|
68
|
-
in_current_dir do
|
|
69
|
-
file = File.read(file_name)
|
|
70
|
-
regex = /#{Regexp.escape(orig_text)}/
|
|
71
|
-
expect(file).to match(regex)
|
|
72
|
-
|
|
73
|
-
file = file.gsub(regex, new_text)
|
|
74
|
-
File.open(file_name, 'w') { |f| f.write(file) }
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
World(VCRHelpers)
|
|
79
|
-
|
|
80
|
-
Given(/the following files do not exist:/) do |files|
|
|
81
|
-
check_file_presence(files.raw.map{|file_row| file_row[0]}, false)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
Given(/^the directory "([^"]*)" does not exist$/) do |dir|
|
|
85
|
-
check_directory_presence([dir], false)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
Given(/^a previously recorded cassette file "([^"]*)" with:$/) do |file_name, content|
|
|
89
|
-
write_file(file_name, normalize_cassette_content(content))
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
Given(/^it is (.*)$/) do |date_string|
|
|
93
|
-
set_env('DATE_STRING', date_string)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
Given(/^that port numbers in "([^"]*)" are normalized to "([^"]*)"$/) do |file_name, port|
|
|
97
|
-
in_current_dir do
|
|
98
|
-
contents = File.read(file_name)
|
|
99
|
-
contents = contents.gsub(/:\d{2,}\//, ":#{port}/")
|
|
100
|
-
File.open(file_name, 'w') { |f| f.write(contents) }
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
When(/^I modify the file "([^"]*)" to replace "([^"]*)" with "([^"]*)"$/) do |file_name, orig_text, new_text|
|
|
105
|
-
modify_file(file_name, orig_text, new_text)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
When(/^I append to file "([^"]*)":$/) do |file_name, content|
|
|
109
|
-
append_to_file(file_name, "\n" + content)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
When(/^I set the "([^"]*)" environment variable to "([^"]*)"$/) do |var, value|
|
|
113
|
-
set_env(var, value)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
Then(/^the file "([^"]*)" should exist$/) do |file_name|
|
|
117
|
-
check_file_presence([file_name], true)
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
Then(/^it should (pass|fail) with "([^"]*)"$/) do |pass_fail, partial_output|
|
|
121
|
-
assert_exit_status_and_partial_output(pass_fail == 'pass', partial_output)
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
Then(/^it should (pass|fail) with an error like:$/) do |pass_fail, partial_output|
|
|
125
|
-
assert_success(pass_fail == 'pass')
|
|
126
|
-
|
|
127
|
-
# different implementations place the exception class at different
|
|
128
|
-
# places relative to the message (i.e. with a multiline error message)
|
|
129
|
-
process_output = all_output.gsub(/\s*\(VCR::Errors::\w+\)/, '')
|
|
130
|
-
|
|
131
|
-
# Some implementations include extra leading spaces, for some reason...
|
|
132
|
-
process_output.gsub!(/^\s*/, '')
|
|
133
|
-
partial_output.gsub!(/^\s*/, '')
|
|
134
|
-
|
|
135
|
-
assert_partial_output(partial_output, process_output)
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
Then(/^the output should contain each of the following:$/) do |table|
|
|
139
|
-
table.raw.flatten.each do |string|
|
|
140
|
-
assert_partial_output(string, all_output)
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
Then(/^the file "([^"]*)" should contain YAML like:$/) do |file_name, expected_content|
|
|
145
|
-
actual_content = in_current_dir { File.read(file_name) }
|
|
146
|
-
expect(normalize_cassette_hash(YAML.load(actual_content))).to eq(normalize_cassette_hash(YAML.load(expected_content.to_s)))
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
Then(/^the file "([^"]*)" should contain JSON like:$/) do |file_name, expected_content|
|
|
150
|
-
actual_content = in_current_dir { File.read(file_name) }
|
|
151
|
-
actual = MultiJson.decode(actual_content)
|
|
152
|
-
expected = MultiJson.decode(expected_content.to_s)
|
|
153
|
-
expect(normalize_cassette_hash(actual)).to eq(normalize_cassette_hash(expected))
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
Then(/^the file "([^"]*)" should contain compressed YAML like:$/) do |file_name, expected_content|
|
|
157
|
-
actual_content = in_current_dir { File.read(file_name) }
|
|
158
|
-
unzipped_content = Zlib::Inflate.inflate(actual_content)
|
|
159
|
-
expect(normalize_cassette_hash(YAML.load(unzipped_content))).to eq(normalize_cassette_hash(YAML.load(expected_content.to_s)))
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
Then(/^the file "([^"]*)" should contain ruby like:$/) do |file_name, expected_content|
|
|
163
|
-
actual_content = in_current_dir { File.read(file_name) }
|
|
164
|
-
actual = eval(actual_content)
|
|
165
|
-
expected = eval(expected_content)
|
|
166
|
-
expect(normalize_cassette_hash(actual)).to eq(normalize_cassette_hash(expected))
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
Then(/^the file "([^"]*)" should contain each of these:$/) do |file_name, table|
|
|
170
|
-
table.raw.flatten.each do |string|
|
|
171
|
-
check_file_content(file_name, string, true)
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
Then(/^the file "([^"]*)" should contain a YAML fragment like:$/) do |file_name, fragment|
|
|
176
|
-
in_current_dir do
|
|
177
|
-
file_content = File.read(file_name)
|
|
178
|
-
|
|
179
|
-
# Normalize by removing leading and trailing whitespace...
|
|
180
|
-
file_content = file_content.split("\n").map do |line|
|
|
181
|
-
# Different versions of psych use single vs. double quotes
|
|
182
|
-
# And then 2.1 sometimes adds quotes...
|
|
183
|
-
line.strip.gsub('"', "'").gsub("'", '')
|
|
184
|
-
end.join("\n")
|
|
185
|
-
|
|
186
|
-
expect(file_content).to include(fragment.gsub("'", ''))
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
Then(/^the cassette "([^"]*)" should have the following response bodies:$/) do |file, table|
|
|
191
|
-
interactions = in_current_dir { YAML.load_file(file) }['http_interactions'].map { |h| VCR::HTTPInteraction.from_hash(h) }
|
|
192
|
-
actual_response_bodies = interactions.map { |i| i.response.body }
|
|
193
|
-
expected_response_bodies = table.raw.flatten
|
|
194
|
-
expect(actual_response_bodies).to match(expected_response_bodies)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
Then(/^it should (pass|fail)$/) do |pass_fail|
|
|
198
|
-
assert_success(pass_fail == 'pass')
|
|
199
|
-
end
|
data/features/support/env.rb
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
require 'bundler'
|
|
2
|
-
Bundler.setup
|
|
3
|
-
|
|
4
|
-
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
|
|
5
|
-
|
|
6
|
-
require 'aruba/cucumber'
|
|
7
|
-
require 'aruba/jruby' if RUBY_PLATFORM == 'java'
|
|
8
|
-
|
|
9
|
-
gem_specs = Bundler.load.specs
|
|
10
|
-
load_paths = Dir.glob(gem_specs.map { |spec|
|
|
11
|
-
if spec.respond_to?(:lib_dirs_glob)
|
|
12
|
-
spec.lib_dirs_glob
|
|
13
|
-
else
|
|
14
|
-
spec.load_paths
|
|
15
|
-
end
|
|
16
|
-
}.flatten)
|
|
17
|
-
|
|
18
|
-
load_paths << File.expand_path("../../../spec", __FILE__)
|
|
19
|
-
rubyopt = "-rsupport/cucumber_helpers"
|
|
20
|
-
|
|
21
|
-
if RUBY_VERSION > '1.9'
|
|
22
|
-
load_paths.unshift(".")
|
|
23
|
-
rubyopt = "--disable-gems #{rubyopt}" unless "rbx" == ruby_engine
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
Before do
|
|
27
|
-
@aruba_timeout_seconds = 30
|
|
28
|
-
if "jruby" == ruby_engine
|
|
29
|
-
@aruba_io_wait_seconds = 0.1
|
|
30
|
-
else
|
|
31
|
-
@aruba_io_wait_seconds = 0.02
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
Before("~@with-bundler") do
|
|
36
|
-
set_env("RUBYLIB", load_paths.join(":"))
|
|
37
|
-
set_env("RUBYOPT", rubyopt)
|
|
38
|
-
set_env("RBXOPT", "--disable-gems #{ENV["RBXOPT"]}") if "rbx" == ruby_engine
|
|
39
|
-
set_env("GEM_HOME", nil)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
Before("@with-bundler") do
|
|
43
|
-
set_env("RUBYLIB", ".:#{ENV["RUBYLIB"]}:#{load_paths.last}")
|
|
44
|
-
set_env("RUBYOPT", "#{ENV["RUBYOPT"]} -rsupport/cucumber_helpers")
|
|
45
|
-
set_env("BUNDLE_GEMFILE", Bundler.default_gemfile.expand_path.to_s)
|
|
46
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
if RUBY_VERSION == '1.8.7'
|
|
2
|
-
# We get timeouts on 1.8.7 w/ Patron for some reason.
|
|
3
|
-
UNSUPPORTED_HTTP_LIBS = %w[ patron ]
|
|
4
|
-
elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
|
5
|
-
# Patron is freezing up the cukes (as it does on 1.9.2)
|
|
6
|
-
|
|
7
|
-
# I'm not sure why em-http-request isn't working on rbx,
|
|
8
|
-
# but considering the fact that VCR works with all the other
|
|
9
|
-
# libs just fine and doesn't do anything for em-http-request,
|
|
10
|
-
# it's probably a bug in it or rbx...so ignore it, for now.
|
|
11
|
-
|
|
12
|
-
# I'm getting errors in the curb C extension in rbx.
|
|
13
|
-
|
|
14
|
-
# Typhoeus should be buildable on rbx, but the travis build times out,
|
|
15
|
-
# so we skip them to speed up the build on travis.
|
|
16
|
-
UNSUPPORTED_HTTP_LIBS = %w[ patron em-http-request curb typhoeus ]
|
|
17
|
-
elsif RUBY_PLATFORM == 'java'
|
|
18
|
-
# These gems have C extensions and can't install on JRuby.
|
|
19
|
-
c_dependent_libs = %w[ typhoeus patron curb em-http-request ]
|
|
20
|
-
|
|
21
|
-
# The latest version of httpclient seems to freeze up the cukes
|
|
22
|
-
# on JRuby. I'm not sure why, and there's little benefit to running
|
|
23
|
-
# them on JRuby...so we just skip them. Excon seems to have the same issue :(.
|
|
24
|
-
UNSUPPORTED_HTTP_LIBS = c_dependent_libs + %w[ httpclient excon ]
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
if defined?(UNSUPPORTED_HTTP_LIBS)
|
|
28
|
-
UNSUPPORTED_HTTP_LIB_REGEX = Regexp.union(*UNSUPPORTED_HTTP_LIBS)
|
|
29
|
-
|
|
30
|
-
# Filter out example rows that use libraries that are not supported on the current ruby interpreter
|
|
31
|
-
Before do |scenario|
|
|
32
|
-
if scenario.respond_to?(:cell_values) && scenario.cell_values.any? { |v| v =~ UNSUPPORTED_HTTP_LIB_REGEX }
|
|
33
|
-
scenario.skip_invoke!
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Set a global based on the current stubbing lib so we can put special-case
|
|
39
|
-
# logic in our step definitions based on the http stubbing library.
|
|
40
|
-
Before do |scenario|
|
|
41
|
-
if scenario.respond_to?(:cell_values)
|
|
42
|
-
@scenario_parameters = scenario.cell_values
|
|
43
|
-
else
|
|
44
|
-
@scenario_parameters = nil
|
|
45
|
-
end
|
|
46
|
-
end
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
@with-bundler
|
|
2
|
-
Feature: Usage with Cucumber
|
|
3
|
-
|
|
4
|
-
VCR can be used with cucumber in two basic ways:
|
|
5
|
-
|
|
6
|
-
- Use `VCR.use_cassette` in a step definition.
|
|
7
|
-
- Use a `VCR.cucumber_tags` block to tell VCR to use a
|
|
8
|
-
cassette for a tagged scenario.
|
|
9
|
-
|
|
10
|
-
In a cucumber support file (e.g. features/support/vcr.rb), put code like this:
|
|
11
|
-
|
|
12
|
-
``` ruby
|
|
13
|
-
VCR.cucumber_tags do |t|
|
|
14
|
-
t.tag '@tag1'
|
|
15
|
-
t.tags '@tag2', '@tag3'
|
|
16
|
-
|
|
17
|
-
t.tag '@tag3', :cassette => :options
|
|
18
|
-
t.tags '@tag4', '@tag5', :cassette => :options
|
|
19
|
-
t.tag '@vcr', :use_scenario_name => true
|
|
20
|
-
end
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
VCR will use a cassette named `cucumber_tags/<tag_name>` for scenarios
|
|
24
|
-
with each of these tags (Unless the `:use_scenario_name` option is provided. See below).
|
|
25
|
-
The configured `default_cassette_options` will be used, or you can override specific
|
|
26
|
-
options by passing a hash as the last argument to `#tag` or `#tags`.
|
|
27
|
-
|
|
28
|
-
You can also have VCR name your cassettes automatically according to the feature
|
|
29
|
-
and scenario name by providing `:use_scenario_name => true` to `#tag` or `#tags`.
|
|
30
|
-
In this case, the cassette will be named `<feature_name>/<scenario_name>`.
|
|
31
|
-
For scenario outlines, VCR will record one cassette per row, and the cassettes
|
|
32
|
-
will be named `<feature_name>/<scenario_name>/<row_name>`.
|
|
33
|
-
|
|
34
|
-
@exclude-jruby
|
|
35
|
-
Scenario: Record HTTP interactions in a scenario by tagging it
|
|
36
|
-
Given a file named "lib/server.rb" with:
|
|
37
|
-
"""ruby
|
|
38
|
-
if ENV['WITH_SERVER'] == 'true'
|
|
39
|
-
$server = start_sinatra_app do
|
|
40
|
-
get('/:path') { "Hello #{params[:path]}" }
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
"""
|
|
44
|
-
|
|
45
|
-
Given a file named "features/support/vcr.rb" with:
|
|
46
|
-
"""ruby
|
|
47
|
-
require "lib/server"
|
|
48
|
-
require 'vcr'
|
|
49
|
-
|
|
50
|
-
VCR.configure do |c|
|
|
51
|
-
c.hook_into :webmock
|
|
52
|
-
c.cassette_library_dir = 'features/cassettes'
|
|
53
|
-
c.default_cassette_options = {
|
|
54
|
-
:match_requests_on => [:method, :host, :path]
|
|
55
|
-
}
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
VCR.cucumber_tags do |t|
|
|
59
|
-
t.tag '@localhost_request' # uses default record mode since no options are given
|
|
60
|
-
t.tags '@disallowed_1', '@disallowed_2', :record => :none
|
|
61
|
-
t.tag '@vcr', :use_scenario_name => true
|
|
62
|
-
end
|
|
63
|
-
"""
|
|
64
|
-
And a file named "features/step_definitions/steps.rb" with:
|
|
65
|
-
"""ruby
|
|
66
|
-
require 'net/http'
|
|
67
|
-
|
|
68
|
-
When /^a request is made to "([^"]*)"$/ do |url|
|
|
69
|
-
uri = URI.parse(url)
|
|
70
|
-
uri.port = $server.port if $server
|
|
71
|
-
@response = Net::HTTP.get_response(uri)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
When /^(.*) within a cassette named "([^"]*)"$/ do |step_name, cassette_name|
|
|
75
|
-
VCR.use_cassette(cassette_name) { step(step_name) }
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
Then /^the response should be "([^"]*)"$/ do |expected_response|
|
|
79
|
-
expect(@response.body).to eq(expected_response)
|
|
80
|
-
end
|
|
81
|
-
"""
|
|
82
|
-
And a file named "features/vcr_example.feature" with:
|
|
83
|
-
"""
|
|
84
|
-
Feature: VCR example
|
|
85
|
-
|
|
86
|
-
Note: Cucumber treats the pre-amble as part of the feature name. When
|
|
87
|
-
using the :use_scenario_name option, VCR will only use the first line
|
|
88
|
-
of the feature name as the directory for the cassette.
|
|
89
|
-
|
|
90
|
-
@localhost_request
|
|
91
|
-
Scenario: tagged scenario
|
|
92
|
-
When a request is made to "http://localhost:7777/localhost_request_1"
|
|
93
|
-
Then the response should be "Hello localhost_request_1"
|
|
94
|
-
When a request is made to "http://localhost:7777/nested_cassette" within a cassette named "nested_cassette"
|
|
95
|
-
Then the response should be "Hello nested_cassette"
|
|
96
|
-
When a request is made to "http://localhost:7777/localhost_request_2"
|
|
97
|
-
Then the response should be "Hello localhost_request_2"
|
|
98
|
-
|
|
99
|
-
@vcr
|
|
100
|
-
Scenario: tagged scenario
|
|
101
|
-
|
|
102
|
-
Note: Like the feature pre-amble, Cucumber treats the scenario pre-amble
|
|
103
|
-
as part of the scenario name. When using the :use_scenario_name option,
|
|
104
|
-
VCR will only use the first line of the feature name as the directory
|
|
105
|
-
for the cassette.
|
|
106
|
-
|
|
107
|
-
When a request is made to "http://localhost:7777/localhost_request_1"
|
|
108
|
-
Then the response should be "Hello localhost_request_1"
|
|
109
|
-
|
|
110
|
-
@vcr
|
|
111
|
-
Scenario Outline: tagged scenario outline
|
|
112
|
-
When a request is made to "http://localhost:7777/localhost_request_1"
|
|
113
|
-
Then the response should be "Hello localhost_request_1"
|
|
114
|
-
Examples:
|
|
115
|
-
| key | value |
|
|
116
|
-
| foo | bar |
|
|
117
|
-
|
|
118
|
-
@disallowed_1
|
|
119
|
-
Scenario: tagged scenario
|
|
120
|
-
When a request is made to "http://localhost:7777/allowed" within a cassette named "allowed"
|
|
121
|
-
Then the response should be "Hello allowed"
|
|
122
|
-
When a request is made to "http://localhost:7777/disallowed_1"
|
|
123
|
-
|
|
124
|
-
@disallowed_2
|
|
125
|
-
Scenario: tagged scenario
|
|
126
|
-
When a request is made to "http://localhost:7777/disallowed_2"
|
|
127
|
-
"""
|
|
128
|
-
And the directory "features/cassettes" does not exist
|
|
129
|
-
When I run `cucumber WITH_SERVER=true features/vcr_example.feature`
|
|
130
|
-
Then it should fail with "5 scenarios (2 failed, 3 passed)"
|
|
131
|
-
And the file "features/cassettes/cucumber_tags/localhost_request.yml" should contain "Hello localhost_request_1"
|
|
132
|
-
And the file "features/cassettes/cucumber_tags/localhost_request.yml" should contain "Hello localhost_request_2"
|
|
133
|
-
And the file "features/cassettes/nested_cassette.yml" should contain "Hello nested_cassette"
|
|
134
|
-
And the file "features/cassettes/allowed.yml" should contain "Hello allowed"
|
|
135
|
-
And the file "features/cassettes/VCR_example/tagged_scenario.yml" should contain "Hello localhost_request_1"
|
|
136
|
-
And the file "features/cassettes/VCR_example/tagged_scenario_outline/_foo_bar_.yml" should contain "Hello localhost_request_1"
|
|
137
|
-
|
|
138
|
-
# Run again without the server; we'll get the same responses because VCR
|
|
139
|
-
# will replay the recorded responses.
|
|
140
|
-
When I run `cucumber features/vcr_example.feature`
|
|
141
|
-
Then it should fail with "5 scenarios (2 failed, 3 passed)"
|
|
142
|
-
And the output should contain each of the following:
|
|
143
|
-
| An HTTP request has been made that VCR does not know how to handle: |
|
|
144
|
-
| GET http://localhost:7777/disallowed_1 |
|
|
145
|
-
| An HTTP request has been made that VCR does not know how to handle: |
|
|
146
|
-
| GET http://localhost:7777/disallowed_2 |
|
|
147
|
-
And the file "features/cassettes/cucumber_tags/localhost_request.yml" should contain "Hello localhost_request_1"
|
|
148
|
-
And the file "features/cassettes/cucumber_tags/localhost_request.yml" should contain "Hello localhost_request_2"
|
|
149
|
-
And the file "features/cassettes/nested_cassette.yml" should contain "Hello nested_cassette"
|
|
150
|
-
And the file "features/cassettes/allowed.yml" should contain "Hello allowed"
|
|
151
|
-
And the file "features/cassettes/VCR_example/tagged_scenario.yml" should contain "Hello localhost_request_1"
|
|
152
|
-
And the file "features/cassettes/VCR_example/tagged_scenario_outline/_foo_bar_.yml" should contain "Hello localhost_request_1"
|
|
153
|
-
|
|
154
|
-
Scenario: `:allow_unused_http_interactions => false` does not raise if the scenario already failed
|
|
155
|
-
Given a previously recorded cassette file "features/cassettes/cucumber_tags/example.yml" with:
|
|
156
|
-
"""
|
|
157
|
-
---
|
|
158
|
-
http_interactions:
|
|
159
|
-
- request:
|
|
160
|
-
method: get
|
|
161
|
-
uri: http://example.com/foo
|
|
162
|
-
body:
|
|
163
|
-
encoding: UTF-8
|
|
164
|
-
string: ""
|
|
165
|
-
headers: {}
|
|
166
|
-
response:
|
|
167
|
-
status:
|
|
168
|
-
code: 200
|
|
169
|
-
message: OK
|
|
170
|
-
headers:
|
|
171
|
-
Content-Length:
|
|
172
|
-
- "5"
|
|
173
|
-
body:
|
|
174
|
-
encoding: UTF-8
|
|
175
|
-
string: Hello
|
|
176
|
-
http_version: "1.1"
|
|
177
|
-
recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
|
|
178
|
-
recorded_with: VCR 2.0.0
|
|
179
|
-
"""
|
|
180
|
-
And a file named "features/support/vcr.rb" with:
|
|
181
|
-
"""ruby
|
|
182
|
-
require 'vcr'
|
|
183
|
-
|
|
184
|
-
VCR.configure do |c|
|
|
185
|
-
c.hook_into :webmock
|
|
186
|
-
c.cassette_library_dir = 'features/cassettes'
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
VCR.cucumber_tags do |t|
|
|
190
|
-
t.tag '@example', :allow_unused_http_interactions => false
|
|
191
|
-
end
|
|
192
|
-
"""
|
|
193
|
-
And a file named "features/step_definitions/steps.rb" with:
|
|
194
|
-
"""ruby
|
|
195
|
-
When /^the scenario fails$/ do
|
|
196
|
-
raise "boom"
|
|
197
|
-
end
|
|
198
|
-
"""
|
|
199
|
-
And a file named "features/vcr_example.feature" with:
|
|
200
|
-
"""
|
|
201
|
-
Feature:
|
|
202
|
-
|
|
203
|
-
@example
|
|
204
|
-
Scenario: tagged scenario
|
|
205
|
-
When the scenario fails
|
|
206
|
-
"""
|
|
207
|
-
When I run `cucumber features/vcr_example.feature`
|
|
208
|
-
Then it should fail with "1 scenario (1 failed)"
|
|
209
|
-
And the output should contain "boom"
|
|
210
|
-
And the output should not contain "There are unused HTTP interactions"
|
|
211
|
-
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
@with-bundler
|
|
2
|
-
Feature: Usage with RSpec macro
|
|
3
|
-
|
|
4
|
-
VCR provides a macro that makes it easy to use a VCR cassette for an RSpec
|
|
5
|
-
example group. To use it, simply add `config.extend VCR::RSpec::Macros`
|
|
6
|
-
to your RSpec configuration block.
|
|
7
|
-
|
|
8
|
-
In any example group, add a `use_vcr_cassette` declaration to use a cassette
|
|
9
|
-
for that example group. You can use this in a few different ways:
|
|
10
|
-
|
|
11
|
-
- `use_vcr_cassette`
|
|
12
|
-
- Infers a cassette name from the example group description (and parent
|
|
13
|
-
example group descriptions).
|
|
14
|
-
- Uses the `default_cassette_options` you have configured.
|
|
15
|
-
- `use_vcr_cassette "Cassette Name"`
|
|
16
|
-
- Uses the given cassette name.
|
|
17
|
-
- Uses the `default_cassette_options` you have configured.
|
|
18
|
-
- `use_vcr_cassette :cassette => :options`
|
|
19
|
-
- Infers a cassette name from the example group description (and parent
|
|
20
|
-
example group descriptions).
|
|
21
|
-
- Uses the provided cassette options (merged with the defaults).
|
|
22
|
-
- `use_vcr_cassette "Cassette Name", :cassette => :options`
|
|
23
|
-
- Uses the given cassette name.
|
|
24
|
-
- Uses the provided cassette options (merged with the defaults).
|
|
25
|
-
|
|
26
|
-
Background:
|
|
27
|
-
Given the following files do not exist:
|
|
28
|
-
| spec/cassettes/VCR-RSpec_integration/without_an_explicit_cassette_name.yml |
|
|
29
|
-
| spec/cassettes/net_http_example.yml |
|
|
30
|
-
And a file named "spec/sinatra_app.rb" with:
|
|
31
|
-
"""ruby
|
|
32
|
-
$server = start_sinatra_app do
|
|
33
|
-
get('/') { "Hello" }
|
|
34
|
-
end
|
|
35
|
-
"""
|
|
36
|
-
And a file named "spec/vcr_example_spec.rb" with:
|
|
37
|
-
"""ruby
|
|
38
|
-
require 'spec_helper'
|
|
39
|
-
|
|
40
|
-
describe "VCR-RSpec integration" do
|
|
41
|
-
def make_http_request
|
|
42
|
-
Net::HTTP.get_response('localhost', '/', $server.port).body
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
context "without an explicit cassette name" do
|
|
46
|
-
use_vcr_cassette
|
|
47
|
-
|
|
48
|
-
it 'records an http request' do
|
|
49
|
-
expect(make_http_request).to eq('Hello')
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
context "with an explicit cassette name" do
|
|
54
|
-
use_vcr_cassette "net_http_example"
|
|
55
|
-
|
|
56
|
-
it 'records an http request' do
|
|
57
|
-
expect(make_http_request).to eq('Hello')
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
Scenario: Use `use_vcr_cassette` macro with RSpec 2
|
|
64
|
-
Given a file named "spec/spec_helper.rb" with:
|
|
65
|
-
"""ruby
|
|
66
|
-
require 'sinatra_app'
|
|
67
|
-
require 'vcr'
|
|
68
|
-
|
|
69
|
-
VCR.configure do |c|
|
|
70
|
-
c.cassette_library_dir = 'spec/cassettes'
|
|
71
|
-
c.hook_into :webmock
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
RSpec.configure do |c|
|
|
75
|
-
c.extend VCR::RSpec::Macros
|
|
76
|
-
end
|
|
77
|
-
"""
|
|
78
|
-
When I run `rspec spec/vcr_example_spec.rb`
|
|
79
|
-
Then the output should contain "2 examples, 0 failures"
|
|
80
|
-
And the file "spec/cassettes/VCR-RSpec_integration/without_an_explicit_cassette_name.yml" should contain "Hello"
|
|
81
|
-
And the file "spec/cassettes/net_http_example.yml" should contain "Hello"
|