vcr 1.6.0 → 1.7.0

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.
Files changed (82) hide show
  1. data/.gemtest +0 -0
  2. data/.gitignore +5 -0
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +29 -2
  5. data/Gemfile +3 -3
  6. data/README.md +55 -11
  7. data/Rakefile +45 -4
  8. data/features/.nav +6 -0
  9. data/features/{README.md → about_the_cucumber_features.md} +1 -1
  10. data/features/cassettes/update_content_length_header.feature +106 -0
  11. data/features/configuration/default_cassette_options.feature +20 -2
  12. data/features/configuration/filter_sensitive_data.feature +154 -0
  13. data/features/getting_started.md +67 -0
  14. data/features/record_modes/all.feature +4 -2
  15. data/features/record_modes/new_episodes.feature +8 -2
  16. data/features/record_modes/none.feature +4 -2
  17. data/features/record_modes/once.feature +92 -0
  18. data/features/step_definitions/cli_steps.rb +18 -0
  19. data/lib/vcr.rb +13 -6
  20. data/lib/vcr/cassette.rb +36 -15
  21. data/lib/vcr/config.rb +14 -2
  22. data/lib/vcr/deprecations/cassette.rb +29 -0
  23. data/lib/vcr/deprecations/config.rb +18 -0
  24. data/lib/vcr/deprecations/http_stubbing_adapters/common.rb +9 -0
  25. data/lib/vcr/deprecations/http_stubbing_adapters/fakeweb.rb +11 -0
  26. data/lib/vcr/http_stubbing_adapters/common.rb +1 -1
  27. data/lib/vcr/http_stubbing_adapters/fakeweb.rb +2 -7
  28. data/lib/vcr/http_stubbing_adapters/multi_object_proxy.rb +1 -1
  29. data/lib/vcr/middleware/common.rb +3 -5
  30. data/lib/vcr/rspec.rb +1 -38
  31. data/lib/vcr/structs/http_interaction.rb +29 -0
  32. data/lib/vcr/structs/request.rb +6 -0
  33. data/lib/vcr/structs/response.rb +4 -0
  34. data/lib/vcr/{cucumber_tags.rb → test_frameworks/cucumber.rb} +10 -2
  35. data/lib/vcr/test_frameworks/rspec.rb +37 -0
  36. data/lib/vcr/util/basic_object.rb +32 -28
  37. data/lib/vcr/{hooks.rb → util/hooks.rb} +3 -6
  38. data/lib/vcr/util/internet_connection.rb +1 -1
  39. data/lib/vcr/util/ping.rb +21 -17
  40. data/lib/vcr/util/variable_args_block_caller.rb +12 -0
  41. data/lib/vcr/util/yaml.rb +11 -0
  42. data/lib/vcr/version.rb +1 -1
  43. data/script/FullBuildRakeFile +7 -0
  44. data/spec/monkey_patches.rb +0 -7
  45. data/spec/spec_helper.rb +40 -8
  46. data/spec/support/http_library_adapters.rb +0 -262
  47. data/spec/support/shared_example_groups/http_library.rb +256 -0
  48. data/spec/support/{http_stubbing_adapter.rb → shared_example_groups/http_stubbing_adapter.rb} +15 -3
  49. data/spec/support/shared_example_groups/ignore_localhost_deprecation.rb +28 -0
  50. data/spec/support/{normalizers.rb → shared_example_groups/normalizers.rb} +3 -3
  51. data/spec/support/{version_checker.rb → shared_example_groups/version_checking.rb} +1 -1
  52. data/spec/vcr/cassette_spec.rb +80 -28
  53. data/spec/vcr/config_spec.rb +55 -8
  54. data/spec/vcr/deprecations/cassette_spec.rb +57 -0
  55. data/spec/vcr/deprecations/config_spec.rb +30 -0
  56. data/spec/vcr/deprecations/http_stubbing_adapters/common_spec.rb +7 -0
  57. data/spec/vcr/deprecations/http_stubbing_adapters/fakeweb_spec.rb +16 -0
  58. data/spec/vcr/extensions/net_http_response_spec.rb +1 -3
  59. data/spec/vcr/extensions/net_http_spec.rb +1 -3
  60. data/spec/vcr/http_stubbing_adapters/fakeweb_spec.rb +1 -4
  61. data/spec/vcr/http_stubbing_adapters/faraday_spec.rb +1 -4
  62. data/spec/vcr/http_stubbing_adapters/typhoeus_spec.rb +1 -4
  63. data/spec/vcr/http_stubbing_adapters/webmock_spec.rb +1 -3
  64. data/spec/vcr/middleware/faraday_spec.rb +4 -4
  65. data/spec/vcr/middleware/rack_spec.rb +4 -4
  66. data/spec/vcr/structs/http_interaction_spec.rb +61 -0
  67. data/spec/vcr/structs/request_spec.rb +20 -2
  68. data/spec/vcr/structs/response_spec.rb +23 -1
  69. data/spec/vcr/structs/response_status_spec.rb +1 -1
  70. data/spec/vcr/{cucumber_tags_spec.rb → test_frameworks/cucumber_spec.rb} +12 -8
  71. data/spec/vcr/{rspec_spec.rb → test_frameworks/rspec_spec.rb} +0 -0
  72. data/spec/vcr/{hooks_spec.rb → util/hooks_spec.rb} +3 -3
  73. data/spec/vcr/util/internet_connection_spec.rb +3 -3
  74. data/spec/vcr_spec.rb +3 -3
  75. data/vcr.gemspec +5 -5
  76. metadata +149 -131
  77. data/Gemfile.lock +0 -155
  78. data/lib/vcr/deprecations.rb +0 -54
  79. data/spec/support/disable_warnings.rb +0 -12
  80. data/spec/support/temp_cassette_library_dir.rb +0 -16
  81. data/spec/support/webmock_macros.rb +0 -14
  82. data/spec/vcr/deprecations_spec.rb +0 -139
