Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: myronmarston/vcr
...
head fork: myronmarston/vcr
  • 7 commits
  • 17 files changed
  • 0 commit comments
  • 1 contributor
View
4 History.rdoc
@@ -1,3 +1,7 @@
+== 0.2.0 March 9, 2010
+* Added <tt>:allow_real_http</tt> cassette option, which allows VCR to work with capybara and a javascript driver.
+ Bug reported by {Ben Hutton}[http://github.com/benhutton].
+* Deprecated the default_cassette_record_mode option. Use default_cassette_options instead.
== 0.1.2 March 4, 2010
* Added explanatory note about VCR to FakeWeb::NetConnectNotAllowedError#message.
View
33 README.rdoc
@@ -69,8 +69,11 @@ modes are:
# the cache_dir is where the cassette yml files will be saved.
c.cache_dir = File.join(Rails.root, 'features', 'fixtures', 'vcr_cassettes')
- # this record mode will be used for any cassette you create without specifying a record mode.
- c.default_cassette_record_mode = :none
+ # these options will be used as defaults for your cassettes, but you can override them in each individual cassette.
+ c.default_cassette_options = {
+ :record => :none,
+ :allow_real_http => :localhost
+ }
end
This can go pretty much wherever, as long as this code is run before your tests, specs or scenarios. I tend
@@ -101,6 +104,27 @@ Alternately, you can create and destroy the cassette with individual method call
In both of these cases, VCR would use the file geocoding/Seattle_WA.yml within the configured
cache dir. The :record setting is optional--if you leave it blank, your configured default will be used.
+Besides the :record option, cassettes also support the :allow_real_http option. You can use this to make the cassette
+allow some real HTTP requests. You can specify it with a lambda:
+
+ VCR.with_cassette('my cassette', :allow_real_http => lambda { |uri| uri.host == 'google.com' }) do
+ # do something that causes an HTTP request.
+ end
+
+In this case, any google HTTP requests will be made for real, regardless of your <tt>FakeWeb.allow_net_connect</tt> setting,
+your current record mode, and whether or not you are recording or replaying this cassette. Non-google requests will do
+the appropriate recording/replaying as usual. You can also use the special <tt>:localhost</tt> option:
+
+ VCR.with_cassette('my cassette', :allow_real_http => :localhost) do
+ # do something that causes an HTTP request.
+ end
+
+This is equivalent to using a lambda like:
+
+ lambda { |uri| uri.host == 'localhost' }
+
+This is needed for using VCR with {capybara}[http://github.com/jnicklas/capybara] and any of the javascript drivers (see below for more info).
+
== Usage with Cucumber
VCR provides special support for cucumber. You can of course use <tt>VCR.with_cassette</tt> within a step definition,
@@ -125,6 +149,11 @@ For each of the tags you specify in your cucumber_tags block, VCR will set up th
for the entire scenario. The tag (minus the '@') will be used as the cassette name, and it'll
go in the cucumber_tags subdirectory of the configured cache dir.
+== Usage with Capybara
+
+When you use any of the javascript-enabled drivers (selenium, celerity, culerity) with {capybara}[http://github.com/jnicklas/capybara],
+it'll need to ping the app running on localhost. You can use the <tt>:allow_real_http => :localhost</tt> option to allow this.
+
== Suggested Workflow
First, configure VCR and FakeWeb as I have above. I like setting <tt>FakeWeb.allow_net_connect</tt> to <tt>false</tt>
View
2  VERSION
@@ -1 +1 @@
-0.1.2
+0.2.0
View
6 features/record_response.feature
@@ -64,3 +64,9 @@ Feature: Record response
When I make a recursive HTTP post request to "http://example.com" within the "temp/recursive_post" unregistered cassette
Then the "temp/recursive_post" cache file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
And the "temp/recursive_post" cache file should have exactly 1 response
+
+ Scenario: Make an allowed HTTP request in a cassette with record mode set to :none
+ Given we do not have a "temp/record_none_cassette" cassette
+ When I make an HTTP get request to "http://example.com" within the "temp/record_none_cassette" none cassette, allowing requests matching /example.com/
+ Then the response for "http://example.com" should match /You have reached this web page by typing.*example\.com/
+ And there should not be a "temp/record_none_cassette" cache file
View
8 features/step_definitions/vcr_steps.rb
@@ -67,11 +67,11 @@ def recorded_responses_for(cassette_name)
@http_requests[url] += [result]
end
-When /^I make(?: an)?(.*)? HTTP (get|post) requests? to "([^\"]*)"(?: and "([^\"]*)")? within the "([^\"]*)" ?(#{VCR::Cassette::VALID_RECORD_MODES.join('|')})? cassette$/ do |request_type, method, url1, url2, cassette_name, record_mode|
- record_mode ||= :unregistered
- record_mode = record_mode.to_sym
+When /^I make(?: an)?(.*)? HTTP (get|post) requests? to "([^\"]*)"(?: and "([^\"]*)")? within the "([^\"]*)" ?(#{VCR::Cassette::VALID_RECORD_MODES.join('|')})? cassette(?:, allowing requests matching \/([^\/]+)\/)?$/ do |request_type, method, url1, url2, cassette_name, record_mode, allowed|
+ options = { :record => (record_mode ? record_mode.to_sym : :unregistered) }
+ options[:allow_real_http] = lambda { |uri| uri.to_s =~ /#{allowed}/ } if allowed.to_s.size > 0
urls = [url1, url2].select { |u| u.to_s.size > 0 }
- VCR.with_cassette(cassette_name, :record => record_mode) do
+ VCR.with_cassette(cassette_name, options) do
urls.each do |url|
When %{I make an#{request_type} HTTP #{method} request to "#{url}"}
end
View
15 lib/vcr/cassette.rb
@@ -9,7 +9,8 @@ class Cassette
def initialize(name, options = {})
@name = name
- @record_mode = options[:record] || VCR::Config.default_cassette_record_mode
+ @record_mode = options[:record] || VCR::Config.default_cassette_options[:record]
+ @allow_real_http_lambda = allow_real_http_lambda_for(options[:allow_real_http] || VCR::Config.default_cassette_options[:allow_real_http])
self.class.raise_error_unless_valid_record_mode(record_mode)
set_fakeweb_allow_net_connect
load_recorded_responses
@@ -39,6 +40,10 @@ def self.raise_error_unless_valid_record_mode(record_mode)
end
end
+ def allow_real_http_requests_to?(uri)
+ @allow_real_http_lambda ? @allow_real_http_lambda.call(uri) : false
+ end
+
private
def new_recorded_responses
@@ -93,5 +98,13 @@ def deregister_original_recorded_responses
FakeWeb.remove_from_registry(rr.method, rr.uri)
end
end
+
+ def allow_real_http_lambda_for(allow_option)
+ if allow_option == :localhost
+ lambda { |uri| uri.host == 'localhost' }
+ else
+ allow_option
+ end
+ end
end
end
View
12 lib/vcr/config.rb
@@ -9,10 +9,14 @@ def cache_dir=(cache_dir)
FileUtils.mkdir_p(cache_dir) if cache_dir
end
- attr_reader :default_cassette_record_mode
- def default_cassette_record_mode=(default_cassette_record_mode)
- VCR::Cassette.raise_error_unless_valid_record_mode(default_cassette_record_mode)
- @default_cassette_record_mode = default_cassette_record_mode
+ attr_writer :default_cassette_options
+ def default_cassette_options
+ @default_cassette_options ||= {}
+ end
+
+ def default_cassette_record_mode=(value)
+ warn %Q{WARNING: #default_cassette_record_mode is deprecated. Instead, use: "default_cassette_options = { :record => :#{value.to_s} }"}
+ default_cassette_options.merge!(:record => value)
end
end
end
View
10 lib/vcr/extensions/fake_web.rb
@@ -5,6 +5,16 @@ def self.remove_from_registry(method, url)
Registry.instance.remove(method, url)
end
+ def self.with_allow_net_connect_set_to(value)
+ original_value = FakeWeb.allow_net_connect?
+ begin
+ FakeWeb.allow_net_connect = value
+ yield
+ ensure
+ FakeWeb.allow_net_connect = original_value
+ end
+ end
+
class Registry #:nodoc:
def remove(method, url)
uri_map.delete_if do |uri, method_hash|
View
41 lib/vcr/extensions/net_http.rb
@@ -4,9 +4,14 @@ module Net
class HTTP
def request_with_vcr(request, body = nil, &block)
@__request_with_vcr_call_count = (@__request_with_vcr_call_count || 0) + 1
- response = request_without_vcr(request, body, &block)
- __store_response_with_vcr__(response, request) if @__request_with_vcr_call_count == 1
- response
+ uri = URI.parse(__vcr_uri__(request))
+ if (cassette = VCR.current_cassette) && cassette.allow_real_http_requests_to?(uri)
+ FakeWeb.with_allow_net_connect_set_to(true) { request_without_vcr(request, body, &block) }
+ else
+ response = request_without_vcr(request, body, &block)
+ __store_response_with_vcr__(response, request) if @__request_with_vcr_call_count == 1
+ response
+ end
ensure
@__request_with_vcr_call_count -= 1
end
@@ -15,22 +20,26 @@ def request_with_vcr(request, body = nil, &block)
private
- def __store_response_with_vcr__(response, request)
- if cassette = VCR.current_cassette
- # Copied from: http://github.com/chrisk/fakeweb/blob/fakeweb-1.2.8/lib/fake_web/ext/net_http.rb#L39-52
- protocol = use_ssl? ? "https" : "http"
+ def __vcr_uri__(request)
+ # Copied from: http://github.com/chrisk/fakeweb/blob/fakeweb-1.2.8/lib/fake_web/ext/net_http.rb#L39-52
+ protocol = use_ssl? ? "https" : "http"
- path = request.path
- path = URI.parse(request.path).request_uri if request.path =~ /^http/
+ path = request.path
+ path = URI.parse(request.path).request_uri if request.path =~ /^http/
- if request["authorization"] =~ /^Basic /
- userinfo = FakeWeb::Utility.decode_userinfo_from_header(request["authorization"])
- userinfo = FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) + "@"
- else
- userinfo = ""
- end
+ if request["authorization"] =~ /^Basic /
+ userinfo = FakeWeb::Utility.decode_userinfo_from_header(request["authorization"])
+ userinfo = FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) + "@"
+ else
+ userinfo = ""
+ end
- uri = "#{protocol}://#{userinfo}#{self.address}:#{self.port}#{path}"
+ "#{protocol}://#{userinfo}#{self.address}:#{self.port}#{path}"
+ end
+
+ def __store_response_with_vcr__(response, request)
+ if cassette = VCR.current_cassette
+ uri = __vcr_uri__(request)
method = request.method.downcase.to_sym
unless FakeWeb.registered_uri?(method, uri)
View
55 spec/cassette_spec.rb
@@ -1,19 +1,6 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe VCR::Cassette do
- before(:all) do
- @orig_default_cassette_record_mode = VCR::Config.default_cassette_record_mode
- VCR::Config.default_cassette_record_mode = :unregistered
- end
-
- after(:all) do
- VCR::Config.default_cassette_record_mode = :unregistered
- end
-
- before(:each) do
- FakeWeb.clean_registry
- end
-
describe '#cache_file' do
temp_dir File.expand_path(File.dirname(__FILE__) + '/fixtures/cache_file'), :assign_to_cache_dir => true
@@ -55,8 +42,8 @@
end
VCR::Cassette::VALID_RECORD_MODES.each do |mode|
- it "defaults the record mode to #{mode} when VCR::Config.default_cassette_record_mode is #{mode}" do
- VCR::Config.default_cassette_record_mode = mode
+ it "defaults the record mode to #{mode} when VCR::Config.default_cassette_options[:record] is #{mode}" do
+ VCR::Config.default_cassette_options = { :record => mode }
cassette = VCR::Cassette.new(:test)
cassette.record_mode.should == mode
end
@@ -116,6 +103,44 @@
end
end
+ describe '#allow_real_http_requests_to?' do
+ it 'delegates to the :allow_real_http lambda' do
+ [true, false].each do |value|
+ yielded_uri = nil
+ c = VCR::Cassette.new('example', :allow_real_http => lambda { |uri| yielded_uri = uri; value })
+ c.allow_real_http_requests_to?(:the_uri).should == value
+ yielded_uri.should == :the_uri
+ end
+ end
+
+ it 'returns true for localhost requests when the :allow_real_http option is set to :localhost' do
+ c = VCR::Cassette.new('example', :allow_real_http => :localhost)
+ c.allow_real_http_requests_to?(URI('http://localhost')).should be_true
+ c.allow_real_http_requests_to?(URI('http://example.com')).should be_false
+ end
+
+ it 'returns false when no option is set' do
+ c = VCR::Cassette.new('example')
+ c.allow_real_http_requests_to?(URI('http://localhost')).should be_false
+ c.allow_real_http_requests_to?(URI('http://example.com')).should be_false
+ end
+
+ it 'delegates to the default :allow_real_http lambda' do
+ [true, false].each do |value|
+ yielded_uri = nil
+ VCR::Config.default_cassette_options.merge!(:allow_real_http => lambda { |uri| yielded_uri = uri; value })
+ c = VCR::Cassette.new('example')
+ c.allow_real_http_requests_to?(:the_uri).should == value
+ yielded_uri.should == :the_uri
+ end
+
+ VCR::Config.default_cassette_options.merge!(:allow_real_http => :localhost)
+ c = VCR::Cassette.new('example')
+ c.allow_real_http_requests_to?(URI('http://localhost')).should be_true
+ c.allow_real_http_requests_to?(URI('http://example.com')).should be_false
+ end
+ end
+
describe '#destroy!' do
temp_dir File.expand_path(File.dirname(__FILE__) + '/fixtures/cassette_spec_destroy'), :assign_to_cache_dir => true
View
32 spec/config_spec.rb
@@ -13,15 +13,35 @@
end
end
- describe '#default_cassette_record_mode' do
- VCR::Cassette::VALID_RECORD_MODES.each do |mode|
- it "allows #{mode}" do
- lambda { VCR::Config.default_cassette_record_mode = mode }.should_not raise_error
+ describe '#default_cassette_options' do
+ it 'always has a hash, even if it is set to nil' do
+ VCR::Config.default_cassette_options = nil
+ VCR::Config.default_cassette_options.should == {}
+ end
+ end
+
+ describe '#default_cassette_record_mode=' do
+ disable_warnings
+
+ it 'sets the default_cassette_options[:record] option' do
+ VCR::Cassette::VALID_RECORD_MODES.each do |mode|
+ VCR::Config.default_cassette_options = nil
+ VCR::Config.default_cassette_record_mode = mode
+ VCR::Config.default_cassette_options[:record].should == mode
end
end
- it "does not allow :not_a_record_mode" do
- lambda { VCR::Config.default_cassette_record_mode = :not_a_record_mode }.should raise_error(ArgumentError)
+ it 'merges the :record option with the existing default_cassette_record options' do
+ VCR::Config.default_cassette_options = { :an => :option }
+ VCR::Config.default_cassette_record_mode = :all
+ VCR::Config.default_cassette_options.should == { :an => :option, :record => :all }
+ end
+
+ it 'warns the user that it is deprecated' do
+ VCR::Cassette::VALID_RECORD_MODES.each do |mode|
+ VCR::Config.should_receive(:warn).with(%Q{WARNING: #default_cassette_record_mode is deprecated. Instead, use: "default_cassette_options = { :record => :#{mode.to_s} }"})
+ VCR::Config.default_cassette_record_mode = mode
+ end
end
end
end
View
30 spec/extensions/fake_web_spec.rb
@@ -30,4 +30,34 @@
'The fakeweb error message. You can use VCR to automatically record this request and replay it later with fakeweb. For more details, see the VCR README at: http://github.com/myronmarston/vcr'
end
end
+
+ describe "#with_allow_net_connect_set_to" do
+ it 'sets allow_net_connect for the duration of the block to the provided value' do
+ [true, false].each do |expected|
+ yielded_value = :not_set
+ FakeWeb.with_allow_net_connect_set_to(expected) { yielded_value = FakeWeb.allow_net_connect? }
+ yielded_value.should == expected
+ end
+ end
+
+ it 'returns the value returned by the block' do
+ FakeWeb.with_allow_net_connect_set_to(true) { :return_value }.should == :return_value
+ end
+
+ it 'reverts allow_net_connect when the block completes' do
+ [true, false].each do |expected|
+ FakeWeb.allow_net_connect = expected
+ FakeWeb.with_allow_net_connect_set_to(true) { }
+ FakeWeb.allow_net_connect?.should == expected
+ end
+ end
+
+ it 'reverts allow_net_connect when the block completes, even if an error is raised' do
+ [true, false].each do |expected|
+ FakeWeb.allow_net_connect = expected
+ lambda { FakeWeb.with_allow_net_connect_set_to(true) { raise RuntimeError } }.should raise_error(RuntimeError)
+ FakeWeb.allow_net_connect?.should == expected
+ end
+ end
+ end
end
View
66 spec/extensions/net_http_spec.rb
@@ -1,45 +1,57 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe "Net::HTTP Extensions" do
- before(:all) do
- @orig_allow_net_connect = FakeWeb.allow_net_connect?
- FakeWeb.allow_net_connect = true
+ before(:each) do
+ VCR.stub!(:current_cassette).and_return(@current_cassette = mock)
+ @uri = URI.parse('http://example.com')
end
- after(:all) do
- FakeWeb.allow_net_connect = @orig_allow_net_connect
+ it 'works when there is no current cassette' do
+ VCR.stub!(:current_cassette).and_return(nil)
+ lambda { Net::HTTP.get(@uri) }.should_not raise_error
end
- before(:each) do
- @current_cassette = mock
- VCR.stub!(:current_cassette).and_return(@current_cassette)
- FakeWeb.clean_registry
- end
-
- describe 'a request that is not registered with FakeWeb' do
- it 'calls #store_recorded_response! on the current cassette' do
- recorded_response = VCR::RecordedResponse.new(:get, 'http://example.com:80/', :example_response)
- VCR::RecordedResponse.should_receive(:new).with(:get, 'http://example.com:80/', an_instance_of(Net::HTTPOK)).and_return(recorded_response)
- @current_cassette.should_receive(:store_recorded_response!).with(recorded_response)
- Net::HTTP.get(URI.parse('http://example.com'))
+ context 'when current_cassette.allow_real_http_requests_to? returns false' do
+ before(:each) do
+ @current_cassette.should_receive(:allow_real_http_requests_to?).at_least(:once).with(@uri).and_return(false)
end
- it 'calls #store_recorded_response! only once, even when Net::HTTP internally recursively calls #request' do
- @current_cassette.should_receive(:store_recorded_response!).once
- Net::HTTP.new('example.com', 80).post('/', nil)
+ describe 'a request that is not registered with FakeWeb' do
+ it 'calls #store_recorded_response! on the current cassette' do
+ recorded_response = VCR::RecordedResponse.new(:get, 'http://example.com:80/', :example_response)
+ VCR::RecordedResponse.should_receive(:new).with(:get, 'http://example.com:80/', an_instance_of(Net::HTTPOK)).and_return(recorded_response)
+ @current_cassette.should_receive(:store_recorded_response!).with(recorded_response)
+ Net::HTTP.get(@uri)
+ end
+
+ it 'calls #store_recorded_response! only once, even when Net::HTTP internally recursively calls #request' do
+ @current_cassette.should_receive(:store_recorded_response!).once
+ Net::HTTP.new('example.com', 80).post('/', nil)
+ end
end
- it 'does not have an error if there is no current cassette' do
- VCR.stub!(:current_cassette).and_return(nil)
- lambda { Net::HTTP.get(URI.parse('http://example.com')) }.should_not raise_error
+ describe 'a request that is registered with FakeWeb' do
+ it 'does not call #store_recorded_response! on the current cassette' do
+ FakeWeb.register_uri(:get, 'http://example.com', :body => 'example.com response')
+ @current_cassette.should_not_receive(:store_recorded_response!)
+ Net::HTTP.get(@uri)
+ end
end
end
- describe 'a request that is registered with FakeWeb' do
+ context 'when current_cassette.allow_real_http_requests_to? returns true' do
+ before(:each) do
+ @current_cassette.should_receive(:allow_real_http_requests_to?).with(@uri).and_return(true)
+ end
+
it 'does not call #store_recorded_response! on the current cassette' do
- FakeWeb.register_uri(:get, 'http://example.com', :body => 'example.com response')
- @current_cassette.should_not_receive(:store_recorded_response!)
- Net::HTTP.get(URI.parse('http://example.com'))
+ @current_cassette.should_receive(:store_recorded_response!).never
+ Net::HTTP.get(@uri)
+ end
+
+ it 'uses FakeWeb.with_allow_net_connect_set_to(true) to make the request' do
+ FakeWeb.should_receive(:with_allow_net_connect_set_to).with(true).and_yield
+ Net::HTTP.get(@uri)
end
end
end
View
7 spec/spec_helper.rb
@@ -19,4 +19,11 @@
Spec::Runner.configure do |config|
config.extend TempCacheDir
+ config.extend DisableWarnings
+
+ config.before(:each) do
+ VCR::Config.default_cassette_options = { :record => :unregistered }
+ FakeWeb.allow_net_connect = true
+ FakeWeb.clean_registry
+ end
end
View
12 spec/support/disable_warnings.rb
@@ -0,0 +1,12 @@
+module DisableWarnings
+ def disable_warnings
+ before(:all) do
+ @orig_std_err = $stderr
+ $stderr = StringIO.new
+ end
+
+ after(:all) do
+ $stderr = @orig_std_err
+ end
+ end
+end
View
9 spec/vcr_spec.rb
@@ -1,15 +1,6 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe VCR do
- before(:all) do
- @orig_default_cassette_record_mode = VCR::Config.default_cassette_record_mode
- VCR::Config.default_cassette_record_mode = :unregistered
- end
-
- after(:all) do
- VCR::Config.default_cassette_record_mode = :unregistered
- end
-
def create_cassette
VCR.create_cassette!(:cassette_test)
end
View
6 vcr.gemspec
@@ -5,11 +5,11 @@
Gem::Specification.new do |s|
s.name = %q{vcr}
- s.version = "0.1.2"
+ s.version = "0.2.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Myron Marston"]
- s.date = %q{2010-03-04}
+ s.date = %q{2010-03-09}
s.description = %q{VCR provides helpers to record HTTP requests for URIs that are not registered with fakeweb, and replay them later. It provides built-in support for cucumber, but works with any ruby testing framework.}
s.email = %q{myron.marston@gmail.com}
s.extra_rdoc_files = [
@@ -63,6 +63,7 @@ Gem::Specification.new do |s|
"spec/recorded_response_spec.rb",
"spec/spec.opts",
"spec/spec_helper.rb",
+ "spec/support/disable_warnings.rb",
"spec/support/temp_cache_dir.rb",
"spec/vcr_spec.rb",
"vcr.gemspec"
@@ -81,6 +82,7 @@ Gem::Specification.new do |s|
"spec/extensions/net_read_adapter_spec.rb",
"spec/recorded_response_spec.rb",
"spec/spec_helper.rb",
+ "spec/support/disable_warnings.rb",
"spec/support/temp_cache_dir.rb",
"spec/vcr_spec.rb"
]

No commit comments for this range

Something went wrong with that request. Please try again.