Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: myronmarston/vcr
...
head fork: myronmarston/vcr
Checking mergeability… Don't worry, you can still create the pull request.
  • 19 commits
  • 50 files changed
  • 0 commit comments
  • 1 contributor
Commits on Jan 16, 2011
@myronmarston Improve full build output. 5cdbba3
Commits on Jan 21, 2011
@myronmarston Ensure headers get serialized as raw strings.
Closes #39.
7ee38dc
@myronmarston 1.5.1 release. be6672d
Commits on Jan 22, 2011
@myronmarston Fix spec doc strings. fd41836
@myronmarston Clean up VCR.version. c9d9bca
@myronmarston Refactoring: extract private method. 44acf01
Commits on Jan 31, 2011
@myronmarston Update benchmarks. 356eca4
@myronmarston Updated typhoeus to latest 0.2.1 release.
The latest includes a new ignore_hosts option.
bdabbb3
@myronmarston Extract some logic into new method: VCR::Config.uri_should_be_ignored? ee52fa8
@myronmarston Remove #ignore_localhost? from the http stubbing adapters. 7b6c9f3
@myronmarston Add new VCR::Config.ignore_hosts option. bf907f7
@myronmarston Add deprecations.
The following are deprecated:

- VCR::Config.ignore_localhost?
- VCR::HttpStubbingAdapters::{FakeWeb,WebMock,Typhoeus,Faraday}.ignore_localhost?
- VCR::HttpStubbingAdapters::FakeWeb::LOCALHOST_REGEX
dbfb3f8
@myronmarston Refactoring: extract regex construction into module. bd4f25b
@myronmarston Add cuke for new ignore_hosts configuration option.
Closes #30.
0883eea
@myronmarston Clean up set construction. e94e616
@myronmarston Add cuke demonstrating Net/HTTP usage over HTTPS. 3a5100d
Commits on Feb 03, 2011
@myronmarston Split structs.rb (and structs_spec.rb) into separate files for each c…
…lass and module.
aa7725d
Commits on Feb 04, 2011
@myronmarston Fix require (no more vcr/structs file). b5c66b2
@myronmarston 1.6.0 release. de8c689
Showing with 998 additions and 598 deletions.
  1. +19 −1 CHANGELOG.md
  2. +1 −1  Gemfile
  3. +4 −3 Gemfile.lock
  4. +4 −1 Rakefile
  5. +0 −5 TODO.md
  6. +4 −4 benchmarks/http_stubbing_libraries.rb
  7. +1 −0  features/.nav
  8. +61 −0 features/configuration/ignore_hosts.feature
  9. +34 −0 features/http_libraries/net_http.feature
  10. +16 −1 features/step_definitions/cli_steps.rb
  11. +23 −14 lib/vcr.rb
  12. +2 −4 lib/vcr/cassette.rb
  13. +20 −5 lib/vcr/config.rb
  14. +27 −14 lib/vcr/deprecations.rb
  15. +14 −9 lib/vcr/http_stubbing_adapters/fakeweb.rb
  16. +12 −3 lib/vcr/http_stubbing_adapters/faraday.rb
  17. +3 −7 lib/vcr/http_stubbing_adapters/typhoeus.rb
  18. +17 −7 lib/vcr/http_stubbing_adapters/webmock.rb
  19. +1 −1  lib/vcr/middleware/faraday.rb
  20. +12 −8 lib/vcr/request_matcher.rb
  21. +0 −169 lib/vcr/structs.rb
  22. +16 −0 lib/vcr/structs/http_interaction.rb
  23. +24 −0 lib/vcr/structs/normalizers/body.rb
  24. +56 −0 lib/vcr/structs/normalizers/header.rb
  25. +17 −0 lib/vcr/structs/normalizers/status_message.rb
  26. +34 −0 lib/vcr/structs/normalizers/uri.rb
  27. +20 −0 lib/vcr/structs/request.rb
  28. +16 −0 lib/vcr/structs/response.rb
  29. +9 −0 lib/vcr/structs/response_status.rb
  30. +37 −0 lib/vcr/util/regexes.rb
  31. +16 −5 lib/vcr/version.rb
  32. +35 −7 script/FullBuildRakeFile
  33. +26 −3 spec/spec_helper.rb
  34. +11 −12 spec/support/http_library_adapters.rb
  35. +2 −16 spec/support/http_stubbing_adapter.rb
  36. +84 −0 spec/support/normalizers.rb
  37. +1 −1  spec/support/version_checker.rb
  38. +8 −10 spec/vcr/cassette_spec.rb
  39. +63 −17 spec/vcr/config_spec.rb
  40. +83 −24 spec/vcr/deprecations_spec.rb
  41. +1 −1  spec/vcr/http_stubbing_adapters/multi_object_proxy_spec.rb
  42. +2 −2 spec/vcr/http_stubbing_adapters/typhoeus_spec.rb
  43. +1 −1  spec/vcr/middleware/faraday_spec.rb
  44. +23 −0 spec/vcr/structs/http_interaction_spec.rb
  45. +54 −0 spec/vcr/structs/request_spec.rb
  46. +39 −0 spec/vcr/structs/response_spec.rb
  47. +18 −0 spec/vcr/structs/response_status_spec.rb
  48. +0 −187 spec/vcr/structs_spec.rb
  49. +26 −54 spec/vcr_spec.rb
  50. +1 −1  vcr.gemspec
