Skip to content

Commit

Permalink
Add :serialize_with cassette option.
Browse files Browse the repository at this point in the history
  • Loading branch information
myronmarston committed Oct 28, 2011
1 parent 1a63361 commit d54d572
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 10 deletions.
91 changes: 87 additions & 4 deletions features/cassettes/format.feature
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Feature: Cassette format

VCR Cassettes are YAML files that contain all of the information
VCR Cassettes are files that contain all of the information
about the requests and corresponding responses in a
human-readable/editable format. A cassette contains an array
of HTTP interactions, each of which has the following:
Expand All @@ -18,8 +18,23 @@ Feature: Cassette format
- body
- http version

Scenario Outline: Request/Response data is saved to disk as YAML
Given a file named "cassette_format.rb" with:
By default, VCR uses YAML to serialize this data. You can configure
VCR to use a different serializer, either on a cassette-by-cassette
basis, or as a default for all cassettes if you use the `default_cassette_options`.

VCR supports the following serializers out of the box:

* `:yaml`--Uses ruby's standard library YAML. This may use psych or syck,
depending on your ruby installation.
* `:syck`--Uses syck (the ruby 1.8 YAML engine). This is useful when using
VCR on a project that must run in environments where psych is not available
(such as on ruby 1.8), to ensure that syck is always used.
* `:psych`--Uses psych (the new ruby 1.9 YAML engine). This is useful when
you want to ensure that psych is always used.
* `:json`--Uses [multi_json]() to serialize the cassette data as JSON.

