vcr 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
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