@@ -0,0 +1,18 @@
1
+ module VCR
2
+ module Config
3
+ def http_stubbing_library
4
+ warn "WARNING: `VCR::Config.http_stubbing_library` is deprecated. Use `VCR::Config.http_stubbing_libraries` instead."
5
+ @http_stubbing_libraries && @http_stubbing_libraries.first
6
+ end
7
+
8
+ def http_stubbing_library=(library)
9
+ warn "WARNING: `VCR::Config.http_stubbing_library = #{library.inspect}` is deprecated. Use `VCR::Config.stub_with #{library.inspect}` instead."
10
+ stub_with library
11
+ end
12
+
13
+ def ignore_localhost?
14
+ warn "WARNING: `VCR::Config.ignore_localhost?` is deprecated. Check the list of ignored hosts using `VCR::Config.ignored_hosts` instead."
15
+ (VCR::LOCALHOST_ALIASES - ignored_hosts).empty?
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module VCR
2
+ module HttpStubbingAdapters
3
+ module Common
4
+ def ignore_localhost?
5
+ VCR::Config.ignore_localhost?
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module VCR
2
+ module HttpStubbingAdapters
3
+ module FakeWeb
4
+ def self.const_missing(const)
5
+ return super unless const == :LOCALHOST_REGEX
6
+ warn "WARNING: `VCR::HttpStubbingAdapters::FakeWeb::LOCALHOST_REGEX` is deprecated."
7
+ VCR::Regexes.url_regex_for_hosts(VCR::LOCALHOST_ALIASES)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -30,7 +30,7 @@ module VCR
30
30
  end
31
31
 
32
32
  RECORDING_INSTRUCTIONS = "You can use VCR to automatically record this request and replay it later. " +
33
- "For more details, visit the VCR wiki at: http://github.com/myronmarston/vcr/wiki"
33
+ "For more details, visit the VCR documentation at: http://relishapp.com/myronmarston/vcr/v/#{VCR.version.gsub('.', '-')}"
34
34
 
35
35
  def enabled?
36
36
  [nil, self].include? VCR::HttpStubbingAdapters::Common.exclusively_enabled_adapter
@@ -1,4 +1,5 @@
1
1
  require 'fakeweb'
2
+ require 'vcr/deprecations/http_stubbing_adapters/fakeweb'
2
3
  require 'vcr/extensions/net_http'
3
4
 
4
5
  module VCR
@@ -80,7 +81,7 @@ module VCR
80
81
  end
81
82
 
82
83
  def response_hash(response)
