vcr 1.1.0 → 1.1.1

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.
Files changed (84) hide show
  1. data/.document +5 -0
  2. data/.gitignore +27 -0
  3. data/CHANGELOG.md +13 -0
  4. data/Gemfile +24 -0
  5. data/Gemfile.lock +119 -0
  6. data/README.md +3 -6
  7. data/Rakefile +70 -0
  8. data/benchmarks/http_stubbing_libraries.rb +59 -0
  9. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/regex_cassette.yml +43 -0
  10. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette1.yml +43 -0
  11. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette2.yml +63 -0
  12. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette3.yml +85 -0
  13. data/features/fixtures/vcr_cassettes/1.9.1/erb_cassette.yml +36 -0
  14. data/features/fixtures/vcr_cassettes/1.9.1/match_requests_on.yml +35 -0
  15. data/features/fixtures/vcr_cassettes/1.9.1/nested_replay_cassette.yml +32 -0
  16. data/features/fixtures/vcr_cassettes/1.9.1/not_the_real_response.yml +43 -0
  17. data/features/fixtures/vcr_cassettes/1.9.1/replay_localhost_cassette.yml +32 -0
  18. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/regex_cassette.yml +43 -0
  19. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette1.yml +43 -0
  20. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette2.yml +47 -0
  21. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette3.yml +85 -0
  22. data/features/fixtures/vcr_cassettes/not_1.9.1/erb_cassette.yml +36 -0
  23. data/features/fixtures/vcr_cassettes/not_1.9.1/match_requests_on.yml +35 -0
  24. data/features/fixtures/vcr_cassettes/not_1.9.1/nested_replay_cassette.yml +24 -0
  25. data/features/fixtures/vcr_cassettes/not_1.9.1/not_the_real_response.yml +43 -0
  26. data/features/fixtures/vcr_cassettes/not_1.9.1/replay_localhost_cassette.yml +32 -0
  27. data/features/http_client.feature +16 -0
  28. data/features/net_http.feature +27 -0
  29. data/features/record_response.feature +66 -0
  30. data/features/replay_recorded_response.feature +96 -0
  31. data/features/step_definitions/http_client_steps.rb +7 -0
  32. data/features/step_definitions/net_http_steps.rb +37 -0
  33. data/features/step_definitions/vcr_steps.rb +240 -0
  34. data/features/support/env.rb +104 -0
  35. data/features/webmock.feature +26 -0
  36. data/lib/vcr.rb +2 -2
  37. data/lib/vcr/extensions/net_http.rb +0 -8
  38. data/lib/vcr/http_stubbing_adapters/common.rb +39 -0
  39. data/lib/vcr/http_stubbing_adapters/fakeweb.rb +74 -70
  40. data/lib/vcr/http_stubbing_adapters/webmock.rb +61 -62
  41. data/lib/vcr/version.rb +1 -1
  42. data/spec/cassette_spec.rb +280 -0
  43. data/spec/config_spec.rb +76 -0
  44. data/spec/cucumber_tags_spec.rb +55 -0
  45. data/spec/deprecations_spec.rb +52 -0
  46. data/spec/extensions/net_http_response_spec.rb +85 -0
  47. data/spec/extensions/net_http_spec.rb +77 -0
  48. data/spec/fixtures/1.9.1/0_3_1_cassette.yml +29 -0
  49. data/spec/fixtures/1.9.1/cassette_spec/erb_with_no_vars.yml +32 -0
  50. data/spec/fixtures/1.9.1/cassette_spec/erb_with_vars.yml +32 -0
  51. data/spec/fixtures/1.9.1/cassette_spec/example.yml +110 -0
  52. data/spec/fixtures/1.9.1/cassette_spec/with_localhost_requests.yml +86 -0
  53. data/spec/fixtures/1.9.1/example_net_http.yml +14 -0
  54. data/spec/fixtures/1.9.1/example_net_http_request.yml +12 -0
  55. data/spec/fixtures/1.9.1/example_net_http_response.yml +25 -0
  56. data/spec/fixtures/1.9.1/fake_example.com_responses.yml +106 -0
  57. data/spec/fixtures/1.9.1/match_requests_on.yml +185 -0
  58. data/spec/fixtures/not_1.9.1/0_3_1_cassette.yml +29 -0
  59. data/spec/fixtures/not_1.9.1/cassette_spec/erb_with_no_vars.yml +32 -0
  60. data/spec/fixtures/not_1.9.1/cassette_spec/erb_with_vars.yml +32 -0
  61. data/spec/fixtures/not_1.9.1/cassette_spec/example.yml +110 -0
  62. data/spec/fixtures/not_1.9.1/cassette_spec/with_localhost_requests.yml +86 -0
  63. data/spec/fixtures/not_1.9.1/example_net_http.yml +14 -0
  64. data/spec/fixtures/not_1.9.1/example_net_http_request.yml +12 -0
  65. data/spec/fixtures/not_1.9.1/example_net_http_response.yml +25 -0
  66. data/spec/fixtures/not_1.9.1/fake_example.com_responses.yml +106 -0
  67. data/spec/fixtures/not_1.9.1/match_requests_on.yml +185 -0
  68. data/spec/http_stubbing_adapters/fakeweb_spec.rb +35 -0
  69. data/spec/http_stubbing_adapters/webmock_spec.rb +35 -0
  70. data/spec/request_matcher_spec.rb +194 -0
  71. data/spec/spec_helper.rb +40 -0
  72. data/spec/structs_spec.rb +121 -0
  73. data/spec/support/disable_warnings.rb +12 -0
  74. data/spec/support/http_library_adapters.rb +272 -0
  75. data/spec/support/http_stubbing_adapter.rb +100 -0
  76. data/spec/support/pending_on_heroku.rb +14 -0
  77. data/spec/support/temp_cassette_library_dir.rb +16 -0
  78. data/spec/support/vcr_localhost_server.rb +53 -0
  79. data/spec/vcr_spec.rb +198 -0
  80. data/spec/version_spec.rb +11 -0
  81. data/vcr.gemspec +43 -0
  82. metadata +134 -73
  83. data/lib/vcr/http_stubbing_adapters/base.rb +0 -36
  84. data/lib/vcr/version.rbc +0 -572