Scenario Outline: Request/Response data is saved to disk as YAML by default
Given a file named "cassette_yaml.rb" with:
"""ruby
include_http_adapter_for("<http_lib>")
Expand All @@ -39,7 +54,7 @@ Feature: Cassette format
make_http_request(:get, "http://localhost:7777/bar")
end
"""
When I run `ruby cassette_format.rb 'Hello'`
When I run `ruby cassette_yaml.rb 'Hello'`
Then the file "cassettes/example.yml" should contain YAML like:
"""
---
Expand Down Expand Up @@ -90,3 +105,71 @@ Feature: Cassette format
| c.hook_into :excon | excon |
| | faraday (w/ net_http) |

Scenario: Request/Response data can be saved as JSON
Given a file named "cassette_json.rb" with:
"""ruby
include_http_adapter_for("net/http")
start_sinatra_app(:port => 7777) do
get('/:path') { ARGV[0] + ' ' + params[:path] }
end
require 'vcr'
VCR.configure do |c|
c.hook_into :webmock
c.cassette_library_dir = 'cassettes'
end
VCR.use_cassette('example', :serialize_with => :json) do
make_http_request(:get, "http://localhost:7777/foo")
make_http_request(:get, "http://localhost:7777/bar")
end
"""
When I run `ruby cassette_json.rb 'Hello'`
Then the file "cassettes/example.json" should contain JSON like:
"""json
[
{
"response": {
"body": "Hello foo",
"http_version": null,
"status": { "code": 200, "message": "OK" },
"headers": {
"Date": [ "Thu, 27 Oct 2011 06:16:31 GMT" ],
"Content-Type": [ "text/html;charset=utf-8" ],
"Content-Length": [ "9" ],
"Server": [ "WEBrick/1.3.1 (Ruby/1.8.7/2011-06-30)" ],
"Connection": [ "Keep-Alive" ]
}
},
"request": {
"uri": "http://localhost:7777/foo",
"body": "",
"method": "get",
"headers": { }
}
},
{
"response": {
"body": "Hello bar",
"http_version": null,
"status": { "code": 200, "message": "OK" },
"headers": {
"Date": [ "Thu, 27 Oct 2011 06:16:31 GMT" ],
"Content-Type": [ "text/html;charset=utf-8" ],
"Content-Length": [ "9" ],
"Server": [ "WEBrick/1.3.1 (Ruby/1.8.7/2011-06-30)" ],
"Connection": [ "Keep-Alive" ]
}
},
"request": {
"uri": "http://localhost:7777/bar",
"body": "",
"method": "get",
"headers": { }
}
}
]
"""

10 changes: 10 additions & 0 deletions features/step_definitions/cli_steps.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'vcr'
require 'multi_json'

module VCRHelpers

Expand Down Expand Up @@ -111,6 +112,15 @@ def modify_file(file_name, orig_text, new_text)
normalize_cassette_structs(actual_content).should == normalize_cassette_structs(expected_content)
end

Then /^the file "([^"]*)" should contain JSON like:$/ do |file_name, expected_content|
actual_content = in_current_dir { File.read(file_name) }
actual = MultiJson.decode(actual_content)
expected = MultiJson.decode(expected_content)
actual.map! { |i| normalize_http_interaction(i) }
expected.map! { |i| normalize_http_interaction(i) }
actual.should == expected
end

Then /^the file "([^"]*)" should contain each of these:$/ do |file_name, table|
table.raw.flatten.each do |string|
check_file_content(file_name, string, true)
Expand Down
10 changes: 6 additions & 4 deletions lib/vcr/cassette.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ def initialize(name, options = {})
options = VCR.configuration.default_cassette_options.merge(options)
invalid_options = options.keys - [
:record, :erb, :match_requests_on, :re_record_interval, :tag,
:update_content_length_header, :allow_playback_repeats, :exclusive
:update_content_length_header, :allow_playback_repeats, :exclusive,
:serialize_with
]

if invalid_options.size > 0
Expand All @@ -29,11 +30,11 @@ def initialize(name, options = {})
@match_requests_on = options[:match_requests_on]
@re_record_interval = options[:re_record_interval]
@tag = options[:tag]
@record_mode = :all if should_re_record?
@update_content_length_header = options[:update_content_length_header]
@allow_playback_repeats = options[:allow_playback_repeats]
@exclusive = options[:exclusive]
@serializer = VCR.cassette_serializers[:yaml]
@serializer = VCR.cassette_serializers[options[:serialize_with]]
@record_mode = :all if should_re_record?

raise_error_unless_valid_record_mode

Expand All @@ -57,7 +58,8 @@ def new_recorded_interactions
end

def file
File.join(VCR.configuration.cassette_library_dir, "#{sanitized_name}.yml") if VCR.configuration.cassette_library_dir
return nil unless VCR.configuration.cassette_library_dir
File.join(VCR.configuration.cassette_library_dir, "#{sanitized_name}.#{@serializer.file_extension}")
end

def update_content_length_header?
Expand Down
3 changes: 2 additions & 1 deletion lib/vcr/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ def initialize
@allow_http_connections_when_no_cassette = nil
@default_cassette_options = {
:record => :once,
:match_requests_on => RequestMatcherRegistry::DEFAULT_MATCHERS
:match_requests_on => RequestMatcherRegistry::DEFAULT_MATCHERS,
:serialize_with => :yaml
}
end

Expand Down
6 changes: 6 additions & 0 deletions spec/vcr/cassette_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ def http_interaction
cassette.file.should eq(File.join(VCR.configuration.cassette_library_dir, 'the_file.yml'))
end

it 'uses the file extension from the serializer' do
VCR.cassette_serializers[:custom] = stub(:file_extension => "custom")
cassette = VCR::Cassette.new('the_file', :serialize_with => :custom)
cassette.file.should =~ /\.custom$/
end

it 'strips out disallowed characters so that it is a valid file name with no spaces' do
cassette = VCR::Cassette.new("\nthis \t! is-the_13212_file name")
cassette.file.should =~ /#{Regexp.escape('_this_is-the_13212_file_name.yml')}$/
Expand Down
3 changes: 2 additions & 1 deletion spec/vcr/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
it 'has a hash with some defaults' do
subject.default_cassette_options.should eq({
:match_requests_on => VCR::RequestMatcherRegistry::DEFAULT_MATCHERS,
:record => :once
:record => :once,
:serialize_with => :yaml
})
end

Expand Down

0 comments on commit d54d572

Please sign in to comment.