83
- response.headers.merge(
84
+ (response.headers || {}).merge(
84
85
  :body => response.body,
85
86
  :status => [response.status.code.to_s, response.status.message]
86
87
  )
@@ -92,12 +93,6 @@ module VCR
92
93
  raise UnsupportedRequestMatchAttributeError.new("FakeWeb does not support matching requests on #{invalid_attributes.join(' or ')}")
93
94
  end
94
95
  end
95
-
96
- def self.const_missing(const)
97
- return super unless const == :LOCALHOST_REGEX
98
- warn "WARNING: `VCR::HttpStubbingAdapters::FakeWeb::LOCALHOST_REGEX` is deprecated."
99
- VCR::Regexes.url_regex_for_hosts(VCR::LOCALHOST_ALIASES)
100
- end
101
96
  end
102
97
  end
103
98
  end
@@ -1,6 +1,6 @@
1
1
  module VCR
2
2
  module HttpStubbingAdapters
3
- class MultiObjectProxy < defined?(::BasicObject) ? ::BasicObject : VCR::BasicObject
3
+ class MultiObjectProxy < VCR::BasicObject
4
4
 
5
5
  def self.for(*objects)
6
6
  return objects.first if objects.size == 1
@@ -1,6 +1,8 @@
1
1
  module VCR
2
2
  module Middleware
3
3
  module Common
4
+ include VCR::VariableArgsBlockCaller
5
+
4
6
  def initialize(app, &block)
5
7
  raise ArgumentError.new("You must provide a block to set the cassette options") unless block
6
8
  @app, @cassette_arguments_block = app, block
@@ -10,11 +12,7 @@ module VCR
10
12
 
11
13
  def cassette_arguments(env)
12
14
  arguments = CassetteArguments.new
13
-
14
- block_args = [arguments]
15
- block_args << env unless @cassette_arguments_block.arity == 1
16
-
17
- @cassette_arguments_block.call(*block_args)
15
+ call_block(@cassette_arguments_block, arguments, env)
18
16
  [arguments.name, arguments.options]
19
17
  end
20
18
  end
@@ -1,39 +1,2 @@
1
1
  require 'vcr'
2
-
3
- module VCR
4
- module RSpec
5
- module Macros
6
- def use_vcr_cassette(*args)
7
- options = args.last.is_a?(Hash) ? args.pop : {}
8
- name = args.first || infer_cassette_name
9
-
10
- before(:each) do
11
- VCR.insert_cassette(name, options)
12
- end
13
-
14
- after(:each) do
15
- VCR.eject_cassette
16
- end
17
- end
18
-
19
- private
20
-
21
- def infer_cassette_name
22
- # RSpec 1 exposes #description_parts; use that if its available
23
- return description_parts.join("/") if respond_to?(:description_parts)
24
-
25
- # Otherwise use RSpec 2 metadata...
26
- group_descriptions = []
27
- klass = self
28
-
29
- while klass.respond_to?(:metadata) && klass.metadata
30
- group_descriptions << klass.metadata[:example_group][:description]
31
- klass = klass.superclass
32
- end
33
-
34
- group_descriptions.compact.reverse.join('/')
35
- end
36
- end
37
- end
38
- end
39
-
2
+ warn "`require 'vcr/rspec'` is deprecated. You no longer need to require this file--just require 'vcr'."
@@ -12,5 +12,34 @@ module VCR
12
12
  def ignored?
13
13
  @ignored
14
14
  end
15
+
16
+ def filter!(text, replacement_text)
17
+ return self if [text, replacement_text].any? { |t| t.to_s.empty? }
18
+ filter_object!(self, text, replacement_text)
19
+ end
20
+
21
+ private
22
+
23
+ def filter_object!(object, text, replacement_text)
24
+ if object.respond_to?(:gsub)
25
+ object.gsub!(text, replacement_text) if object.include?(text)
26
+ elsif Hash === object
27
+ filter_hash!(object, text, replacement_text)
28
+ elsif object.respond_to?(:each)
29
+ # This handles nested arrays and structs
30
+ object.each { |o| filter_object!(o, text, replacement_text) }
31
+ end
32
+
33
+ object
34
+ end
35
+
36
+ def filter_hash!(hash, text, replacement_text)
37
+ filter_object!(hash.values, text, replacement_text)
38
+
39
+ hash.keys.each do |k|
40
+ new_key = filter_object!(k.dup, text, replacement_text)
41
+ hash[new_key] = hash.delete(k) unless k == new_key
42
+ end
43
+ end
15
44
  end
16
45
  end
@@ -13,6 +13,12 @@ module VCR
13
13
  )