@@ -0,0 +1,7 @@
1
+ When /^I make an asynchronous HTTPClient get request to "([^\"]*)"$/ do |url|
2
+ capture_response(url) do |uri, path|
3
+ connection = HTTPClient.new.get_async(uri)
4
+ connection.join
5
+ connection.pop
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ module NetHTTPHelpers
2
+ def perform_net_http_get_with_returning_block(uri, path)
3
+ Net::HTTP.new(uri.host, uri.port).request(Net::HTTP::Get.new(path, {})) do |response|
4
+ return response
5
+ end
6
+ end
7
+ end
8
+ World(NetHTTPHelpers)
9
+
10
+ When /^I make an asynchronous Net::HTTP get request to "([^\"]*)"$/ do |url|
11
+ capture_response(url) do |uri, path|
12
+ result = Net::HTTP.new(uri.host, uri.port).request_get(path) { |r| r.read_body { } }
13
+ result.body.should be_a(Net::ReadAdapter)
14
+ result
15
+ end
16
+ end
17
+
18
+ When /^I make a replayed asynchronous Net::HTTP get request to "([^\"]*)"$/ do |url|
19
+ capture_response(url) do |uri, path|
20
+ result_body = ''
21
+ result = Net::HTTP.new(uri.host, uri.port).request_get(path) { |r| r.read_body { |fragment| result_body << fragment } }
22
+ result.body.should == result_body
23
+ result
24
+ end
25
+ end
26
+
27
+ When /^I make a recursive Net::HTTP post request to "([^\"]*)"$/ do |url|
28
+ capture_response(url) do |uri, path|
29
+ Net::HTTP.new(uri.host, uri.port).post(path, nil)
30
+ end
31
+ end
32
+
33
+ When /^I make a returning block Net::HTTP get request to "([^\"]*)"$/ do |url|
34
+ capture_response(url) do |uri, path|
35
+ perform_net_http_get_with_returning_block(uri, path)
36
+ end
37
+ end
@@ -0,0 +1,240 @@
1
+ require 'tmpdir'
2
+
3
+ RSpec::Matchers.define :have_expected_response do |regex_str, request_attributes|
4
+ def matched_responses(responses, request_attributes)
5
+ url, request_body, request_headers = request_attributes[:url], request_attributes[:request_body], request_attributes[:request_headers]
6
+
7
+ selector = case url
8
+ when String then lambda { |r| URI.parse(r.uri) == URI.parse(url) }
9
+ when Regexp then lambda { |r| r.uri == url }
10
+ else raise ArgumentError.new("Unexpected url: #{url.class.to_s}: #{url.inspect}")
11
+ end
12
+
13
+ matched = responses.select(&selector)
14
+
15
+ if request_body
16
+ matched = matched.select { |r| r.request.body == request_body }
17
+ end
18
+
19
+ (request_headers || {}).each do |r_key, r_val|
20
+ matched = matched.select do |r|
21
+ r.request.headers.any? { |k, v| k.downcase == r_key.downcase && v == [r_val] }
22
+ end
23
+ end
24
+
25
+ matched
26
+ end
27
+
28
+ match do |responses|
29
+ regex = /#{regex_str}/i
30
+ matched_responses(responses, request_attributes).detect { |r| r.response.body =~ regex }
31
+ end
32
+
33
+ failure_message_for_should do |responses|
34
+ url = request_attributes[:url]
35
+ responses = matched_responses(responses, request_attributes)
36
+ response_bodies = responses.map { |r| r.response.body }
37
+ "expected a response for #{url.inspect} to match /#{regex_str}/. Responses for #{url.inspect}:\n\n #{response_bodies.join("\n\n")}"
38
+ end
39
+ end
40
+
41
+ RSpec::Matchers.define :be_tagged_with do |tag|
42
+ match do |scenario|
43
+ scenario.source_tag_names.include?(tag)
44
+ end
45
+
46
+ failure_message_for_should do |scenario|
47
+ "expected scenario to be tagged with #{tag}. Tags: #{scenario.source_tag_names.inspect}"
48
+ end
49
+ end
50
+
51
+ RSpec::Matchers.define :have_normalized_headers do
52
+ match do |object|
53
+ headers = object.headers
54
+ headers.is_a?(Hash) &&
55
+ headers.keys.map { |k| k.downcase } == headers.keys &&
56
+ headers.values.all? { |val| val.is_a?(Array) }
57
+ end
58
+
59
+ failure_message_for_should do |object|
60
+ "expected headers to be normalized to have lower cased keys and arrays as values. Actual headers: #{object.headers.inspect}"
61
+ end
62
+ end
63
+
64
+ module VCRHelpers
65
+ def static_rack_server(response_string)
66
+ orig_ignore_localhost = VCR.http_stubbing_adapter.ignore_localhost?
67
+ VCR.http_stubbing_adapter.ignore_localhost = true
68
+
69
+ begin
70
+ VCR::LocalhostServer::STATIC_SERVERS[response_string]
71
+ ensure
72
+ VCR.http_stubbing_adapter.ignore_localhost = orig_ignore_localhost
73
+ end
74
+ end
75
+
76
+ def recorded_interactions_for(cassette_name)
77
+ yaml_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
78
+ yaml = File.open(yaml_file, 'r') { |f| f.read }
79
+ interactions = YAML.load(yaml)
80
+ end
81
+
82
+ def capture_response(url)
83
+ @http_requests ||= Hash.new([])
84
+ uri = URI.parse(url)
85
+ path = uri.path.to_s == '' ? '/' : uri.path
86
+ begin
87
+ result = yield uri, path
88
+ rescue => e
89
+ result = e
90
+ end
91
+ @http_requests[url] += [result]
92
+ end
93
+
94
+ end
95
+ World(VCRHelpers)
96
+
97
+ Given /^we do not have a "([^\"]*)" cassette$/ do |cassette_name|
98
+ fixture_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
99
+ File.exist?(fixture_file).should be_false
100
+ end
101
+
102
+ Given /^we have a "([^\"]*)" library file with (a|no) previously recorded response for "([^\"]*)"$/ do |file_name, a_or_no, url|
103
+ fixture_file = File.join(VCR::Config.cassette_library_dir, "#{file_name}.yml")
104
+ File.exist?(fixture_file).should be_true
105
+ responses = File.open(fixture_file, 'r') { |f| YAML.load(f.read) }
106
+ should_method = a_or_no == 'a' ? :should : :should_not
107
+ responses.map{ |r| URI.parse(r.uri) }.send(should_method, include(URI.parse(url)))
108
+ end
109
+
110
+ Given /^the "([^\"]*)" library file has a response for "([^\"]*)" that matches \/(.+)\/$/ do |cassette_name, url, regex_str|
111
+ Given %{we have a "#{cassette_name}" library file with a previously recorded response for "#{url}"}
112
+ Then %{the "#{cassette_name}" library file should have a response for "#{url}" that matches /#{regex_str}/}
113
+ end
114
+
115
+ Given /^the "([^\"]*)" library file has a response for \/(\S+)\/ that matches \/(.+)\/$/ do |cassette_name, url_regex, body_regex|
116
+ recorded_interactions_for(cassette_name).should have_expected_response(body_regex, :url => /#{url_regex}/)
117
+ end
118
+
119
+ Given /^the "([^"]*)" library file has a response for "([^"]*)" with the request body "([^"]*)" that matches \/(.+)\/$/ do |cassette_name, url, request_body, response_regex|
120
+ recorded_interactions_for(cassette_name).should have_expected_response(response_regex, :url => url, :request_body => request_body)
121
+ end
122
+
123
+ Given /^the "([^"]*)" library file has a response for "([^"]*)" with the request header "([^"]*)=([^"]*)" that matches \/(.+)\/$/ do |cassette_name, url, header_key, header_value, response_regex|
124
+ recorded_interactions_for(cassette_name).should have_expected_response(response_regex, :url => url, :request_headers => { header_key => header_value })
125
+ end
126
+
127
+ Given /^this scenario is tagged with the vcr cassette tag: "([^\"]+)"$/ do |tag|
128
+ VCR.current_cucumber_scenario.should be_tagged_with(tag)
129
+ VCR::CucumberTags.tags.should include(tag)
130
+ end
131
+
132
+ Given /^the previous scenario was tagged with the vcr cassette tag: "([^\"]*)"$/ do |tag|
133
+ last_scenario = VCR.completed_cucumber_scenarios.last
134
+ last_scenario.should_not be_nil
135
+ last_scenario.should be_tagged_with(tag)
136
+ VCR::CucumberTags.tags.should include(tag)
137
+ end
138
+
139
+ When /^I make (?:an )?HTTP get request to "([^\"]*)"$/ do |url|
140
+ capture_response(url) do |uri, path|
141
+ make_http_request(:get, url)
142
+ end
143
+ end
144
+
145
+ When /^I make an HTTP post request to "([^"]*)" with request body "([^"]*)"$/ do |url, request_body|
146
+ capture_response(url) do |uri, path|
147
+ make_http_request(:post, url, request_body)
148
+ end
149
+ end
150
+
151
+ When /^I make an HTTP post request to "([^"]*)" with request header "([^"]*)=([^"]*)"$/ do |url, header_key, header_val|
152
+ capture_response(url) do |uri, path|
153
+ make_http_request(:post, url, '', { header_key => header_val })
154
+ end
155
+ end
156
+
157
+ When /^I make (.*) requests? to "([^\"]*)"(?: and "([^\"]*)")? within the "([^\"]*)" cassette(?: using cassette options: (.*))?$/ do |http_request_type, url1, url2, cassette_name, options|
158
+ options = options.to_s == '' ? { :record => :new_episodes } : eval(options)
159
+ urls = [url1, url2].select { |u| u.to_s.size > 0 }
160
+ VCR.use_cassette(cassette_name, options) do
161
+ urls.each do |url|
162
+ When %{I make #{http_request_type} request to "#{url}"}
163
+ end
164
+ end
165
+ end
166
+
167
+ When /^I make an HTTP post request to "([^"]*)" with request body "([^"]*)" within the "([^"]*)" cassette(?: using cassette options: (.*))?$/ do |url, request_body, cassette_name, options|
168
+ options = options.to_s == '' ? { :record => :new_episodes } : eval(options)
169
+ VCR.use_cassette(cassette_name, options) do
170
+ When %{I make an HTTP post request to "#{url}" with request body "#{request_body}"}
171
+ end
172
+ end
173
+
174
+ When /^I make an HTTP post request to "([^"]*)" with request header "([^"]*)=([^"]*)" within the "([^"]*)" cassette(?: using cassette options: (.*))?$/ do |url, header_key, header_value, cassette_name, options|
175
+ options = options.to_s == '' ? { :record => :new_episodes } : eval(options)
176
+ VCR.use_cassette(cassette_name, options) do
177
+ When %{I make an HTTP post request to "#{url}" with request header "#{header_key}=#{header_value}"}
178
+ end
179
+ end
180
+
181
+ Then /^the "([^\"]*)" library file should have a response for "([^\"]*)" that matches \/(.+)\/$/ do |cassette_name, url, regex_str|
182
+ interactions = recorded_interactions_for(cassette_name)
183
+ interactions.should have_expected_response(regex_str, :url => url)
184
+ end
185
+
186
+ Then /^the "([^\"]*)" library file should have exactly (\d+) response$/ do |cassette_name, response_count|
187
+ interactions = recorded_interactions_for(cassette_name)
188
+ interactions.should have(response_count.to_i).responses
189
+ end
190
+
191
+ Then /^the "([^"]*)" library file should have normalized headers for all recorded interactions$/ do |cassette_name|
192
+ interactions = recorded_interactions_for(cassette_name)
193
+ interactions.each do |i|
194
+ i.request.should have_normalized_headers
195
+ i.response.should have_normalized_headers
196
+ end
197
+ end
198
+
199
+ Then /^I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been ejected$/ do
200
+ # do nothing...
201
+ end
202
+
203
+ Then /^the HTTP get request to "([^\"]*)" should result in an error that mentions VCR$/ do |url|
204
+ result = @http_requests[url][0]
205
+ result.should be_a(StandardError)
206
+ result.message.should =~ /VCR/
207
+ end
208
+
209
+ Then /^(?:the )?response(?: (\d+))? for "([^\"]*)" should match \/(.+)\/$/ do |response_num, url, regex_str|
210
+ response_num = response_num.to_i || 0
211
+ response_num -= 1 if response_num > 0 # translate to 0-based array index.
212
+ regex = /#{regex_str}/i
213
+ get_body_string(@http_requests[url][response_num]).should =~ regex
214
+ end
215
+
216
+ Then /^there should not be a "([^\"]*)" library file$/ do |cassette_name|
217
+ yaml_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
218
+ File.exist?(yaml_file).should be_false
219
+ end
220
+
221
+ Given /^the ignore_localhost config setting is set to (true|false)$/ do |value|
222
+ VCR::Config.ignore_localhost = eval(value)
223
+ end
224
+
225
+ Given /^a rack app is running on localhost that returns "([^"]+)" for all requests$/ do |response_string|
226
+ @rack_server = static_rack_server(response_string)
227
+ end
228
+
229
+ When /^I make an HTTP get request to the localhost rack app within the "([^\"]*)" cassette$/ do |cassette|
230
+ When %{I make an HTTP get request to "http://localhost:#{@rack_server.port}/" within the "#{cassette}" cassette}
231
+ end
232
+
233
+ Then /^the response for the localhost rack app should match \/(.*)\/$/ do |regex|
234
+ Then %{the response for "http://localhost:#{@rack_server.port}/" should match /#{regex}/}
235
+ end
236
+
237
+ Given /^the "([^\"]*)" library file has a response for localhost that matches \/(.*)\/$/ do |cassette, regex|
238
+ port = static_rack_server('localhost response').port
239
+ Given %{the "#{cassette}" library file has a response for "http://localhost:#{port}/" that matches /#{regex}/}
240
+ end
@@ -0,0 +1,104 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../spec/support')
2
+
3
+ if ENV['HTTP_STUBBING_ADAPTER'].to_s == ''
4
+ ENV['HTTP_STUBBING_ADAPTER'] = 'fakeweb'
5
+ warn "Using FakeWeb for VCR's cucumber features since the adapter was not specified. Set HTTP_STUBBING_ADAPTER to specify."
6
+ end
7
+
8
+ if ENV['HTTP_LIB'].to_s == ''
9
+ ENV['HTTP_LIB'] = 'net/http'
10
+ warn "Using Net::HTTP for VCR's cucumber features since the HTTP library was not specified. Set HTTP_LIB to specify."
11
+ end
12
+
13
+ # The HTTP library must be loaded before VCR since WebMock looks for the presence of the HTTB library class constant
14
+ # to decide whether or not to hook into it.
15
+ require ENV['HTTP_LIB']
16
+ require 'http_library_adapters'
17
+ World(HTTP_LIBRARY_ADAPTERS[ENV['HTTP_LIB']])
18
+
19
+ puts "\n\n---------------- Running features using #{ENV['HTTP_STUBBING_ADAPTER']} and #{ENV['HTTP_LIB']} -----------------\n"
20
+
21
+ require 'vcr'
22
+ require 'vcr_localhost_server'
23
+
24
+ require 'rubygems'
25
+ require 'bundler'
26
+ Bundler.setup
27
+
28
+ begin
29
+ require 'ruby-debug'
30
+ Debugger.start
31
+ Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
32
+ rescue LoadError
33
+ # ruby-debug wasn't available so neither can the debugging be
34
+ end unless RUBY_VERSION > '1.9.1' # ruby-debug doesn't work on 1.9.2 yet
35
+
36
+ # Ruby 1.9.1 has a different yaml serialization format.
37
+ YAML_SERIALIZATION_VERSION = RUBY_VERSION == '1.9.1' ? '1.9.1' : 'not_1.9.1'
38
+
39
+ VCR.config do |c|
40
+ c.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes', YAML_SERIALIZATION_VERSION)
41
+ c.http_stubbing_library = ENV['HTTP_STUBBING_ADAPTER'].to_sym
42
+ end
43
+
44
+ VCR.module_eval do
45
+ def self.completed_cucumber_scenarios
46
+ @completed_cucumber_scenarios ||= []
47
+ end
48
+
49
+ class << self
50
+ attr_accessor :current_cucumber_scenario
51
+ end
52
+ end
53
+
54
+ After do |scenario|
55
+ if raised_error = (@http_requests || {}).values.flatten.detect { |result| result.is_a?(Exception) && result.message !~ /VCR/ }
56
+ raise raised_error
57
+ end
58
+ VCR.completed_cucumber_scenarios << scenario
59
+ end
60
+
61
+ Before do |scenario|
62
+ VCR::Config.ignore_localhost = false
63
+
64
+ VCR.current_cucumber_scenario = scenario
65
+ temp_dir = File.join(VCR::Config.cassette_library_dir, 'temp')
66
+ FileUtils.rm_rf(temp_dir) if File.exist?(temp_dir)
67
+ end
68
+
69
+ Before('@copy_not_the_real_response_to_temp') do
70
+ orig_file = File.join(VCR::Config.cassette_library_dir, 'not_the_real_response.yml')
71
+ temp_file = File.join(VCR::Config.cassette_library_dir, 'temp', 'not_the_real_response.yml')
72
+ FileUtils.mkdir_p(File.join(VCR::Config.cassette_library_dir, 'temp'))
73
+ FileUtils.cp orig_file, temp_file
74
+ end
75
+
76
+ Before('@create_replay_localhost_cassette') do
77
+ orig_file = File.join(VCR::Config.cassette_library_dir, 'replay_localhost_cassette.yml')
78
+ temp_file = File.join(VCR::Config.cassette_library_dir, 'temp', 'replay_localhost_cassette.yml')
79
+ FileUtils.mkdir_p(File.join(VCR::Config.cassette_library_dir, 'temp'))
80
+
81
+ # the port varies each time, so create a temp cassette with the correct port.
82
+ port = static_rack_server('localhost response').port
83
+
84
+ interactions = YAML.load(File.read(orig_file))
85
+ interactions.each do |i|
86
+ uri = URI.parse(i.request.uri)
87
+ uri.port = port
88
+ i.request.uri = uri.to_s
89
+ end
90
+
91
+ File.open(temp_file, 'w') { |f| f.write interactions.to_yaml }
92
+ end
93
+
94
+ at_exit do
95
+ %w(record_cassette1 record_cassette2).each do |tag|
96
+ file = File.join(VCR::Config.cassette_library_dir, 'cucumber_tags', "#{tag}.yml")
97
+ FileUtils.rm_rf(file) if File.exist?(file)
98
+ end
99
+ end
100
+
101
+ VCR.cucumber_tags do |t|
102
+ t.tags '@record_cassette1', '@record_cassette2', :record => :new_episodes
103
+ t.tags '@replay_cassette1', '@replay_cassette2', '@replay_cassette3', '@regex_cassette', :record => :none
104
+ end
@@ -0,0 +1,26 @@
1
+ @webmock
2
+ Feature: Replay recorded response
3
+ In order to have deterministic, fast tests that do not depend on an internet connection
4
+ As a TDD/BDD developer who uses WebMock
5
+ I want to replay responses for requests I have previously recorded
6
+
7
+ Scenario: Use the :match_requests_on option to differentiate requests by request body (for "foo=bar")
8
+ Given the "match_requests_on" library file has a response for "http://example.com/" with the request body "foo=bar" that matches /foo=bar response/
9
+ When I make an HTTP post request to "http://example.com/" with request body "foo=bar" within the "match_requests_on" cassette using cassette options: { :match_requests_on => [:uri, :body], :record => :none }
10
+ Then the response for "http://example.com/" should match /foo=bar response/
11
+
12
+ Scenario: Use the :match_requests_on option to differentiate requests by request body (for "bar=bazz")
13
+ Given the "match_requests_on" library file has a response for "http://example.com/" with the request body "bar=bazz" that matches /bar=bazz response/
14
+ When I make an HTTP post request to "http://example.com/" with request body "bar=bazz" within the "match_requests_on" cassette using cassette options: { :match_requests_on => [:uri, :body], :record => :none }
15
+ Then the response for "http://example.com/" should match /bar=bazz response/
16
+
17
+ Scenario: Use the :match_requests_on option to differentiate requests by request header (for "X-HTTP-USER=joe")
18
+ Given the "match_requests_on" library file has a response for "http://example.com/" with the request header "X-HTTP-USER=joe" that matches /joe response/
19
+ When I make an HTTP post request to "http://example.com/" with request header "X-HTTP-USER=joe" within the "match_requests_on" cassette using cassette options: { :match_requests_on => [:uri, :headers], :record => :none }
20
+ Then the response for "http://example.com/" should match /joe response/
21
+
22
+ Scenario: Use the :match_requests_on option to differentiate requests by request header (for "X-HTTP-USER=bob")
23
+ Given the "match_requests_on" library file has a response for "http://example.com/" with the request header "X-HTTP-USER=bob" that matches /bob response/
24
+ When I make an HTTP post request to "http://example.com/" with request header "X-HTTP-USER=bob" within the "match_requests_on" cassette using cassette options: { :match_requests_on => [:uri, :headers], :record => :none }
25
+ Then the response for "http://example.com/" should match /bob response/
26
+
data/lib/vcr.rb CHANGED
@@ -8,7 +8,7 @@ require 'vcr/version'
8
8
 
9
9
  require 'vcr/extensions/net_http_response'
10
10
 
11
- require 'vcr/http_stubbing_adapters/base'
11
+ require 'vcr/http_stubbing_adapters/common'
12
12
 
13
13
  module VCR
14
14
  extend self
@@ -77,4 +77,4 @@ module VCR
77
77
  def cassettes
78
78
  @cassettes ||= []
79
79
  end
80
- end
80
+ end
@@ -5,14 +5,6 @@ module Net
5
5
  alias_method :request_without_vcr, :request
6
6
 
7
7
  def request(request, body = nil, &block)
8
- uri = URI.parse(VCR.http_stubbing_adapter.request_uri(self, request))
9
-
10
- if VCR::LOCALHOST_ALIASES.include?(uri.host) && VCR.http_stubbing_adapter.ignore_localhost?
11
- VCR.http_stubbing_adapter.with_http_connections_allowed_set_to(true) do
12
- return request_without_vcr(request, body, &block)
13
- end
14
- end
15
-
16
8
  vcr_request = VCR::Request.from_net_http_request(self, request)
17
9
  response = request_without_vcr(request, body)
18
10