vcr 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
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