vcr 1.3.1 → 1.3.2
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.
- 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
|
+
|