14
14
  end
15
15
 
16
+ @@object_method = Object.instance_method(:method)
17
+ def method(*args)
18
+ return super if args.empty?
19
+ @@object_method.bind(self).call(*args)
20
+ end
21
+
16
22
  def matcher(match_attributes)
17
23
  RequestMatcher.new(self, match_attributes)
18
24
  end
@@ -11,6 +11,10 @@ module VCR
11
11
  response.http_version
12
12
  )
13
13
  end
14
+
15
+ def update_content_length_header
16
+ headers['content-length'] &&= [body.length.to_s]
17
+ end
14
18
  end
15
19
  end
16
20
 
@@ -21,8 +21,16 @@ module VCR
21
21
  tag_name = "@#{tag_name}" unless tag_name =~ /^@/
22
22
  cassette_name = "cucumber_tags/#{tag_name.gsub(/\A@/, '')}"
23
23
 
24
- @main_object.Around(tag_name) do |scenario, block|
25
- VCR.use_cassette(cassette_name, options, &block)
24
+ # It would be nice to use an Around hook here, but
25
+ # cucumber has a bug: background steps do not run
26
+ # within an around hook.
27
+ # https://gist.github.com/652968
28
+ @main_object.Before(tag_name) do
29
+ VCR.insert_cassette(cassette_name, options)
30
+ end
31
+
32
+ @main_object.After(tag_name) do
33
+ VCR.eject_cassette
26
34
  end
27
35
 
28
36
  self.class.add_tag(tag_name)
@@ -0,0 +1,37 @@
1
+ module VCR
2
+ module RSpec
3
+ module Macros
4
+ def use_vcr_cassette(*args)
5
+ options = args.last.is_a?(Hash) ? args.pop : {}
6
+ name = args.first || infer_cassette_name
7
+
8
+ before(:each) do
9
+ VCR.insert_cassette(name, options)
10
+ end
11
+
12
+ after(:each) do
13
+ VCR.eject_cassette
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def infer_cassette_name
20
+ # RSpec 1 exposes #description_parts; use that if its available
21
+ return description_parts.join("/") if respond_to?(:description_parts)
22
+
23
+ # Otherwise use RSpec 2 metadata...
24
+ group_descriptions = []
25
+ klass = self
26
+
27
+ while klass.respond_to?(:metadata) && klass.metadata
28
+ group_descriptions << klass.metadata[:example_group][:description]
29
+ klass = klass.superclass
30
+ end
31
+
32
+ group_descriptions.compact.reverse.join('/')
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -1,35 +1,39 @@
1
1
  module VCR
2
- # taken directly from backports:
3
- # https://github.com/marcandre/backports/blob/v1.18.2/lib/backports/basic_object.rb
4
- class BasicObject
5
- KEEP = [:instance_eval, :instance_exec, :__send__,
6
- "instance_eval", "instance_exec", "__send__"]
7
- # undefine almost all instance methods
8
- begin
9
- old_verbose, $VERBOSE = $VERBOSE, nil # silence the warning for undefining __id__
10
- (instance_methods - KEEP).each do |method|
11
- undef_method method
2
+ if defined?(::BasicObject)
3
+ BasicObject = ::BasicObject
4
+ else
5
+ # taken directly from backports:
6
+ # https://github.com/marcandre/backports/blob/v1.18.2/lib/backports/basic_object.rb
7
+ class BasicObject
8
+ KEEP = [:instance_eval, :instance_exec, :__send__,
9
+ "instance_eval", "instance_exec", "__send__"]
10
+ # undefine almost all instance methods
11
+ begin
12
+ old_verbose, $VERBOSE = $VERBOSE, nil # silence the warning for undefining __id__
13
+ (instance_methods - KEEP).each do |method|
14
+ undef_method method
15
+ end
16
+ ensure
17
+ $VERBOSE = old_verbose
12
18
  end
13
- ensure
14
- $VERBOSE = old_verbose
15
- end
16
19
 
17
- class << self
18
- def === (cmp)
19
- true
20
- end
20
+ class << self
21
+ def === (cmp)
22
+ true
23
+ end
21
24
 
