vcr 1.3.1 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +14 -2
- data/Gemfile +3 -0
- data/Gemfile.lock +20 -2
- data/README.md +6 -1
- data/Rakefile +6 -44
- data/benchmarks/http_stubbing_libraries.rb +4 -4
- data/cucumber.yml +14 -0
- data/features/README.md +21 -0
- data/features/cassettes/automatic_re_recording.feature +68 -0
- data/features/cassettes/dynamic_erb.feature +90 -0
- data/features/cassettes/format.feature +81 -0
- data/features/cassettes/no_cassette.feature +38 -0
- data/features/cassettes/record_modes/all.feature +78 -0
- data/features/cassettes/record_modes/new_episodes.feature +71 -0
- data/features/cassettes/record_modes/none.feature +65 -0
- data/features/cassettes/request_matching.feature +379 -0
- data/features/configuration/cassette_library_dir.feature +28 -0
- data/features/configuration/default_cassette_options.feature +80 -0
- data/features/configuration/ignore_localhost.feature +103 -0
- data/features/configuration/stub_with.feature +164 -0
- data/features/http_libraries/net_http.feature +137 -0
- data/features/step_definitions/cli_steps.rb +82 -0
- data/features/support/aruba_workaround/aruba_patches.rb +36 -0
- data/features/support/aruba_workaround/background_process.rb +4 -0
- data/features/support/env.rb +16 -102
- data/features/support/http_lib_filters.rb +37 -0
- data/features/support/vcr_cucumber_helpers.rb +34 -0
- data/features/test_frameworks/cucumber.feature +109 -0
- data/features/test_frameworks/rspec.feature +110 -0
- data/features/test_frameworks/shoulda.feature +64 -0
- data/features/test_frameworks/test_unit.feature +46 -0
- data/lib/vcr/cassette.rb +1 -1
- data/lib/vcr/structs.rb +64 -13
- data/lib/vcr/version.rb +1 -1
- data/{FullBuildRakeFile → script/FullBuildRakeFile} +0 -0
- data/script/full_build +1 -0
- data/spec/extensions/net_http_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/structs_spec.rb +47 -16
- data/spec/support/vcr_localhost_server.rb +11 -5
- data/vcr.gemspec +2 -1
- metadata +82 -77
- data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/regex_cassette.yml +0 -43
- data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette1.yml +0 -43
- data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette2.yml +0 -63
- data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette3.yml +0 -85
- data/features/fixtures/vcr_cassettes/1.9.1/erb_cassette.yml +0 -36
- data/features/fixtures/vcr_cassettes/1.9.1/match_requests_on.yml +0 -35
- data/features/fixtures/vcr_cassettes/1.9.1/nested_replay_cassette.yml +0 -32
- data/features/fixtures/vcr_cassettes/1.9.1/not_the_real_response.yml +0 -43
- data/features/fixtures/vcr_cassettes/1.9.1/record_all.yml +0 -62
- data/features/fixtures/vcr_cassettes/1.9.1/replay_localhost_cassette.yml +0 -32
- data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/regex_cassette.yml +0 -43
- data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette1.yml +0 -43
- data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette2.yml +0 -47
- data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette3.yml +0 -85
- data/features/fixtures/vcr_cassettes/not_1.9.1/erb_cassette.yml +0 -36
- data/features/fixtures/vcr_cassettes/not_1.9.1/match_requests_on.yml +0 -35
- data/features/fixtures/vcr_cassettes/not_1.9.1/nested_replay_cassette.yml +0 -24
- data/features/fixtures/vcr_cassettes/not_1.9.1/not_the_real_response.yml +0 -43
- data/features/fixtures/vcr_cassettes/not_1.9.1/record_all.yml +0 -61
- data/features/fixtures/vcr_cassettes/not_1.9.1/replay_localhost_cassette.yml +0 -32
- data/features/http_client.feature +0 -16
- data/features/net_http.feature +0 -38
- data/features/record_response.feature +0 -95
- data/features/replay_recorded_response.feature +0 -96
- data/features/rspec.feature +0 -100
- data/features/step_definitions/http_client_steps.rb +0 -7
- data/features/step_definitions/net_http_steps.rb +0 -49
- data/features/step_definitions/vcr_steps.rb +0 -252
- data/features/webmock.feature +0 -26
- data/full_build +0 -1
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'vcr/structs'
|
2
|
+
|
3
|
+
module VCRHelpers
|
4
|
+
YAML_REGEX_FOR_1_9_1 = Regexp.union(*[
|
5
|
+
' request',
|
6
|
+
' method',
|
7
|
+
' uri',
|
8
|
+
' body',
|
9
|
+
' headers',
|
10
|
+
' response',
|
11
|
+
' status',
|
12
|
+
' code',
|
13
|
+
' message',
|
14
|
+
' body',
|
15
|
+
' http_version'
|
16
|
+
].uniq)
|
17
|
+
|
18
|
+
def normalize_cassette_yaml(content)
|
19
|
+
return content unless RUBY_VERSION == '1.9.1'
|
20
|
+
|
21
|
+
# Ruby 1.9.1 serializes YAML a bit different, so
|
22
|
+
# we deal with that difference and add leading colons here.
|
23
|
+
content = content.gsub(YAML_REGEX_FOR_1_9_1) do |match|
|
24
|
+
match.sub(/^ +/, '\0:')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def normalize_cassette_structs(content)
|
29
|
+
content = normalize_cassette_yaml(content)
|
30
|
+
structs = YAML.load(content)
|
31
|
+
|
32
|
+
# Remove non-deterministic headers
|
33
|
+
structs.each do |s|
|
34
|
+
s.response.headers.reject! { |k, v| %w[ server date ].include?(k) }
|
35
|
+
end
|
36
|
+
|
37
|
+
structs
|
38
|
+
end
|
39
|
+
end
|
40
|
+
World(VCRHelpers)
|
41
|
+
|
42
|
+
Given /the following files do not exist:/ do |files|
|
43
|
+
check_file_presence(files.raw.map{|file_row| file_row[0]}, false)
|
44
|
+
end
|
45
|
+
|
46
|
+
Given /^the directory "([^"]*)" does not exist$/ do |dir|
|
47
|
+
check_directory_presence([dir], false)
|
48
|
+
end
|
49
|
+
|
50
|
+
Then /^the file "([^"]*)" should exist$/ do |file_name|
|
51
|
+
check_file_presence([file_name], true)
|
52
|
+
end
|
53
|
+
|
54
|
+
Then /^it should (pass|fail) with "([^"]*)"$/ do |pass_fail, partial_output|
|
55
|
+
assert_exit_status_and_partial_output(pass_fail == 'pass', partial_output)
|
56
|
+
end
|
57
|
+
|
58
|
+
Then /^the output should contain each of the following:$/ do |table|
|
59
|
+
table.raw.flatten.each do |string|
|
60
|
+
assert_partial_output(string)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
Then /^the file "([^"]*)" should contain YAML like:$/ do |file_name, expected_content|
|
65
|
+
actual_content = in_current_dir { File.read(file_name) }
|
66
|
+
normalize_cassette_structs(actual_content).should == normalize_cassette_structs(expected_content)
|
67
|
+
end
|
68
|
+
|
69
|
+
Given /^a previously recorded cassette file "([^"]*)" with:$/ do |file_name, content|
|
70
|
+
create_file(file_name, normalize_cassette_yaml(content))
|
71
|
+
end
|
72
|
+
|
73
|
+
Then /^the file "([^"]*)" should contain each of these:$/ do |file_name, table|
|
74
|
+
table.raw.flatten.each do |string|
|
75
|
+
check_file_content(file_name, string, true)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Given /^(\d+) days have passed since the cassette was recorded$/ do |day_count|
|
80
|
+
set_env('DAYS_PASSED', day_count)
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Aruba::Api#run in aruba 0.2.4 does not work w/ JRuby or Rubinius.
|
2
|
+
# This is the version from 0.2.2 before aruba relied upon
|
3
|
+
# BackgroundProcess (which is not jruby/rbx compatible).
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
Aruba::Api.module_eval do
|
7
|
+
def run(cmd, fail_on_error=true)
|
8
|
+
cmd = detect_ruby(cmd)
|
9
|
+
|
10
|
+
stderr_file = Tempfile.new('cucumber')
|
11
|
+
stderr_file.close
|
12
|
+
in_current_dir do
|
13
|
+
announce_or_puts("$ cd #{Dir.pwd}") if @announce_dir
|
14
|
+
announce_or_puts("$ #{cmd}") if @announce_cmd
|
15
|
+
|
16
|
+
mode = RUBY_VERSION =~ /^1\.9/ ? {:external_encoding=>"UTF-8"} : 'r'
|
17
|
+
|
18
|
+
IO.popen("#{cmd} 2> #{stderr_file.path}", mode) do |io|
|
19
|
+
@last_stdout = io.read
|
20
|
+
announce_or_puts(@last_stdout) if @announce_stdout
|
21
|
+
end
|
22
|
+
|
23
|
+
@last_exit_status = $?.exitstatus
|
24
|
+
end
|
25
|
+
@last_stderr = IO.read(stderr_file.path)
|
26
|
+
|
27
|
+
announce_or_puts(@last_stderr) if @announce_stderr
|
28
|
+
|
29
|
+
if(@last_exit_status != 0 && fail_on_error)
|
30
|
+
fail("Exit status was #{@last_exit_status}. Output:\n#{combined_output}")
|
31
|
+
end
|
32
|
+
|
33
|
+
@last_stderr
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,4 @@
|
|
1
|
+
# Don't do anything--this is just here to allow aruba to run on JRuby/rbx.
|
2
|
+
# It requires background_process, but that doesn't work on JRuby/rbx.
|
3
|
+
# So on JRuby/rbx, we add this file's dir to the load path, in order to fake out aruba
|
4
|
+
# and force it to load this file instaed.
|
data/features/support/env.rb
CHANGED
@@ -1,116 +1,30 @@
|
|
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 'ruby_interpreter'
|
23
|
-
require 'vcr_localhost_server'
|
24
|
-
require 'fixnum_extension'
|
25
|
-
|
26
1
|
require 'rubygems'
|
27
2
|
require 'bundler'
|
28
3
|
Bundler.setup
|
29
4
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
begin
|
34
|
-
require 'ruby-debug'
|
35
|
-
Debugger.start
|
36
|
-
Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
|
37
|
-
rescue LoadError
|
38
|
-
# ruby-debug wasn't available so neither can the debugging be
|
39
|
-
end unless RUBY_VERSION > '1.9.1' # ruby-debug doesn't work on 1.9.2 yet
|
40
|
-
|
41
|
-
# Ruby 1.9.1 has a different yaml serialization format.
|
42
|
-
YAML_SERIALIZATION_VERSION = RUBY_VERSION == '1.9.1' ? '1.9.1' : 'not_1.9.1'
|
43
|
-
|
44
|
-
VCR.config do |c|
|
45
|
-
c.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes', YAML_SERIALIZATION_VERSION)
|
5
|
+
# Current version of aruba won't run on JRuby or Rubinius due to
|
6
|
+
# dependency on background_process. We have a work around to fix this.
|
7
|
+
NEEDS_ARUBA_FIX = defined?(RUBY_ENGINE) && %w[ jruby rbx ].include?(RUBY_ENGINE)
|
46
8
|
|
47
|
-
|
48
|
-
stubs.delete(:typhoeus) if RUBY_INTERPRETER == :jruby
|
49
|
-
|
50
|
-
c.stub_with *stubs
|
51
|
-
end
|
52
|
-
|
53
|
-
VCR.module_eval do
|
54
|
-
def self.completed_cucumber_scenarios
|
55
|
-
@completed_cucumber_scenarios ||= []
|
56
|
-
end
|
9
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/aruba_workaround' if NEEDS_ARUBA_FIX
|
57
10
|
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
After do |scenario|
|
64
|
-
Timecop.return
|
65
|
-
if raised_error = (@http_requests || {}).values.flatten.detect { |result| result.is_a?(Exception) && result.message !~ /VCR/ }
|
66
|
-
raise raised_error
|
67
|
-
end
|
68
|
-
VCR.completed_cucumber_scenarios << scenario
|
69
|
-
end
|
70
|
-
|
71
|
-
Before do |scenario|
|
72
|
-
VCR::Config.ignore_localhost = false
|
73
|
-
|
74
|
-
VCR.current_cucumber_scenario = scenario
|
75
|
-
temp_dir = File.join(VCR::Config.cassette_library_dir, 'temp')
|
76
|
-
FileUtils.rm_rf(temp_dir) if File.exist?(temp_dir)
|
77
|
-
end
|
11
|
+
require 'aruba'
|
12
|
+
require 'aruba_patches' if NEEDS_ARUBA_FIX
|
78
13
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
FileUtils.mkdir_p(File.join(VCR::Config.cassette_library_dir, 'temp'))
|
84
|
-
FileUtils.cp orig_file, temp_file
|
14
|
+
Before do
|
15
|
+
this_dir = File.dirname(__FILE__)
|
16
|
+
in_current_dir do
|
17
|
+
FileUtils.ln_s File.join(this_dir, 'vcr_cucumber_helpers.rb'), 'vcr_cucumber_helpers.rb'
|
85
18
|
end
|
86
19
|
end
|
87
20
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
FileUtils.mkdir_p(File.join(VCR::Config.cassette_library_dir, 'temp'))
|
92
|
-
|
93
|
-
# the port varies each time, so create a temp cassette with the correct port.
|
94
|
-
port = static_rack_server('localhost response').port
|
95
|
-
|
96
|
-
interactions = YAML.load(File.read(orig_file))
|
97
|
-
interactions.each do |i|
|
98
|
-
uri = URI.parse(i.request.uri)
|
99
|
-
uri.port = port
|
100
|
-
i.request.uri = uri.to_s
|
21
|
+
if RUBY_VERSION > '1.9.1'
|
22
|
+
Before do
|
23
|
+
set_env('RUBYOPT', '-I.:../../lib')
|
101
24
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
at_exit do
|
107
|
-
%w(record_cassette1 record_cassette2).each do |tag|
|
108
|
-
file = File.join(VCR::Config.cassette_library_dir, 'cucumber_tags', "#{tag}.yml")
|
109
|
-
FileUtils.rm_rf(file) if File.exist?(file)
|
25
|
+
elsif RUBY_PLATFORM == 'java'
|
26
|
+
Before do
|
27
|
+
set_env('RUBYOPT', '-I../../lib -rubygems')
|
110
28
|
end
|
111
29
|
end
|
112
30
|
|
113
|
-
VCR.cucumber_tags do |t|
|
114
|
-
t.tags '@record_cassette1', '@record_cassette2', :record => :new_episodes
|
115
|
-
t.tags '@replay_cassette1', '@replay_cassette2', '@replay_cassette3', '@regex_cassette', :record => :none
|
116
|
-
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# make the values of the example row cells available as an array...
|
2
|
+
Cucumber::Ast::OutlineTable::ExampleRow.class_eval do
|
3
|
+
def cell_values
|
4
|
+
@cells.map { |c| c.value }
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
if RUBY_VERSION == '1.9.2'
|
9
|
+
# For some reason, the local sinatra server locks up and never exits
|
10
|
+
# when using patron on 1.9.2, even though it exits fine during the specs.
|
11
|
+
UNSUPPORTED_HTTP_LIBS = %w[ patron ]
|
12
|
+
elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
13
|
+
# Patron is freezing up the cukes (as it does on 1.9.2)
|
14
|
+
|
15
|
+
# I'm not sure why em-http-request isn't working on rbx,
|
16
|
+
# but considering the fact that VCR works with all the other
|
17
|
+
# libs just fine and doesn't do anything for em-http-request,
|
18
|
+
# it's probably a bug in it or rbx...so ignore it, for now.
|
19
|
+
|
20
|
+
# I'm getting errors in the curb C extension in rbx.
|
21
|
+
UNSUPPORTED_HTTP_LIBS = %w[ patron em-http-request curb ]
|
22
|
+
elsif RUBY_PLATFORM == 'java'
|
23
|
+
# These gems have C extensions and can't install on JRuby.
|
24
|
+
UNSUPPORTED_HTTP_LIBS = %w[ typhoeus patron curb em-http-request ]
|
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
|
+
Around do |scenario, block|
|
32
|
+
unless scenario.respond_to?(:cell_values) && scenario.cell_values.any? { |v| v =~ UNSUPPORTED_HTTP_LIB_REGEX }
|
33
|
+
block.call
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# This file gets symlinked into the tmp/aruba directory before
|
2
|
+
# each scenario so that it is available to be required in them.
|
3
|
+
$LOAD_PATH.unshift '../../spec' unless $LOAD_PATH.include?('../../spec')
|
4
|
+
$LOAD_PATH.unshift '../../lib' unless $LOAD_PATH.include?('../../lib')
|
5
|
+
|
6
|
+
RUNNING_UNDER_ARUBA = File.dirname(__FILE__) == '.' || File.dirname(__FILE__) =~ /aruba/
|
7
|
+
|
8
|
+
require 'support/fixnum_extension' if RUNNING_UNDER_ARUBA
|
9
|
+
|
10
|
+
if ENV['DAYS_PASSED']
|
11
|
+
require 'timecop'
|
12
|
+
Timecop.travel(Time.now + ENV['DAYS_PASSED'].to_i.days)
|
13
|
+
end
|
14
|
+
|
15
|
+
def include_http_adapter_for(lib)
|
16
|
+
require 'support/http_library_adapters'
|
17
|
+
require lib
|
18
|
+
include HTTP_LIBRARY_ADAPTERS[lib]
|
19
|
+
end
|
20
|
+
|
21
|
+
def response_body_for(*args)
|
22
|
+
get_body_string(make_http_request(*args))
|
23
|
+
end
|
24
|
+
|
25
|
+
def start_sinatra_app(options, &block)
|
26
|
+
raise ArgumentError.new("You must pass a port") unless options[:port]
|
27
|
+
|
28
|
+
require 'sinatra'
|
29
|
+
require 'support/vcr_localhost_server'
|
30
|
+
klass = Class.new(Sinatra::Base)
|
31
|
+
klass.class_eval(&block)
|
32
|
+
|
33
|
+
VCR::LocalhostServer.new(klass.new, options[:port])
|
34
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
Feature: Usage with cucumber
|
2
|
+
|
3
|
+
VCR can be used with cucumber in two basic ways:
|
4
|
+
|
5
|
+
* Use `VCR.use_cassette` in a step definition.
|
6
|
+
* Use a `VCR.cucumber_tags` block to tell VCR to use a
|
7
|
+
cassette for a tagged scenario.
|
8
|
+
|
9
|
+
In a cucumber support file (e.g. features/support/vcr.rb), put code like this:
|
10
|
+
|
11
|
+
VCR.cucumber_tags do |t|
|
12
|
+
t.tag '@tag1'
|
13
|
+
t.tags '@tag2', '@tag3'
|
14
|
+
|
15
|
+
t.tag '@tag3', :cassette => :options
|
16
|
+
t.tags '@tag4, '@tag5', :cassette => :options
|
17
|
+
end
|
18
|
+
|
19
|
+
VCR will use a cassette named "cucumber_tags/<tag_name>" for scenarios
|
20
|
+
with each of these tags. The configured default_cassette_options will
|
21
|
+
be used, or you can override specific options by passing a hash as the
|
22
|
+
last argument to #tag or #tags.
|
23
|
+
|
24
|
+
Scenario: Record HTTP interactions in a scenario by tagging it
|
25
|
+
Given a file named "features/support/vcr.rb" with:
|
26
|
+
"""
|
27
|
+
require 'vcr_cucumber_helpers.rb'
|
28
|
+
|
29
|
+
if ENV['WITH_SERVER'] == 'true'
|
30
|
+
start_sinatra_app(:port => 7777) do
|
31
|
+
get('/:path') { "Hello #{params[:path]}" }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'vcr'
|
36
|
+
|
37
|
+
VCR.config do |c|
|
38
|
+
c.stub_with :webmock
|
39
|
+
c.cassette_library_dir = 'features/cassettes'
|
40
|
+
c.default_cassette_options = { :record => :new_episodes }
|
41
|
+
end
|
42
|
+
|
43
|
+
VCR.cucumber_tags do |t|
|
44
|
+
t.tag '@localhost_request' # uses default record mode since no options are given
|
45
|
+
t.tags '@disallowed_1', '@disallowed_2', :record => :none
|
46
|
+
end
|
47
|
+
"""
|
48
|
+
And a file named "features/step_definitions/steps.rb" with:
|
49
|
+
"""
|
50
|
+
require 'net/http'
|
51
|
+
|
52
|
+
When /^a request is made to "([^"]*)"$/ do |url|
|
53
|
+
@response = Net::HTTP.get_response(URI.parse(url))
|
54
|
+
end
|
55
|
+
|
56
|
+
When /^(.*) within a cassette named "([^"]*)"$/ do |step, cassette_name|
|
57
|
+
VCR.use_cassette(cassette_name) { When step }
|
58
|
+
end
|
59
|
+
|
60
|
+
Then /^the response should be "([^"]*)"$/ do |expected_response|
|
61
|
+
@response.body.should == expected_response
|
62
|
+
end
|
63
|
+
"""
|
64
|
+
And a file named "features/vcr_example.feature" with:
|
65
|
+
"""
|
66
|
+
Feature: VCR example
|
67
|
+
|
68
|
+
@localhost_request
|
69
|
+
Scenario: tagged scenario
|
70
|
+
When a request is made to "http://localhost:7777/localhost_request_1"
|
71
|
+
Then the response should be "Hello localhost_request_1"
|
72
|
+
When a request is made to "http://localhost:7777/nested_cassette" within a cassette named "nested_cassette"
|
73
|
+
Then the response should be "Hello nested_cassette"
|
74
|
+
When a request is made to "http://localhost:7777/localhost_request_2"
|
75
|
+
Then the response should be "Hello localhost_request_2"
|
76
|
+
|
77
|
+
@disallowed_1
|
78
|
+
Scenario: tagged scenario
|
79
|
+
When a request is made to "http://localhost:7777/allowed" within a cassette named "allowed"
|
80
|
+
Then the response should be "Hello allowed"
|
81
|
+
When a request is made to "http://localhost:7777/disallowed_1"
|
82
|
+
|
83
|
+
@disallowed_2
|
84
|
+
Scenario: tagged scenario
|
85
|
+
When a request is made to "http://localhost:7777/disallowed_2"
|
86
|
+
"""
|
87
|
+
And the directory "features/cassettes" does not exist
|
88
|
+
When I run "cucumber WITH_SERVER=true features/vcr_example.feature"
|
89
|
+
Then it should fail with "3 scenarios (2 failed, 1 passed)"
|
90
|
+
And the output should contain each of the following:
|
91
|
+
| Real HTTP connections are disabled. Unregistered request: GET http://localhost:7777/disallowed_1 |
|
92
|
+
| Real HTTP connections are disabled. Unregistered request: GET http://localhost:7777/disallowed_2 |
|
93
|
+
And the file "features/cassettes/cucumber_tags/localhost_request.yml" should contain "body: Hello localhost_request_1"
|
94
|
+
And the file "features/cassettes/cucumber_tags/localhost_request.yml" should contain "body: Hello localhost_request_2"
|
95
|
+
And the file "features/cassettes/nested_cassette.yml" should contain "body: Hello nested_cassette"
|
96
|
+
And the file "features/cassettes/allowed.yml" should contain "body: Hello allowed"
|
97
|
+
|
98
|
+
# Run again without the server; we'll get the same responses because VCR
|
99
|
+
# will replay the recorded responses.
|
100
|
+
When I run "cucumber features/vcr_example.feature"
|
101
|
+
Then it should fail with "3 scenarios (2 failed, 1 passed)"
|
102
|
+
And the output should contain each of the following:
|
103
|
+
| Real HTTP connections are disabled. Unregistered request: GET http://localhost:7777/disallowed_1 |
|
104
|
+
| Real HTTP connections are disabled. Unregistered request: GET http://localhost:7777/disallowed_2 |
|
105
|
+
And the file "features/cassettes/cucumber_tags/localhost_request.yml" should contain "body: Hello localhost_request_1"
|
106
|
+
And the file "features/cassettes/cucumber_tags/localhost_request.yml" should contain "body: Hello localhost_request_2"
|
107
|
+
And the file "features/cassettes/nested_cassette.yml" should contain "body: Hello nested_cassette"
|
108
|
+
And the file "features/cassettes/allowed.yml" should contain "body: Hello allowed"
|
109
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
Feature: Usage with RSpec
|
2
|
+
|
3
|
+
VCR provides a macro that makes it easy to use a VCR cassette for an RSpec
|
4
|
+
example group. To use it, simply add `config.extend VCR::RSpec::Macros`
|
5
|
+
to your RSpec configuration block.
|
6
|
+
|
7
|
+
In any example group, add a `use_vcr_cassette` declaration to use a cassette
|
8
|
+
for that example group. You can use this in a few different ways:
|
9
|
+
|
10
|
+
* use_vcr_cassette
|
11
|
+
* Infers a cassette name from the example group description (and parent
|
12
|
+
example group descriptions).
|
13
|
+
* Uses the default_cassette_options you have configured.
|
14
|
+
* use_vcr_cassette "Cassette Name"
|
15
|
+
* Uses the given cassette name.
|
16
|
+
* Uses the default_cassette_options you have configured.
|
17
|
+
* use_vcr_cassette :cassette => :options
|
18
|
+
* Infers a cassette name from the example group description (and parent
|
19
|
+
example group descriptions).
|
20
|
+
* Uses the provided cassette options (merged with the defaults).
|
21
|
+
* use_vcr_cassette "Cassette Name", :cassette => :options
|
22
|
+
* Uses the given cassette name.
|
23
|
+
* Uses the provided cassette options (merged with the defaults).
|
24
|
+
|
25
|
+
Background:
|
26
|
+
Given the following files do not exist:
|
27
|
+
| spec/cassettes/VCR-RSpec_integration/without_an_explicit_cassette_name.yml |
|
28
|
+
| spec/cassettes/net_http_example.yml |
|
29
|
+
And a file named "spec/sinatra_app.rb" with:
|
30
|
+
"""
|
31
|
+
require 'vcr_cucumber_helpers'
|
32
|
+
|
33
|
+
start_sinatra_app(:port => 7777) do
|
34
|
+
get('/') { "Hello" }
|
35
|
+
end
|
36
|
+
"""
|
37
|
+
And a file named "spec/vcr_example_spec.rb" with:
|
38
|
+
"""
|
39
|
+
require 'spec_helper'
|
40
|
+
|
41
|
+
describe "VCR-RSpec integration" do
|
42
|
+
def make_http_request
|
43
|
+
Net::HTTP.get_response('localhost', '/', 7777).body
|
44
|
+
end
|
45
|
+
|
46
|
+
context "without an explicit cassette name" do
|
47
|
+
use_vcr_cassette
|
48
|
+
|
49
|
+
it 'records an http request' do
|
50
|
+
make_http_request.should == 'Hello'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "with an explicit cassette name" do
|
55
|
+
use_vcr_cassette "net_http_example"
|
56
|
+
|
57
|
+
it 'records an http request' do
|
58
|
+
make_http_request.should == 'Hello'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
"""
|
63
|
+
|
64
|
+
Scenario: Use `use_vcr_cassette` macro with RSpec 2
|
65
|
+
Given a file named "spec/spec_helper.rb" with:
|
66
|
+
"""
|
67
|
+
require 'sinatra_app'
|
68
|
+
require 'vcr'
|
69
|
+
|
70
|
+
VCR.config do |c|
|
71
|
+
c.cassette_library_dir = 'spec/cassettes'
|
72
|
+
c.stub_with :fakeweb
|
73
|
+
c.default_cassette_options = { :record => :new_episodes }
|
74
|
+
end
|
75
|
+
|
76
|
+
RSpec.configure do |c|
|
77
|
+
c.extend VCR::RSpec::Macros
|
78
|
+
end
|
79
|
+
"""
|
80
|
+
When I run "rspec spec/vcr_example_spec.rb"
|
81
|
+
Then the output should contain "2 examples, 0 failures"
|
82
|
+
And the file "spec/cassettes/VCR-RSpec_integration/without_an_explicit_cassette_name.yml" should contain "body: Hello"
|
83
|
+
And the file "spec/cassettes/net_http_example.yml" should contain "body: Hello"
|
84
|
+
|
85
|
+
Scenario: Use `use_vcr_cassette` macro with RSpec 1
|
86
|
+
Given a file named "spec/spec_helper.rb" with:
|
87
|
+
"""
|
88
|
+
require 'sinatra_app'
|
89
|
+
$LOAD_PATH.unshift(File.join(%w[ .. .. vendor rspec-1 lib ]))
|
90
|
+
|
91
|
+
require 'spec'
|
92
|
+
require 'spec/autorun'
|
93
|
+
|
94
|
+
require 'vcr'
|
95
|
+
|
96
|
+
VCR.config do |c|
|
97
|
+
c.cassette_library_dir = 'spec/cassettes'
|
98
|
+
c.stub_with :fakeweb
|
99
|
+
c.default_cassette_options = { :record => :new_episodes }
|
100
|
+
end
|
101
|
+
|
102
|
+
Spec::Runner.configure do |c|
|
103
|
+
c.extend VCR::RSpec::Macros
|
104
|
+
end
|
105
|
+
"""
|
106
|
+
When I run "ruby -Ispec spec/vcr_example_spec.rb"
|
107
|
+
Then the output should contain "2 examples, 0 failures"
|
108
|
+
And the file "spec/cassettes/VCR-RSpec_integration/without_an_explicit_cassette_name.yml" should contain "body: Hello"
|
109
|
+
And the file "spec/cassettes/net_http_example.yml" should contain "body: Hello"
|
110
|
+
|