Permalink
Browse files

Add :re_record_interval cassette option.

This option causes a cassette to be re-recorded when the existing file is older than the specified interval.
  • Loading branch information...
1 parent acb7e63 commit d0e7dbd2baf3aa627f8beb4d092ca8884e752c26 @myronmarston committed Sep 19, 2010
View
@@ -4,6 +4,8 @@
* Improved the `:all` record mode so that it keeps previously recorded interactions that do not match the
new recorded interactions. Previously, all of the previously recorded interactions were deleted.
+* Added `:re_record_interval` cassette option. This option causes a cassette to be re-recorded when the
+ existing file is older than the specified interval.
## 1.1.2 (September 9, 2010)
View
@@ -6,7 +6,7 @@ require 'rake'
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec) do |t|
- #t.spec_opts = %w[--format documentation]
+ #t.rspec_opts = %w[--format documentation]
end
desc "Run all examples using rcov"
@@ -77,3 +77,19 @@ Feature: Record response
When I make an HTTP get request to the localhost rack app while using the "temp/localhost" cassette
Then the response for the localhost rack app should match /hello world/
And there should not be a "temp/localhost" library file
+
+ @copy_not_the_real_response_to_temp
+ Scenario: The response is not automatically recorded when not enough time has passed
+ Given the "temp/not_the_real_response" library file has a response for "http://example.com/" that matches /This is not the real response from example.com/
+ And 6 days have passed since the "temp/not_the_real_response" library file last changed
+ When I make an HTTP get request to "http://example.com/" while using the "temp/not_the_real_response" cassette using cassette options: { :record => :none, :re_record_interval => 7.days }
+ Then the response for "http://example.com/" should match /This is not the real response from example.com/
+ And the "temp/not_the_real_response" library file should have a response for "http://example.com/" that matches /This is not the real response from example.com/
+
+ @copy_not_the_real_response_to_temp
+ Scenario: The response is automatically recorded when enough time has passed
+ Given the "temp/not_the_real_response" library file has a response for "http://example.com/" that matches /This is not the real response from example.com/
+ And 8 days have passed since the "temp/not_the_real_response" library file last changed
+ When I make an HTTP get request to "http://example.com/" while using the "temp/not_the_real_response" cassette using cassette options: { :record => :none, :re_record_interval => 7.days }
+ Then the response for "http://example.com/" should match /You have reached this web page by typing.*example\.com/
+ And the "temp/not_the_real_response" library file should have a response for "http://example.com/" that matches /You have reached this web page by typing.*example\.com/
@@ -74,9 +74,11 @@ def static_rack_server(response_string)
end
def recorded_interactions_for(cassette_name)
- yaml_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
- yaml = File.open(yaml_file, 'r') { |f| f.read }
- interactions = YAML.load(yaml)
+ interactions = YAML.load(File.read(file_name(cassette_name)))
+ end
+
+ def file_name(cassette_name)
+ File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
end
def capture_response(url)
@@ -95,12 +97,11 @@ def capture_response(url)
World(VCRHelpers)
Given /^we do not have a "([^\"]*)" cassette$/ do |cassette_name|
- fixture_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
- File.exist?(fixture_file).should be_false
+ File.exist?(file_name(cassette_name)).should be_false
end
-Given /^we have a "([^\"]*)" library file with (a|no) previously recorded response for "([^\"]*)"$/ do |file_name, a_or_no, url|
- fixture_file = File.join(VCR::Config.cassette_library_dir, "#{file_name}.yml")
+Given /^we have a "([^\"]*)" library file with (a|no) previously recorded response for "([^\"]*)"$/ do |cassette_name, a_or_no, url|
+ fixture_file = file_name(cassette_name)
File.exist?(fixture_file).should be_true
responses = File.open(fixture_file, 'r') { |f| YAML.load(f.read) }
should_method = a_or_no == 'a' ? :should : :should_not
@@ -217,8 +218,7 @@ def capture_response(url)
end
Then /^there should not be a "([^\"]*)" library file$/ do |cassette_name|
- yaml_file = File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
- File.exist?(yaml_file).should be_false
+ File.exist?(file_name(cassette_name)).should be_false
end
Given /^the ignore_localhost config setting is set to (true|false)$/ do |value|
@@ -241,3 +241,9 @@ def capture_response(url)
port = static_rack_server('localhost response').port
Given %{the "#{cassette}" library file has a response for "http://localhost:#{port}/" that matches /#{regex}/}
end
+
+Given /^(\d+) days have passed since the "([^"]*)" library file last changed$/ do |day_count, file|
+ last_changed_at = File.new(file_name(file)).mtime
+ Timecop.travel(last_changed_at + day_count.to_i.days)
+end
+
@@ -20,11 +20,14 @@
require 'vcr'
require 'vcr_localhost_server'
+require 'fixnum_extension'
require 'rubygems'
require 'bundler'
Bundler.setup
+require 'timecop'
+
begin
require 'ruby-debug'
Debugger.start
@@ -52,6 +55,7 @@ class << self
end
After do |scenario|
+ Timecop.return
if raised_error = (@http_requests || {}).values.flatten.detect { |result| result.is_a?(Exception) && result.message !~ /VCR/ }
raise raised_error
end
View
@@ -13,13 +13,18 @@ class MissingERBVariableError < NameError; end
def initialize(name, options = {})
options = VCR::Config.default_cassette_options.merge(options)
- invalid_options = options.keys - [:record, :erb, :allow_real_http, :match_requests_on]
+ invalid_options = options.keys - [:record, :erb, :allow_real_http, :match_requests_on, :re_record_interval]
if invalid_options.size > 0
raise ArgumentError.new("You passed the following invalid options to VCR::Cassette.new: #{invalid_options.inspect}.")
end
- @name, @record_mode, @erb, @match_requests_on = name, options[:record], options[:erb], options[:match_requests_on]
+ @name = name
+ @record_mode = options[:record]
+ @erb = options[:erb]
+ @match_requests_on = options[:match_requests_on]
+ @re_record_interval = options[:re_record_interval]
+ @record_mode = :all if should_re_record?
deprecate_old_cassette_options(options)
raise_error_unless_valid_record_mode(record_mode)
@@ -63,6 +68,12 @@ def raise_error_unless_valid_record_mode(record_mode)
end
end
+ def should_re_record?
+ @re_record_interval &&
+ File.exist?(file) &&
+ File.stat(file).mtime + @re_record_interval < Time.now
+ end
+
def should_allow_http_connections?
record_mode != :none
end
View
@@ -138,7 +138,45 @@ def cassette_body(name, options = {})
end
end
- context "when the record mode is :#{record_mode}" do
+ context "when :#{record_mode} is passed as the record option" do
+ unless record_mode == :all
+ context "and re_record_interval is 7.days" do
+ let(:file_name) { File.join(VCR::Config.cassette_library_dir, "cassette_name.yml") }
+ subject { VCR::Cassette.new(File.basename(file_name).gsub('.yml', ''), :record => record_mode, :re_record_interval => 7.days) }
+
+ context 'when the cassette file does not exist' do
+ before(:each) { File.stub(:exist?).with(file_name).and_return(false) }
+
+ it "has :#{record_mode} for the record mode" do
+ subject.record_mode.should == record_mode
+ end
+ end
+
+ context 'when the cassette file does exist' do
+ before(:each) do
+ File.stub(:exist?).with(file_name).and_return(true)
+ File.stub(:read).with(file_name).and_return([].to_yaml)
+ end
+
+ context 'and the file was last modified less than 7 days ago' do
+ before(:each) { File.stub(:stat).with(file_name).and_return(stub(:mtime => Time.now - 7.days + 60)) }
+
+ it "has :#{record_mode} for the record mode" do
+ subject.record_mode.should == record_mode
+ end
+ end
+
+ context 'and the file was last modified more than 7 days ago' do
+ before(:each) { File.stub(:stat).with(file_name).and_return(stub(:mtime => Time.now - 7.days - 60)) }
+
+ it "has :all for the record mode" do
+ subject.record_mode.should == :all
+ end
+ end
+ end
+ end
+ end
+
it "sets http_connections_allowed to #{http_connections_allowed} on the http stubbing adapter" do
VCR.http_stubbing_adapter.should_receive(:http_connections_allowed=).with(http_connections_allowed)
VCR::Cassette.new(:name, :record => record_mode)
@@ -0,0 +1,10 @@
+unless 7.respond_to?(:days)
+ class Fixnum
+ def days
+ self *
+ 24 * # hours
+ 60 * # minutes
+ 60 # seconds
+ end
+ end
+end

0 comments on commit d0e7dbd

Please sign in to comment.