22
- # Let's try to keep things clean, in case methods have been added to Object
23
- # either directly or through an included module.
24
- # We'll do this whenever a class is derived from BasicObject
25
- # Ideally, we'd do this by trapping Object.method_added
26
- # and M.method_added for any module M included in Object or a submodule
27
- # Seems really though to get right, but pull requests welcome ;-)
28
- def inherited(sub)
29
- BasicObject.class_eval do
30
- (instance_methods - KEEP).each do |method|
31
- if Object.method_defined?(method) && instance_method(method).owner == Object.instance_method(method).owner
32
- undef_method method
25
+ # Let's try to keep things clean, in case methods have been added to Object
26
+ # either directly or through an included module.
27
+ # We'll do this whenever a class is derived from BasicObject
28
+ # Ideally, we'd do this by trapping Object.method_added
29
+ # and M.method_added for any module M included in Object or a submodule
30
+ # Seems really though to get right, but pull requests welcome ;-)
31
+ def inherited(sub)
32
+ BasicObject.class_eval do
33
+ (instance_methods - KEEP).each do |method|
34
+ if Object.method_defined?(method) && instance_method(method).owner == Object.instance_method(method).owner
35
+ undef_method method
36
+ end
33
37
  end
34
38
  end
35
39
  end
@@ -1,8 +1,10 @@
1
1
  module VCR
2
2
  module Hooks
3
+ include VariableArgsBlockCaller
4
+
3
5
  def invoke_hook(hook, tag, *args)
4
6
  hooks_for(hook, tag).each do |callback|
5
- callback.call(*args_for_callback(args, callback))
7
+ call_block(callback, *args)
6
8
  end
7
9
  end
8
10
 
@@ -36,10 +38,5 @@ module VCR
36
38
  hooks += for_hook[nil] unless tag.nil? # untagged hooks
37
39
  hooks
38
40
  end
39
-
40
- def args_for_callback(args, callback)
41
- return args if callback.arity < 0
42
- args.first([args.size, callback.arity].min)
43
- end
44
41
  end
45
42
  end
@@ -7,7 +7,7 @@ module VCR
7
7
  EXAMPLE_HOST = "example.com"
8
8
 
9
9
  def available?
10
- @available = Ping.pingecho(EXAMPLE_HOST, 1, 80) unless defined?(@available)
10
+ @available = VCR::Ping.pingecho(EXAMPLE_HOST, 1, 80) unless defined?(@available)
11
11
  @available
12
12
  end
13
13
  end
@@ -1,26 +1,30 @@
1
1
  # Ruby 1.8 provides Ping.pingecho, but it was removed in 1.9.
2
2
  # So we try requiring it, and if that fails, define it ourselves.
3
- begin
4
- require 'ping'
5
- rescue LoadError
6
- # This is copied, verbatim, from Ruby 1.8.7's ping.rb.
7
- require 'timeout'
8
- require "socket"
9
3
 
10
- module Ping
11
- def pingecho(host, timeout=5, service="echo")
12
- begin
13
- timeout(timeout) do
14
- s = TCPSocket.new(host, service)
15
- s.close
4
+ module VCR
5
+ begin
6
+ require 'ping'
7
+ Ping = ::Ping
8
+ rescue LoadError
9
+ # This is copied, verbatim, from Ruby 1.8.7's ping.rb.
10
+ require 'timeout'
11
+ require "socket"
12
+
13
+ module Ping
14
+ def pingecho(host, timeout=5, service="echo")
15
+ begin
16
+ timeout(timeout) do
17
+ s = TCPSocket.new(host, service)
18
+ s.close
19
+ end
20
+ rescue Errno::ECONNREFUSED
21
+ return true
22
+ rescue Timeout::Error, StandardError
23
+ return false
16
24
  end
17
- rescue Errno::ECONNREFUSED
18
25
  return true
19
- rescue Timeout::Error, StandardError
20
- return false
21
26
  end
22
- return true
27
+ module_function :pingecho
23
28
  end
24
- module_function :pingecho
25
29
  end
26
30
  end
@@ -0,0 +1,12 @@
1
+ module VCR
2
+ module VariableArgsBlockCaller
3
+ def call_block(block, *args)
4
+ if block.arity >= 0
5
+ args = args.first([args.size, block.arity].min)
6
+ end
7
+
8
+ block.call(*args)
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,11 @@
1
+ require 'yaml'
2
+
3
+ module VCR
4
+ # Attempt to use psych if it is available.
5
+ YAML = begin
6
+ require 'psych'
7
+ Psych
8
+ rescue LoadError
9
+ ::YAML
10
+ end
11
+ end