View
20 CHANGELOG.md
@@ -2,7 +2,25 @@
## In git
-[Full Changelog](http://github.com/myronmarston/vcr/compare/v1.5.0...master)
+[Full Changelog](http://github.com/myronmarston/vcr/compare/v1.6.0...master)
+
+## 1.6.0 (February 3, 2011)
+
+[Full Changelog](http://github.com/myronmarston/vcr/compare/v1.5.1...v1.6.0)
+
+* Add new `ignore_hosts` configuration option that allows you to ignore
+ any host (not just localhost aliases, as the `ignore_localhost` option
+ works). Feature suggested by [Claudio Poli](https://github.com/masterkain).
+* Upgraded to the latest Typhoeus (0.2.1).
+* General code clean up and refactoring.
+
+## 1.5.1 (January 12, 2011)
+
+[Full Changelog](http://github.com/myronmarston/vcr/compare/v1.5.0...v1.5.1)
+
+* Fix response and request serialization so that the headers are raw
+ strings. This fixes intermittent YAML seg faults for paperclip
+ uploads to S3. But reported by [Rob Slifka](https://github.com/rslifka).
## 1.5.0 (January 12, 2011)
View
2  Gemfile
@@ -7,7 +7,7 @@ group :development do
gem 'patron', '~> 0.4.6'
gem 'em-http-request', '~> 0.2.7'
gem 'curb', '~> 0.7.8'
- gem 'typhoeus', '~> 0.2.0'
+ gem 'typhoeus', '~> 0.2.1'
end
platforms :jruby do
View
7 Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- vcr (1.5.0)
+ vcr (1.6.0)
GEM
remote: http://rubygems.org/
@@ -113,7 +113,8 @@ GEM
thor (0.14.6)
tilt (1.1)
timecop (0.3.5)
- typhoeus (0.2.0)
+ typhoeus (0.2.1)
+ mime-types
webmock (1.6.2)
addressable (>= 2.2.2)
crack (>= 0.1.7)
@@ -149,6 +150,6 @@ DEPENDENCIES
shoulda (~> 2.9.2)
sinatra (~> 1.1.0)
timecop (~> 0.3.5)
- typhoeus (~> 0.2.0)
+ typhoeus (~> 0.2.1)
vcr!
webmock (~> 1.6.0)
View
5 Rakefile
@@ -5,7 +5,10 @@ Bundler::GemHelper.install_tasks
require 'rake'
require "rspec/core/rake_task"
-RSpec::Core::RakeTask.new(:spec)
+RSpec::Core::RakeTask.new(:spec) do |t|
+ t.verbose = false
+ t.rspec_opts = %w[--format progress] if ENV['FULL_BUILD']
+end
desc "Run all examples using rcov"
RSpec::Core::RakeTask.new :rcov => :cleanup_rcov_files do |t|
View
5 TODO.md
@@ -1,5 +0,0 @@
-* Use fakefs gem instead of using temp_dir in specs.
-* Fix #method vs .method in specs.
-* Cuke for Net::HTTP HTTPS request
-* Cuke for multiple simultaneous em-http-request
-* Ensure the checkpoints are properly deep-duped
View
8 benchmarks/http_stubbing_libraries.rb
@@ -50,10 +50,10 @@ def perform_benchmark(name)
# Output on my machine:
#
# Benchmarking Single setup/teardown:
-# webmock 0.000000 0.000000 8.500000 ( 8.559143)
-# fakeweb 0.000000 0.000000 1.900000 ( 1.967160)
+# webmock 0.000000 0.000000 6.950000 ( 6.981525)
+# fakeweb 0.000000 0.010000 1.750000 ( 1.740679)
#
#
# Benchmarking Setup/teardown for each http request:
-# webmock 0.000000 0.000000 9.710000 ( 9.764760)
-# fakeweb 0.000000 0.000000 2.470000 ( 2.479292)
+# webmock 0.000000 0.000000 7.970000 ( 7.981383)
+# fakeweb 0.000000 0.000000 2.210000 ( 2.203478)
View
1  features/.nav
@@ -12,6 +12,7 @@
- cassette_library_dir.feature
- stub_with.feature
- default_cassette_options.feature
+ - ignore_hosts.feature
- ignore_localhost.feature
- hooks.feature
- allow_http_connections_when_no_cassette.feature
View
61 features/configuration/ignore_hosts.feature
@@ -0,0 +1,61 @@
+Feature: ignore_hosts
+
+ The `ignore_hosts` configuration option can be used to prevent VCR
+ from having any affect on requests to particular hosts.
+ Requests to ignored hosts will not be recorded and will always be
+ allowed, regardless of the record mode, and even outside of a
+ `VCR.use_cassette` block.
+
+ If you only want to ignore localhost (and its various aliases) you
+ may want to use the `ignore_localhost` option instead.
+
+ Background:
+ Given a file named "sinatra_app.rb" with:
+ """
+ require 'vcr_cucumber_helpers'
+
+ response_count = 0
+ start_sinatra_app(:port => 7777) do
+ get('/') { "Response #{response_count += 1}" }
+ end
+ """
+
+ Scenario Outline: ignored host requests are not recorded and are always allowed
+ Given a file named "ignore_hosts.rb" with:
+ """
+ require 'vcr_cucumber_helpers'
+ include_http_adapter_for("<http_lib>")
+ require 'sinatra_app.rb'
+
+ require 'vcr'
+
+ VCR.config do |c|
+ c.ignore_hosts '127.0.0.1', 'localhost'
+ c.cassette_library_dir = 'cassettes'
+ c.stub_with <stub_with>
+ end
+
+ VCR.use_cassette('example', :record => :new_episodes) do
+ puts response_body_for(:get, "http://localhost:7777/")
+ end
+
+ puts response_body_for(:get, "http://localhost:7777/")
+ """
+ When I run "ruby ignore_hosts.rb"
+ Then it should pass with:
+ """
+ Response 1
+ Response 2
+ """
+ And the file "cassettes/example.yml" should not exist
+
+ Examples:
+ | stub_with | http_lib |
+ | :fakeweb | net/http |
+ | :webmock | net/http |
+ | :webmock | httpclient |
+ | :webmock | patron |
+ | :webmock | curb |
+ | :webmock | em-http-request |
+ | :typhoeus | typhoeus |
+
View
34 features/http_libraries/net_http.feature
@@ -135,3 +135,37 @@ Feature: Net::HTTP
| stub_with |
| :fakeweb |
| :webmock |
+
+ Scenario Outline: Make an HTTPS request
+ Given a file named "vcr_https.rb" with:
+ """
+ require 'vcr'
+
+ VCR.config do |c|
+ c.stub_with <stub_with>
+ c.cassette_library_dir = 'cassettes'
+ end
+
+ uri = URI("https://gist.github.com/raw/fb555cb593f3349d53af/6921dd638337d3f6a51b0e02e7f30e3c414f70d6/vcr_gist")
+
+ VCR.use_cassette('https', :record => :new_episodes) do
+ http = Net::HTTP.new(uri.host, uri.port)
+ http.use_ssl = true
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ response = http.request_get(uri.path)
+
+ puts response.body
+ end
+ """
+ When I run "ruby vcr_https.rb"
+ Then the output should contain "VCR gist"
+ And the file "cassettes/https.yml" should contain "body: VCR gist"
+
+ When I modify the file "cassettes/https.yml" to replace "body: VCR gist" with "body: HTTPS replaying works"
+ And I run "ruby vcr_https.rb"
+ Then the output should contain "HTTPS replaying works"
+
+ Examples:
+ | stub_with |
+ | :fakeweb |
+ | :webmock |
View
17 features/step_definitions/cli_steps.rb
@@ -1,4 +1,4 @@
-require 'vcr/structs'
+require 'vcr'
module VCRHelpers
YAML_REGEX_FOR_1_9_1 = Regexp.union(*[
@@ -36,6 +36,17 @@ def normalize_cassette_structs(content)
structs
end
+
+ def modify_file(file_name, orig_text, new_text)
+ in_current_dir do
+ file = File.read(file_name)
+ regex = /#{Regexp.escape(orig_text)}/
+ file.should =~ regex
+
+ file = file.gsub(regex, new_text)
+ File.open(file_name, 'w') { |f| f.write(file) }
+ end
+ end
end
World(VCRHelpers)
@@ -55,6 +66,10 @@ def normalize_cassette_structs(content)
set_env('DAYS_PASSED', day_count)
end
+When /^I modify the file "([^"]*)" to replace "([^"]*)" with "([^"]*)"$/ do |file_name, orig_text, new_text|
+ modify_file(file_name, orig_text, new_text)
+end
+
Then /^the file "([^"]*)" should exist$/ do |file_name|
check_file_presence([file_name], true)
end
View
37 lib/vcr.rb
@@ -2,10 +2,19 @@
require 'vcr/config'
require 'vcr/deprecations'
require 'vcr/request_matcher'
-require 'vcr/structs'
+require 'vcr/util/regexes'
require 'vcr/version'
require 'vcr/http_stubbing_adapters/common'
+require 'vcr/structs/normalizers/body'
+require 'vcr/structs/normalizers/header'
+require 'vcr/structs/normalizers/status_message'
+require 'vcr/structs/normalizers/uri'
+require 'vcr/structs/http_interaction'
+require 'vcr/structs/request'
+require 'vcr/structs/response'
+require 'vcr/structs/response_status'
+
module VCR
extend self
@@ -65,7 +74,7 @@ def config
yield VCR::Config
http_stubbing_adapter.check_version!
http_stubbing_adapter.set_http_connections_allowed_to_default
- http_stubbing_adapter.ignore_localhost = VCR::Config.ignore_localhost?
+ http_stubbing_adapter.ignored_hosts = VCR::Config.ignored_hosts
end
def cucumber_tags(&block)
@@ -79,16 +88,7 @@ def http_stubbing_adapter
raise ArgumentError.new("You have configured VCR to use both :fakeweb and :webmock. You cannot use both.")
end
- adapters = VCR::Config.http_stubbing_libraries.map do |lib|
- case lib
- when :fakeweb; HttpStubbingAdapters::FakeWeb
- when :webmock; HttpStubbingAdapters::WebMock
- when :typhoeus; HttpStubbingAdapters::Typhoeus
- when :faraday; HttpStubbingAdapters::Faraday
- else raise ArgumentError.new("#{lib.inspect} is not a supported HTTP stubbing library.")
- end
- end
-
+ adapters = VCR::Config.http_stubbing_libraries.map { |l| adapter_for(l) }
raise ArgumentError.new("The http stubbing library is not configured.") if adapters.empty?
HttpStubbingAdapters::MultiObjectProxy.for(*adapters)
end
@@ -96,8 +96,7 @@ def http_stubbing_adapter
def record_http_interaction(interaction)
return unless cassette = current_cassette
- return if http_stubbing_adapter.ignore_localhost? &&
- LOCALHOST_ALIASES.include?(URI.parse(interaction.uri).host)
+ return if VCR::Config.uri_should_be_ignored?(interaction.uri)
cassette.record_http_interaction(interaction)
end
@@ -132,6 +131,16 @@ def turned_on?
private
+ def adapter_for(lib)
+ case lib
+ when :fakeweb; HttpStubbingAdapters::FakeWeb
+ when :webmock; HttpStubbingAdapters::WebMock
+ when :typhoeus; HttpStubbingAdapters::Typhoeus
+ when :faraday; HttpStubbingAdapters::Faraday
+ else raise ArgumentError.new("#{lib.inspect} is not a supported HTTP stubbing library.")
+ end
+ end
+
def cassettes
@cassettes ||= []
end
View
6 lib/vcr/cassette.rb
@@ -104,10 +104,8 @@ def load_recorded_interactions
interactions = YAML.load(raw_yaml_content)
invoke_hook(:before_playback, interactions)
- if VCR.http_stubbing_adapter.ignore_localhost?
- interactions.reject! do |i|
- i.uri.is_a?(String) && VCR::LOCALHOST_ALIASES.include?(URI.parse(i.uri).host)
- end
+ interactions.reject! do |i|
+ i.request.uri.is_a?(String) && VCR::Config.uri_should_be_ignored?(i.request.uri)
end
recorded_interactions.replace(interactions)
View
25 lib/vcr/config.rb
@@ -30,13 +30,22 @@ def http_stubbing_libraries
@http_stubbing_libraries ||= []
end
- def ignore_localhost=(value)
- @ignore_localhost = value
- VCR.http_stubbing_adapter.ignore_localhost = value if http_stubbing_libraries.any?
+ def ignore_hosts(*hosts)
+ ignored_hosts.push(*hosts).uniq!
+ VCR.http_stubbing_adapter.ignored_hosts = ignored_hosts if http_stubbing_libraries.any?
+ end
+ alias ignore_host ignore_hosts
+
+ def ignored_hosts
+ @ignored_hosts ||= []
end
- def ignore_localhost?
- @ignore_localhost
+ def ignore_localhost=(value)
+ if value
+ ignore_hosts *VCR::LOCALHOST_ALIASES
+ else
+ ignored_hosts.reject! { |h| VCR::LOCALHOST_ALIASES.include?(h) }
+ end
end
def allow_http_connections_when_no_cassette=(value)
@@ -47,5 +56,11 @@ def allow_http_connections_when_no_cassette=(value)
def allow_http_connections_when_no_cassette?
!!@allow_http_connections_when_no_cassette
end
+
+ def uri_should_be_ignored?(uri)
+ uri = URI.parse(uri) unless uri.respond_to?(:host)
+ ignored_hosts.include?(uri.host)
+ end
end
end
+
View
41 lib/vcr/deprecations.rb
@@ -1,22 +1,33 @@
module VCR
- module Config
- class << self
- def http_stubbing_library
- warn "WARNING: `VCR::Config.http_stubbing_library` is deprecated. Use `VCR::Config.http_stubbing_libraries` instead."
- @http_stubbing_libraries && @http_stubbing_libraries.first
+ module HttpStubbingAdapters
+ module Common
+ def ignore_localhost?
+ VCR::Config.ignore_localhost?
end
+ end
+ end
- def http_stubbing_library=(library)
- warn "WARNING: `VCR::Config.http_stubbing_library = #{library.inspect}` is deprecated. Use `VCR::Config.stub_with #{library.inspect}` instead."
- stub_with library
- end
+ module Config
+ def http_stubbing_library
+ warn "WARNING: `VCR::Config.http_stubbing_library` is deprecated. Use `VCR::Config.http_stubbing_libraries` instead."
+ @http_stubbing_libraries && @http_stubbing_libraries.first
+ end
+
+ def http_stubbing_library=(library)
+ warn "WARNING: `VCR::Config.http_stubbing_library = #{library.inspect}` is deprecated. Use `VCR::Config.stub_with #{library.inspect}` instead."
+ stub_with library
+ end
+
+ def ignore_localhost?
+ warn "WARNING: `VCR::Config.ignore_localhost?` is deprecated. Check the list of ignored hosts using `VCR::Config.ignored_hosts` instead."
+ (VCR::LOCALHOST_ALIASES - ignored_hosts).empty?
end
end
class Cassette
def allow_real_http_requests_to?(uri)
warn "WARNING: VCR::Cassette#allow_real_http_requests_to? is deprecated and should no longer be used."
- VCR.http_stubbing_adapter.ignore_localhost? && VCR::LOCALHOST_ALIASES.include?(uri.host)
+ VCR::Config.uri_should_be_ignored?(uri.to_s)
end
private
@@ -24,8 +35,9 @@ def allow_real_http_requests_to?(uri)
def deprecate_old_cassette_options(options)
message = "VCR's :allow_real_http cassette option is deprecated. Instead, use the ignore_localhost configuration option."
if options[:allow_real_http] == :localhost
- @original_ignore_localhost = VCR.http_stubbing_adapter.ignore_localhost?
- VCR.http_stubbing_adapter.ignore_localhost = true
+ @original_ignored_hosts = VCR::Config.ignored_hosts.dup
+ VCR::Config.ignored_hosts.clear
+ VCR::Config.ignore_hosts *VCR::LOCALHOST_ALIASES
Kernel.warn "WARNING: #{message}"
elsif options[:allow_real_http]
raise ArgumentError.new(message)
@@ -33,8 +45,9 @@ def deprecate_old_cassette_options(options)
end
def restore_ignore_localhost_for_deprecation
- if defined?(@original_ignore_localhost)
- VCR.http_stubbing_adapter.ignore_localhost = @original_ignore_localhost
+ if defined?(@original_ignored_hosts)
+ VCR::Config.ignored_hosts.clear
+ VCR::Config.ignore_hosts *@original_ignored_hosts
end
end
end
View
23 lib/vcr/http_stubbing_adapters/fakeweb.rb
@@ -8,7 +8,6 @@ module FakeWeb
extend self
UNSUPPORTED_REQUEST_MATCH_ATTRIBUTES = [:body, :headers]
- LOCALHOST_REGEX = %r|\Ahttps?://((\w+:)?\w+@)?(#{VCR::LOCALHOST_ALIASES.map { |a| Regexp.escape(a) }.join('|')})(:\d+)?/|i
MINIMUM_VERSION = '1.3.0'
MAXIMUM_VERSION = '1.3'
@@ -22,15 +21,11 @@ def http_connections_allowed?
!!::FakeWeb.allow_net_connect?("http://some.url/besides/localhost")
end
- def ignore_localhost=(value)
- @ignore_localhost = value
+ def ignored_hosts=(hosts)
+ @ignored_hosts = hosts
update_fakeweb_allow_net_connect
end
- def ignore_localhost?
- !!@ignore_localhost
- end
-
def stub_requests(http_interactions, match_attributes)
validate_match_attributes(match_attributes)
@@ -62,6 +57,10 @@ def request_uri(net_http, request)
private
+ def ignored_hosts
+ @ignored_hosts ||= []
+ end
+
def version
::FakeWeb::VERSION
end
@@ -69,8 +68,8 @@ def version
def update_fakeweb_allow_net_connect
::FakeWeb.allow_net_connect = if @http_connections_allowed
true
- elsif @ignore_localhost
- LOCALHOST_REGEX
+ elsif ignored_hosts.any?
+ VCR::Regexes.url_regex_for_hosts(ignored_hosts)
else
false
end
@@ -93,6 +92,12 @@ def validate_match_attributes(match_attributes)
raise UnsupportedRequestMatchAttributeError.new("FakeWeb does not support matching requests on #{invalid_attributes.join(' or ')}")
end
end
+
+ def self.const_missing(const)
+ return super unless const == :LOCALHOST_REGEX
+ warn "WARNING: `VCR::HttpStubbingAdapters::FakeWeb::LOCALHOST_REGEX` is deprecated."
+ VCR::Regexes.url_regex_for_hosts(VCR::LOCALHOST_ALIASES)
+ end
end
end
end
View
15 lib/vcr/http_stubbing_adapters/faraday.rb
@@ -9,14 +9,19 @@ module Faraday
MINIMUM_VERSION = '0.5.3'
MAXIMUM_VERSION = '0.5'
- attr_writer :http_connections_allowed, :ignore_localhost
+ attr_writer :http_connections_allowed
def http_connections_allowed?
!!@http_connections_allowed
end
- def ignore_localhost?
- !!@ignore_localhost
+ def ignored_hosts=(hosts)
+ @ignored_hosts = hosts
+ end
+
+ def uri_should_be_ignored?(uri)
+ uri = URI.parse(uri) unless uri.respond_to?(:host)
+ ignored_hosts.include?(uri.host)
end
def stub_requests(http_interactions, match_attributes)
@@ -52,6 +57,10 @@ def version
::Faraday::VERSION
end
+ def ignored_hosts
+ @ignored_hosts ||= []
+ end
+
def checkpoints
@checkpoints ||= {}
end
View
10 lib/vcr/http_stubbing_adapters/typhoeus.rb
@@ -6,7 +6,7 @@ module Typhoeus
include VCR::HttpStubbingAdapters::Common
extend self
- MINIMUM_VERSION = '0.2.0'
+ MINIMUM_VERSION = '0.2.1'
MAXIMUM_VERSION = '0.2'
def http_connections_allowed=(value)
@@ -17,12 +17,8 @@ def http_connections_allowed?
!!::Typhoeus::Hydra.allow_net_connect?
end
- def ignore_localhost=(value)
- ::Typhoeus::Hydra.ignore_localhost = value
- end
-
- def ignore_localhost?
- !!::Typhoeus::Hydra.ignore_localhost?
+ def ignored_hosts=(hosts)
+ ::Typhoeus::Hydra.ignore_hosts = hosts
end
def stub_requests(http_interactions, match_attributes)
View
24 lib/vcr/http_stubbing_adapters/webmock.rb
@@ -10,19 +10,17 @@ module WebMock
MAXIMUM_VERSION = '1.6'
def http_connections_allowed=(value)
- ::WebMock::Config.instance.allow_net_connect = value
+ @http_connections_allowed = value
+ update_webmock_allow_net_connect
end
def http_connections_allowed?
!!::WebMock::Config.instance.allow_net_connect
end
- def ignore_localhost=(value)
- ::WebMock::Config.instance.allow_localhost = value
- end
-
- def ignore_localhost?
- !!::WebMock::Config.instance.allow_localhost
+ def ignored_hosts=(hosts)
+ @ignored_hosts = hosts
+ update_webmock_allow_net_connect
end
def stub_requests(http_interactions, match_attributes)
@@ -50,6 +48,18 @@ def version
::WebMock.version
end
+ def ignored_hosts
+ @ignored_hosts ||= []
+ end
+
+ def update_webmock_allow_net_connect
+ if @http_connections_allowed
+ ::WebMock.allow_net_connect!
+ else
+ ::WebMock.disable_net_connect!(:allow => ignored_hosts)
+ end
+ end
+
def request_signature_hash(request_matcher)
signature = {}
signature[:body] = request_matcher.body if request_matcher.match_requests_on?(:body)
View
2  lib/vcr/middleware/faraday.rb
@@ -13,7 +13,7 @@ def call(env)
request = request_for(env)
request_matcher = request.matcher(cassette.match_requests_on)
- if VCR::HttpStubbingAdapters::Faraday.ignore_localhost? && VCR::LOCALHOST_ALIASES.include?(URI.parse(request.uri).host)
+ if VCR::HttpStubbingAdapters::Faraday.uri_should_be_ignored?(request.uri)
@app.call(env)
elsif response = VCR::HttpStubbingAdapters::Faraday.stubbed_response_for(request_matcher)
env.update(
View
20 lib/vcr/request_matcher.rb
@@ -20,21 +20,21 @@ def match_attributes=(attributes)
# for two sets of the same elements unless they are ordered
# the same, so we sort the attributes here.
attributes = attributes.sort { |a, b| a.to_s <=> b.to_s }
- @match_attributes = Set.new(attributes)
+ @match_attributes = set(attributes)
end
def uri
return request.uri unless request.uri.is_a?(String)
uri_matchers = match_attributes.to_a & [:uri, :host, :path]
- case Set.new(uri_matchers)
- when Set.new then /.*/
- when Set.new([:uri]) then request.uri
- when Set.new([:host]) then %r{\Ahttps?://((\w+:)?\w+@)?#{Regexp.escape(URI(request.uri).host)}(:\d+)?/}i
- when Set.new([:path]) then %r{\Ahttps?://[^/]+#{Regexp.escape(URI(request.uri).path)}/?(\?.*)?\z}i
- when Set.new([:host, :path])
+ case set(uri_matchers)
+ when set then /.*/
+ when set(:uri) then request.uri
+ when set(:host) then VCR::Regexes.url_regex_for_hosts([URI(request.uri).host])
+ when set(:path) then VCR::Regexes.url_regex_for_path(URI(request.uri).path)
+ when set(:host, :path)
uri = URI(request.uri)
- %r{\Ahttps?://((\w+:)?\w+@)?#{Regexp.escape(uri.host)}(:\d+)?#{Regexp.escape(uri.path)}/?(\?.*)?\z}i
+ VCR::Regexes.url_regex_for_host_and_path(uri.host, uri.path)
else raise ArgumentError.new("match_attributes cannot include #{uri_matchers.join(' and ')}")
end
end
@@ -74,6 +74,10 @@ def hash
private
+ def set(*elements)
+ Set.new(elements.flatten)
+ end
+
def sorted_header_array
header_hash = headers
return header_hash unless header_hash.is_a?(Hash)
View
169 lib/vcr/structs.rb
@@ -1,169 +0,0 @@
-require 'forwardable'
-
-module VCR
- module BodyNormalizer
- def initialize(*args)
- super
- normalize_body
- end
-
- private
-
- def normalize_body
- # Ensure that the body is a raw string, in case the string instance
- # has been subclassed or extended with additional instance variables
- # or attributes, so that it is serialized to YAML as a raw string.
- # This is needed for rest-client. See this ticket for more info:
- # http://github.com/myronmarston/vcr/issues/4
- self.body = case body
- when nil, ''; nil
- else String.new(body)
- end
- end
- end
-
- module HeaderNormalizer
- # These headers get added by the various HTTP clients automatically,
- # and we don't care about them. We store the headers for the purposes
- # of request matching, and we only care to match on headers users
- # explicitly set.
- HEADERS_TO_SKIP = {
- 'connection' => %w[ close Keep-Alive ],
- 'accept' => %w[ */* ],
- 'expect' => [''],
- 'user-agent' => ["Typhoeus - http://github.com/pauldix/typhoeus/tree/master", 'Ruby']
- }
-
- def initialize(*args)
- super
- normalize_headers
- end
-
- private
-
- def important_header_values(k, values)
- skip_values = HEADERS_TO_SKIP[k] || []
- values - skip_values
- end
-
- def normalize_headers
- new_headers = {}
-
- headers.each do |k, v|
- k = k.downcase
-
- val_array = case v
- when Array then v
- when nil then []
- else [v]
- end
-
- important_vals = important_header_values(k, val_array)
- next unless important_vals.size > 0
-
- new_headers[k] = important_vals
- end if headers
-
- self.headers = new_headers.empty? ? nil : new_headers
- end
- end
-
- module URINormalizer
- DEFAULT_PORTS = {
- 'http' => 80,
- 'https' => 443
- }
-
- def initialize(*args)
- super
- normalize_uri
- end
-
- private
-
- def normalize_uri
- u = begin
- URI.parse(uri)
- rescue URI::InvalidURIError
- return
- end
-
- u.port ||= DEFAULT_PORTS[u.scheme]
-
- # URI#to_s only includes the port if it's not the default
- # but we want to always include it (since FakeWeb/WebMock
- # urls have always included it). We force it to be included
- # here by redefining default_port so that URI#to_s will include it.
- def u.default_port; nil; end
- self.uri = u.to_s
- end
- end
-
- module StatusMessageNormalizer
- def initialize(*args)
- super
- normalize_status_message
- end
-
- private
-
- def normalize_status_message
- self.message = message.strip if message
- self.message = nil if message == ''
- end
- end
-
- class Request < Struct.new(:method, :uri, :body, :headers)
- include HeaderNormalizer
- include URINormalizer
- include BodyNormalizer
-
- def self.from_net_http_request(net_http, request)
- new(
- request.method.downcase.to_sym,
- VCR.http_stubbing_adapter.request_uri(net_http, request),
- request.body,
- request.to_hash
- )
- end
-
- def matcher(match_attributes)
- RequestMatcher.new(self, match_attributes)
- end
- end
-
- class ResponseStatus < Struct.new(:code, :message)
- include StatusMessageNormalizer
-
- def self.from_net_http_response(response)
- new(response.code.to_i, response.message)
- end
- end
-
- class Response < Struct.new(:status, :headers, :body, :http_version)
- include HeaderNormalizer
- include BodyNormalizer
-
- def self.from_net_http_response(response)
- new(
- ResponseStatus.from_net_http_response(response),
- response.to_hash,
- response.body,
- response.http_version
- )
- end
- end
-
- class HTTPInteraction < Struct.new(:request, :response)
- extend ::Forwardable
- def_delegators :request, :uri, :method
-
- def ignore!
- @ignored = true
- end
-
- def ignored?
- @ignored
- end
- end
-end
View
16 lib/vcr/structs/http_interaction.rb
@@ -0,0 +1,16 @@
+require 'forwardable'
+
+module VCR
+ class HTTPInteraction < Struct.new(:request, :response)
+ extend ::Forwardable
+ def_delegators :request, :uri, :method
+
+ def ignore!
+ @ignored = true
+ end
+
+ def ignored?
+ @ignored
+ end
+ end
+end
View
24 lib/vcr/structs/normalizers/body.rb
@@ -0,0 +1,24 @@
+module VCR
+ module Normalizers
+ module Body
+ def initialize(*args)
+ super
+ normalize_body
+ end
+
+ private
+
+ def normalize_body
+ # Ensure that the body is a raw string, in case the string instance
+ # has been subclassed or extended with additional instance variables
+ # or attributes, so that it is serialized to YAML as a raw string.
+ # This is needed for rest-client. See this ticket for more info:
+ # http://github.com/myronmarston/vcr/issues/4
+ self.body = case body
+ when nil, ''; nil
+ else String.new(body)
+ end
+ end
+ end
+ end
+end
View
56 lib/vcr/structs/normalizers/header.rb
@@ -0,0 +1,56 @@
+module VCR
+ module Normalizers
+ module Header
+ # These headers get added by the various HTTP clients automatically,
+ # and we don't care about them. We store the headers for the purposes
+ # of request matching, and we only care to match on headers users
+ # explicitly set.
+ HEADERS_TO_SKIP = {
+ 'connection' => %w[ close Keep-Alive ],
+ 'accept' => %w[ */* ],
+ 'expect' => [''],
+ 'user-agent' => ["Typhoeus - http://github.com/dbalatero/typhoeus/tree/master", 'Ruby']
+ }
+
+ def initialize(*args)
+ super
+ normalize_headers
+ end
+
+ private
+
+ def important_header_values(k, values)
+ skip_values = HEADERS_TO_SKIP[k] || []
+ values - skip_values
+ end
+
+ def normalize_headers
+ new_headers = {}
+
+ headers.each do |k, v|
+ k = k.downcase
+
+ val_array = case v
+ when Array then v
+ when nil then []
+ else [v]
+ end
+
+ important_vals = important_header_values(k, val_array)
+ next unless important_vals.size > 0
+
+ # Ensure the values are raw strings.
+ # Apparently for Paperclip uploads to S3, headers
+ # get serialized with some extra stuff which leads
+ # to a seg fault. See this issue for more info:
+ # https://github.com/myronmarston/vcr/issues#issue/39
+ string_vals = important_vals.map { |v| String.new(v) }
+
+ new_headers[k] = string_vals
+ end if headers
+
+ self.headers = new_headers.empty? ? nil : new_headers
+ end
+ end
+ end
+end
View
17 lib/vcr/structs/normalizers/status_message.rb
@@ -0,0 +1,17 @@
+module VCR
+ module Normalizers
+ module StatusMessage
+ def initialize(*args)
+ super
+ normalize_status_message
+ end
+
+ private
+
+ def normalize_status_message
+ self.message = message.strip if message
+ self.message = nil if message == ''
+ end
+ end
+ end
+end
View
34 lib/vcr/structs/normalizers/uri.rb
@@ -0,0 +1,34 @@
+module VCR
+ module Normalizers
+ module URI
+ DEFAULT_PORTS = {
+ 'http' => 80,
+ 'https' => 443
+ }
+
+ def initialize(*args)
+ super
+ normalize_uri
+ end
+
+ private
+
+ def normalize_uri
+ u = begin
+ ::URI.parse(uri)
+ rescue ::URI::InvalidURIError
+ return
+ end
+
+ u.port ||= DEFAULT_PORTS[u.scheme]
+
+ # URI#to_s only includes the port if it's not the default
+ # but we want to always include it (since FakeWeb/WebMock
+ # urls have always included it). We force it to be included
+ # here by redefining default_port so that URI#to_s will include it.
+ def u.default_port; nil; end
+ self.uri = u.to_s
+ end
+ end
+ end
+end
View
20 lib/vcr/structs/request.rb
@@ -0,0 +1,20 @@
+module VCR
+ class Request < Struct.new(:method, :uri, :body, :headers)
+ include Normalizers::Header
+ include Normalizers::URI
+ include Normalizers::Body
+
+ def self.from_net_http_request(net_http, request)
+ new(
+ request.method.downcase.to_sym,
+ VCR.http_stubbing_adapter.request_uri(net_http, request),
+ request.body,
+ request.to_hash
+ )
+ end
+
+ def matcher(match_attributes)
+ RequestMatcher.new(self, match_attributes)
+ end
+ end
+end
View
16 lib/vcr/structs/response.rb
@@ -0,0 +1,16 @@
+module VCR
+ class Response < Struct.new(:status, :headers, :body, :http_version)
+ include Normalizers::Header
+ include Normalizers::Body
+
+ def self.from_net_http_response(response)
+ new(
+ ResponseStatus.from_net_http_response(response),
+ response.to_hash,
+ response.body,
+ response.http_version
+ )
+ end
+ end
+end
+
View
9 lib/vcr/structs/response_status.rb
@@ -0,0 +1,9 @@
+module VCR
+ class ResponseStatus < Struct.new(:code, :message)
+ include Normalizers::StatusMessage
+
+ def self.from_net_http_response(response)
+ new(response.code.to_i, response.message)
+ end
+ end
+end
View
37 lib/vcr/util/regexes.rb
@@ -0,0 +1,37 @@
+module VCR
+ module Regexes
+ extend self
+
+ PROTOCOL = '\Ahttps?://'
+ CREDENTIALS = '((\w+:)?\w+@)?'
+ PORT = '(:\d+)?'
+ THE_REST = '/?(\?.*)?\z'
+
+ @@url_host_regexes = Hash.new do |hash, hosts|
+ hash[hosts] = begin
+ host_regex = hosts.map { |h| Regexp.escape(h) }.join('|')
+ %r|#{PROTOCOL}#{CREDENTIALS}(#{host_regex})#{PORT}/|i
+ end
+ end
+
+ def url_regex_for_hosts(hosts)
+ @@url_host_regexes[hosts.sort]
+ end
+
+ @@url_path_regexes = Hash.new do |hash, path|
+ %r|#{PROTOCOL}[^/]+#{Regexp.escape(path)}#{THE_REST}|i
+ end
+
+ def url_regex_for_path(path)
+ @@url_path_regexes[path]
+ end
+
+ @@url_host_and_path_regexes = Hash.new do |hash, (host, path)|
+ %r|#{PROTOCOL}#{CREDENTIALS}#{Regexp.escape(host)}#{PORT}#{Regexp.escape(path)}#{THE_REST}|i
+ end
+
+ def url_regex_for_host_and_path(host, path)
+ @@url_host_and_path_regexes[[host, path]]
+ end
+ end
+end
View
21 lib/vcr/version.rb
@@ -3,12 +3,23 @@ module VCR
def version
@version ||= begin
- string = '1.5.0'
+ string = '1.6.0'
- def string.parts; VCR.version.split('.').map { |p| p.to_i }; end
- def string.major; parts[0]; end
- def string.minor; parts[1]; end
- def string.patch; parts[2]; end
+ def string.parts
+ split('.').map { |p| p.to_i }
+ end
+
+ def string.major
+ parts[0]
+ end
+
+ def string.minor
+ parts[1]
+ end
+
+ def string.patch
+ parts[2]
+ end
string
end
View
42 script/FullBuildRakeFile
@@ -1,19 +1,46 @@
# this is in a separate rakefile because our main one depends on the bundled gems
# already being installed. This must be able to run w/o bundled gems installed.
+def rake(command = "")
+ sh "rake #{command} FULL_BUILD=true"
+end
+
desc "Run a full build: install necessary gems with bundler, runs specs, run cukes"
-task :build => :ensure_bundler_installed do
- sh "bundle install"
- sh "rake"
+task :build => :bundle_install do
+ rake
+end
+
+desc "Install necessary gems with bundler and runs specs"
+task :spec => :bundle_install do
+ rake "spec"
+end
+
+desc "Install necessary gems with bundler and runs cukes"
+task :cucumber => :bundle_install do
+ rake "cucumber"
+end
+
+desc "Prints description of current ruby interpreter"
+task :print_ruby_description do
+ description = if defined?(RUBY_DESCRIPTION)
+ RUBY_DESCRIPTION
+ else
+ # RUBY_DESCRIPTION is undefined on 1.8.6
+ "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE} patchlevel #{RUBY_PATCHLEVEL}) [#{RUBY_PLATFORM}]"
+ end
+
+ puts
+ puts "=" * 80
+ puts "Using #{description}"
+ puts "=" * 80
+ puts
end
-desc "Install necessary gems with bundler, runs specs, run cukes"
-task :spec => :ensure_bundler_installed do
+task :bundle_install => :ensure_bundler_installed do
sh "bundle install"
- sh "rake spec"
end
-task :ensure_bundler_installed do
+task :ensure_bundler_installed => :print_ruby_description do
installed = begin
require 'rubygems'
require 'bundler'
@@ -26,3 +53,4 @@ task :ensure_bundler_installed do
sh "gem install bundler"
end
end
+
View
29 spec/spec_helper.rb
@@ -14,6 +14,25 @@
module VCR
SPEC_ROOT = File.dirname(__FILE__)
+
+ module Config
+ def reset!(stubbing_lib = :fakeweb)
+ self.default_cassette_options = { :record => :new_episodes }
+
+ if stubbing_lib
+ stub_with stubbing_lib
+ else
+ http_stubbing_libraries.clear
+ end
+
+ clear_hooks
+ @ignored_hosts = []
+
+ VCR.instance_eval do
+ instance_variables.each { |ivar| remove_instance_variable(ivar) }
+ end
+ end
+ end
end
RSpec.configure do |config|
@@ -29,9 +48,7 @@ module VCR
VCR.turn_on! unless VCR.turned_on?
VCR.eject_cassette while VCR.current_cassette
- VCR::Config.default_cassette_options = { :record => :new_episodes }
- VCR::Config.stub_with :fakeweb
- VCR::Config.clear_hooks
+ VCR::Config.reset!
WebMock.allow_net_connect!
WebMock.reset!
@@ -42,6 +59,12 @@ module VCR
VCR::HttpStubbingAdapters::Faraday.reset!
end
+ config.after(:each) do
+ VCR::HttpStubbingAdapters::Common.adapters.each do |a|
+ a.ignored_hosts = []
+ end
+ end
+
config.filter_run :focus => true
config.run_all_when_everything_filtered = true
View
23 spec/support/http_library_adapters.rb
@@ -340,7 +340,7 @@ def test_request_stubbed(method, url, expected)
end
[true, false].each do |http_allowed|
- context "when #http_connections_allowed is set to #{http_allowed}" do
+ context "when http_connections_allowed is set to #{http_allowed}" do
before(:each) { subject.http_connections_allowed = http_allowed }
it "returns #{http_allowed} for #http_connections_allowed?" do
@@ -350,25 +350,24 @@ def test_request_stubbed(method, url, expected)
test_real_http_request(http_allowed, *other)
unless http_allowed
- describe '.ignore_localhost =' do
- localhost_response = "Localhost response"
+ localhost_response = "Localhost response"
+
+ describe '.ignore_hosts' do
let(:record_mode) { :none }
- VCR::LOCALHOST_ALIASES.each do |localhost_alias|
- describe 'when set to true' do
- before(:each) { subject.ignore_localhost = true }
+ context 'when set to ["127.0.0.1", "localhost"]' do
+ before(:each) do
+ subject.ignored_hosts = ["127.0.0.1", "localhost"]
+ end
+ %w[ 127.0.0.1 localhost ].each do |localhost_alias|
it "allows requests to #{localhost_alias}" do
get_body_string(make_http_request(:get, "http://#{localhost_alias}:#{VCR::SinatraApp.port}/localhost_test")).should == localhost_response
end
end
- describe 'when set to false' do
- before(:each) { subject.ignore_localhost = false }
-
- it "does not allow requests to #{localhost_alias}" do
- expect { make_http_request(:get, "http://#{localhost_alias}:#{VCR::SinatraApp.port}/localhost_test") }.to raise_error(NET_CONNECT_NOT_ALLOWED_ERROR)
- end
+ it 'does not allow requests to 0.0.0.0' do
+ expect { make_http_request(:get, "http://0.0.0.0:#{VCR::SinatraApp.port}/localhost_test") }.to raise_error(NET_CONNECT_NOT_ALLOWED_ERROR)
end
end
end
View
18 spec/support/http_stubbing_adapter.rb
@@ -3,20 +3,6 @@
before(:each) { VCR.stub!(:http_stubbing_adapter).and_return(subject) }
subject { described_class }
- describe '.ignore_localhost?' do
- [true, false].each do |val|
- it "returns #{val} when ignore_localhost is set to #{val}" do
- subject.ignore_localhost = val
- subject.ignore_localhost?.should == val
- end
- end
-
- it "returns false when ignore_localhost is set to nil" do
- subject.ignore_localhost = nil
- subject.ignore_localhost?.should == false
- end
- end
-
describe '.set_http_connections_allowed_to_default' do
[true, false].each do |default|
context "when VCR::Config.allow_http_connections_when_no_cassette is #{default}" do
@@ -59,7 +45,7 @@ def adapter_enabled?(adapter)
end
if other.include?(:needs_net_http_extension)
- describe '#request_uri' do
+ describe '.request_uri' do
it 'returns the uri for the given http request' do
net_http = Net::HTTP.new('example.com', 80)
request = Net::HTTP::Get.new('/foo/bar')
@@ -74,7 +60,7 @@ def adapter_enabled?(adapter)
end
end
- describe '#request_stubbed? using specific match_attributes' do
+ describe '.request_stubbed? using specific match_attributes' do
let(:interactions) { YAML.load(File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', YAML_SERIALIZATION_VERSION, 'match_requests_on.yml'))) }
@supported_request_match_attributes = supported_request_match_attributes
View
84 spec/support/normalizers.rb
@@ -0,0 +1,84 @@
+require 'spec_helper'
+
+shared_examples_for "header normalization" do
+ let(:instance) do
+ with_headers('Some_Header' => 'value1', 'aNother' => ['a', 'b'], 'third' => [], 'fourth' => nil)
+ end
+
+ it 'normalizes the hash to lower case keys and arrays of values' do
+ instance.headers['some_header'].should == ['value1']
+ instance.headers['another'].should == ['a', 'b']
+ end
+
+ it 'removes empty headers' do
+ instance.headers.should_not have_key('third')
+ instance.headers.should_not have_key('fourth')
+ end
+
+ it 'filters out unimportant default values set by the HTTP library' do
+ instance = with_headers('accept' => ['*/*'], 'connection' => 'close', 'http-user' => ['foo'], 'expect' => ['', 'bar'])
+ instance.headers.should == { 'http-user' => ['foo'], 'expect' => ['bar'] }
+ end
+
+ it 'sets empty hash header to nil' do
+ with_headers({}).headers.should be_nil
+ end
+
+ it 'ensures header keys are serialized to yaml as raw strings' do
+ key = 'my-key'
+ key.instance_variable_set(:@foo, 7)
+ instance = with_headers(key => ['value1'])
+ instance.headers.to_yaml.should == { 'my-key' => ['value1'] }.to_yaml
+ end
+
+ it 'ensures header values are serialized to yaml as raw strings' do
+ value = 'my-value'
+ value.instance_variable_set(:@foo, 7)
+ instance = with_headers('my-key' => [value])
+ instance.headers.to_yaml.should == { 'my-key' => ['my-value'] }.to_yaml
+ end
+end
+
+shared_examples_for "body normalization" do
+ it 'sets empty string to nil' do
+ instance('').body.should be_nil
+ end
+
+ it "ensures the body is serialized to yaml as a raw string" do
+ body = "My String"
+ body.instance_variable_set(:@foo, 7)
+ instance(body).body.to_yaml.should == "My String".to_yaml
+ end
+end
+
+shared_examples_for 'uri normalization' do
+ it 'adds port 80 to an http URI that lacks a port' do
+ instance('http://example.com/foo').uri.should == 'http://example.com:80/foo'
+ end
+
+ it 'keeps the existing port for an http URI' do
+ instance('http://example.com:8000/foo').uri.should == 'http://example.com:8000/foo'
+ end
+
+ it 'adds port 443 to an https URI that lacks a port' do
+ instance('https://example.com/foo').uri.should == 'https://example.com:443/foo'
+ end
+
+ it 'keeps the existing port for an https URI' do
+ instance('https://example.com:8000/foo').uri.should == 'https://example.com:8000/foo'
+ end
+end
+
+shared_examples_for 'status message normalization' do
+ it 'chomps leading and trailing spaces on the status message' do
+ instance(' OK ').message.should == 'OK'
+ end
+
+ it 'sets status message to nil when it is the empty string' do
+ instance('').message.should be_nil
+ end
+
+ it 'sets status message to nil when it is a blank string' do
+ instance(' ').message.should be_nil
+ end
+end
View
2  spec/support/version_checker.rb
@@ -1,7 +1,7 @@
shared_examples_for "version checking" do |options|
library = described_class.library_name
- describe '#check_version!' do
+ describe '.check_version!' do
options[:valid].each do |version|
it "does nothing when #{library}'s version is #{version}" do
stub_version(version)
View
18 spec/vcr/cassette_spec.rb
@@ -49,7 +49,7 @@
end
end
- describe 'on creation' do
+ describe '.new' do
it 'raises an error with a helpful message when loading an old unsupported cassette' do
VCR::Config.cassette_library_dir = "#{VCR::SPEC_ROOT}/fixtures/#{YAML_SERIALIZATION_VERSION}"
expect { VCR::Cassette.new('0_3_1_cassette') }.to raise_error(/The VCR cassette 0_3_1_cassette.yml uses an old format that is now deprecated/)
@@ -181,16 +181,14 @@
VCR::Cassette.new(:name, :record => record_mode)
end
- [true, false].each do |ignore_localhost|
- expected_uri_hosts = %w(example.com)
- expected_uri_hosts += VCR::LOCALHOST_ALIASES unless ignore_localhost
-
- it "#{ ignore_localhost ? 'does not load' : 'loads' } localhost interactions from the cassette file when http_stubbing_adapter.ignore_localhost is set to #{ignore_localhost}" do
- VCR.http_stubbing_adapter.stub!(:ignore_localhost?).and_return(ignore_localhost)
- VCR::Config.cassette_library_dir = "#{VCR::SPEC_ROOT}/fixtures/#{YAML_SERIALIZATION_VERSION}/cassette_spec"
- cassette = VCR::Cassette.new('with_localhost_requests', :record => record_mode)
- cassette.recorded_interactions.map { |i| URI.parse(i.uri).host }.should =~ expected_uri_hosts
+ it 'does not load ignored interactions' do
+ VCR::Config.stub(:uri_should_be_ignored?) do |uri|
+ uri.to_s !~ /example\.com/
end
+
+ VCR::Config.cassette_library_dir = "#{VCR::SPEC_ROOT}/fixtures/#{YAML_SERIALIZATION_VERSION}/cassette_spec"
+ cassette = VCR::Cassette.new('with_localhost_requests', :record => record_mode)
+ cassette.recorded_interactions.map { |i| URI.parse(i.uri).host }.should == %w[example.com]
end
it "loads the recorded interactions from the library yml file" do
View
80 spec/vcr/config_spec.rb
@@ -6,7 +6,7 @@ def stub_no_http_stubbing_adapter
VCR::Config.stub(:http_stubbing_libraries).and_return([])
end
- describe '#cassette_library_dir=' do
+ describe '.cassette_library_dir=' do
temp_dir(File.expand_path(File.dirname(__FILE__) + '/fixtures/config_spec'))
it 'creates the directory if it does not exist' do
@@ -18,7 +18,7 @@ def stub_no_http_stubbing_adapter
end
end
- describe '#default_cassette_options' do
+ describe '.default_cassette_options' do
it 'has a hash with some defaults even if it is set to nil' do
VCR::Config.default_cassette_options = nil
VCR::Config.default_cassette_options.should == { :match_requests_on => VCR::RequestMatcher::DEFAULT_MATCH_ATTRIBUTES }
@@ -47,26 +47,52 @@ def stub_no_http_stubbing_adapter
end
end
- describe '#ignore_localhost' do
- it 'sets VCR.http_stubbing_adapter.ignore_localhost?' do
- [true, false].each do |val|
- VCR.http_stubbing_adapter.ignore_localhost = !val
- expect {
- VCR::Config.ignore_localhost = val
- }.to change { VCR.http_stubbing_adapter.ignore_localhost? }.from(!val).to(val)
- end
+ describe '.ignore_hosts' do
+ let(:stubbing_adapter) { VCR::HttpStubbingAdapters::FakeWeb }
+ before(:each) do
+ stubbing_adapter.send(:ignored_hosts).should be_empty
+ VCR.stub(:http_stubbing_adapter => stubbing_adapter)
+ VCR::Config.ignored_hosts.should be_empty
end
- it 'stores the value even when VCR.http_stubbing_adapter is not set' do
- stub_no_http_stubbing_adapter
- [true, false].each do |val|
- VCR::Config.ignore_localhost = val
- VCR::Config.ignore_localhost?.should == val
- end
+ it 'adds the given hosts to the ignored_hosts list' do
+ VCR::Config.ignore_hosts 'example.com', 'example.net'
+ VCR::Config.ignored_hosts.should == %w[ example.com example.net ]
+ VCR::Config.ignore_host 'example.org'
+ VCR::Config.ignored_hosts.should == %w[ example.com example.net example.org ]
+ end
+
+ it 'removes duplicate hosts' do
+ VCR::Config.ignore_host 'example.com'
+ VCR::Config.ignore_host 'example.com'
+ VCR::Config.ignored_hosts.should == ['example.com']
+ end
+
+ it "updates the http_stubbing_adapter's ignored_hosts list" do
+ VCR::Config.ignore_hosts 'example.com', 'example.org'
+ stubbing_adapter.send(:ignored_hosts).should == %w[ example.com example.org ]
+ end
+ end
+
+ describe '.ignore_localhost=' do
+ before(:each) do
+ VCR::Config.ignored_hosts.should be_empty
+ end
+
+ it 'adds the localhost aliases to the ignored_hosts list when set to true' do
+ VCR::Config.ignore_host 'example.com'
+ VCR::Config.ignore_localhost = true
+ VCR::Config.ignored_hosts.should == ['example.com', *VCR::LOCALHOST_ALIASES]
+ end
+
+ it 'removes the localhost aliases from the ignored_hosts list when set to false' do
+ VCR::Config.ignore_host 'example.com', *VCR::LOCALHOST_ALIASES
+ VCR::Config.ignore_localhost = false
+ VCR::Config.ignored_hosts.should == ['example.com']
end
end
- describe '#allow_http_connections_when_no_cassette=' do
+ describe '.allow_http_connections_when_no_cassette=' do
[true, false].each do |val|
it "sets the allow_http_connections_when_no_cassette to #{val} when set to #{val}" do
VCR::Config.allow_http_connections_when_no_cassette = val
@@ -85,4 +111,24 @@ def stub_no_http_stubbing_adapter
VCR::Config.allow_http_connections_when_no_cassette = true
end
end
+
+ describe '.uri_should_be_ignored?' do
+ before(:each) { described_class.ignore_hosts 'example.com' }
+
+ it 'returns true for a string URI with a host in the ignore_hosts list' do
+ described_class.uri_should_be_ignored?("http://example.com/").should be_true
+ end
+
+ it 'returns true for a URI instance with a host in the ignore_hosts list' do
+ described_class.uri_should_be_ignored?(URI("http://example.com/")).should be_true
+ end
+
+ it 'returns false for a string URI with a host in the ignore_hosts list' do
+ described_class.uri_should_be_ignored?("http://example.net/").should be_false
+ end
+
+ it 'returns false for a URI instance with a host in the ignore_hosts list' do
+ described_class.uri_should_be_ignored?(URI("http://example.net/")).should be_false
+ end
+ end
end
View
107 spec/vcr/deprecations_spec.rb
@@ -1,8 +1,58 @@
require 'spec_helper'
+shared_examples_for '.ignore_localhost? deprecation' do
+ it 'returns false when no hosts are ignored' do
+ VCR::Config.ignored_hosts.should be_empty
+ described_class.ignore_localhost?.should be_false
+ end
+
+ it 'returns false when only non-local hosts are ignored' do
+ VCR::Config.ignore_hosts 'example.com'
+ described_class.ignore_localhost?.should be_false
+ end
+
+ it 'returns false when only some localhost aliases are ignored' do
+ aliases = VCR::LOCALHOST_ALIASES.dup
+ aliases.pop
+ VCR::Config.ignore_hosts *aliases
+ described_class.ignore_localhost?.should be_false
+ end
+
+ it 'returns true when all localhost aliases are ignored, even if some other hosts are ignored, too' do
+ VCR::Config.ignore_hosts 'example.com', *VCR::LOCALHOST_ALIASES
+ described_class.ignore_localhost?.should be_true
+ end
+
+ it 'prints a warning: WARNING: `VCR::Config.ignore_localhost?` is deprecated. Check the list of ignored hosts using `VCR::Config.ignored_hosts` instead.' do
+ VCR::Config.should_receive(:warn).with(/Check the list of ignored hosts using `VCR::Config.ignored_hosts` instead/)
+ described_class.ignore_localhost?
+ end
+end
+
describe 'Deprecations' do
disable_warnings
+ VCR::HttpStubbingAdapters::Common.adapters.each do |adapter|
+ describe adapter do
+ it_behaves_like '.ignore_localhost? deprecation'
+ end
+ end
+
+ describe VCR::HttpStubbingAdapters::FakeWeb do
+ describe 'LOCALHOST_REGEX constant' do
+ subject { described_class::LOCALHOST_REGEX }
+
+ it 'refers to the expected regex' do
+ should == %r|\Ahttps?://((\w+:)?\w+@)?(#{VCR::LOCALHOST_ALIASES.sort.map { |a| Regexp.escape(a) }.join('|')})(:\d+)?/|i
+ end
+
+ it 'prints a warning: WARNING: `VCR::HttpStubbingAdapters::FakeWeb::LOCALHOST_REGEX` is deprecated.' do
+ described_class.should_receive(:warn).with("WARNING: `VCR::HttpStubbingAdapters::FakeWeb::LOCALHOST_REGEX` is deprecated.")
+ subject
+ end
+ end
+ end
+
describe VCR::Config do
describe '.http_stubbing_library' do
before(:each) { described_class.stub_with :webmock, :typhoeus }
@@ -28,6 +78,8 @@
described_class.http_stubbing_library = :webmock
end
end
+
+ it_behaves_like '.ignore_localhost? deprecation'
end
describe VCR::Cassette do
@@ -43,35 +95,42 @@
end
[true, false].each do |orig_ignore_localhost|
- context "when the http_stubbing_adapter's ignore_localhost is set to #{orig_ignore_localhost}" do
- before(:each) { VCR.http_stubbing_adapter.ignore_localhost = orig_ignore_localhost }
+ orig_ignored_hosts = if orig_ignore_localhost
+ VCR::LOCALHOST_ALIASES
+ else
+ []
+ end
- context 'when the :allow_real_http option is set to :localhost' do
- subject { VCR::Cassette.new('cassette name', :allow_real_http => :localhost) }
+ context "when the ignored_hosts list is set to #{orig_ignored_hosts.inspect} and the :allow_real_http option is set to :localhost" do
+ before(:each) do
+ VCR::Config.ignored_hosts.clear
+ VCR::Config.ignore_hosts *orig_ignored_hosts
+ end
- it "sets the http_stubbing_adapter's ignore_localhost attribute to true" do
- subject
- VCR.http_stubbing_adapter.ignore_localhost?.should == true
- end
+ subject { VCR::Cassette.new('cassette name', :allow_real_http => :localhost) }
- it "prints a warning: VCR's :allow_real_http cassette option is deprecated. Instead, use the ignore_localhost configuration option." do
- Kernel.should_receive(:warn).with("WARNING: VCR's :allow_real_http cassette option is deprecated. Instead, use the ignore_localhost configuration option.")
- subject
- end
+ it "sets the ignored_hosts list to the list of localhost aliases" do
+ subject
+ VCR::Config.ignored_hosts.should == VCR::LOCALHOST_ALIASES
+ end
- it "reverts ignore_localhost when the cassette is ejected" do
- subject.eject
- VCR.http_stubbing_adapter.ignore_localhost?.should == orig_ignore_localhost
- end
+ it "prints a warning: VCR's :allow_real_http cassette option is deprecated. Instead, use the ignore_localhost configuration option." do
+ Kernel.should_receive(:warn).with("WARNING: VCR's :allow_real_http cassette option is deprecated. Instead, use the ignore_localhost configuration option.")
+ subject
+ end
+
+ it "reverts ignore_hosts when the cassette is ejected" do
+ subject.eject
+ VCR::Config.ignored_hosts.should == orig_ignored_hosts
+ end
- {
- 'http://localhost' => true,
- 'http://127.0.0.1' => true,
- 'http://example.com' => false
- }.each do |url, expected_value|
- it "returns #{expected_value} for #allow_real_http_requests_to? when it is given #{url}" do
- subject.allow_real_http_requests_to?(URI.parse(url)).should == expected_value
- end
+ {
+ 'http://localhost' => true,
+ 'http://127.0.0.1' => true,
+ 'http://example.com' => false
+ }.each do |url, expected_value|
+ it "returns #{expected_value} for #allow_real_http_requests_to? when it is given #{url}" do
+ subject.allow_real_http_requests_to?(URI.parse(url)).should == expected_value
end
end
end
View
2  spec/vcr/http_stubbing_adapters/multi_object_proxy_spec.rb
@@ -20,7 +20,7 @@ module HttpStubbingAdapters
inst_methods.should_not include(:send, :object_id, :__id__)
end
- describe '#proxies_objects' do
+ describe '#proxied_objects' do
it 'returns the proxied objects' do
subject.proxied_objects.should == [mock1, mock2]
end
View
4 spec/vcr/http_stubbing_adapters/typhoeus_spec.rb
@@ -11,8 +11,8 @@
it_behaves_like 'an http stubbing adapter', ['typhoeus'], [:method, :uri, :host, :path, :body, :headers]
it_performs('version checking',
- :valid => %w[ 0.2.0 0.2.99 ],
- :too_low => %w[ 0.1.0 0.1.31 ],
+ :valid => %w[ 0.2.1 0.2.99 ],
+ :too_low => %w[ 0.1.0 0.1.31 0.2.0 ],
:too_high => %w[ 0.3.0 1.0.0 ]
) do
disable_warnings
View
2  spec/vcr/middleware/faraday_spec.rb