hashrocket-netrecorder 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +11 -0
- data/README.rdoc +62 -0
- data/Rakefile +15 -0
- data/features/manage_cache.feature +41 -0
- data/features/step_definitions/manage_cache_steps.rb +74 -0
- data/features/support/env.rb +1 -0
- data/lib/config.rb +13 -0
- data/lib/http.rb +51 -0
- data/lib/http_header.rb +17 -0
- data/lib/netrecorder.rb +85 -0
- data/netrecorder.gemspec +42 -0
- metadata +115 -0
data/Manifest
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
== NetRecorder
|
2
|
+
|
3
|
+
Record network responses for easy stubbing of external calls.
|
4
|
+
|
5
|
+
Net recorder hooks into NetHTTP to record the outgoing request path and method and caches the response. Then you can switch on fakeweb and it will use the cache from the recording.
|
6
|
+
|
7
|
+
== Requirements
|
8
|
+
|
9
|
+
gem install fakeweb
|
10
|
+
|
11
|
+
== Install
|
12
|
+
|
13
|
+
gem install netrecorder
|
14
|
+
|
15
|
+
== Usage
|
16
|
+
|
17
|
+
Anywhere you use fakeweb, you can use net recorder.
|
18
|
+
|
19
|
+
Record all responses:
|
20
|
+
|
21
|
+
NetRecorder.config do |config|
|
22
|
+
config.cache_file = File.join(RAILS_ROOT, 'fakeweb')
|
23
|
+
config.record_net_calls = true
|
24
|
+
end
|
25
|
+
|
26
|
+
Save recorded responses:
|
27
|
+
|
28
|
+
NetRecorder.cache!
|
29
|
+
|
30
|
+
Use recorded cache with fakeweb:
|
31
|
+
|
32
|
+
NetRecorder.config do |config|
|
33
|
+
config.cache_file = File.join(RAILS_ROOT, 'features', 'support', 'fakeweb')
|
34
|
+
config.fakeweb = true
|
35
|
+
end
|
36
|
+
|
37
|
+
== Cucumber Example
|
38
|
+
|
39
|
+
see http://cukes.info for more info on testing with Cucumber
|
40
|
+
# Find me in features/support/netrecorder.rb
|
41
|
+
|
42
|
+
NetRecorder.config do |config|
|
43
|
+
config.cache_file = "#{File.dirname(__FILE__)}/../support/fakeweb"
|
44
|
+
if ENV['RECORD_WEB']
|
45
|
+
config.record_net_calls = true
|
46
|
+
else
|
47
|
+
config.fakeweb = true
|
48
|
+
FakeWeb.allow_net_connect = false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
at_exit do
|
53
|
+
if NetRecorder.recording?
|
54
|
+
NetRecorder.cache!
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
record mode (command line)
|
59
|
+
>> rake features RECORD_NET_CALLS=true
|
60
|
+
|
61
|
+
cache mode (command line)
|
62
|
+
>> rake features
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('hashrocket-netrecorder', '0.2.1') do |p|
|
6
|
+
p.description = "Record network responses for easy stubbing of external calls"
|
7
|
+
p.url = "http://github.com/hashrocket/netrecorder"
|
8
|
+
p.author = "Chris Young, Josh Graham, Jim Remsik"
|
9
|
+
p.email = "dev@hashrocket.com"
|
10
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
11
|
+
p.development_dependencies = %w(echoe cucumber rspec)
|
12
|
+
p.runtime_dependencies = %w(fakeweb)
|
13
|
+
end
|
14
|
+
|
15
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
@@ -0,0 +1,41 @@
|
|
1
|
+
Feature: Manage cache
|
2
|
+
In order to speed up my testing and avoid network calls
|
3
|
+
As a user
|
4
|
+
I want to be able to manage the cache
|
5
|
+
|
6
|
+
Scenario: Cache a page
|
7
|
+
Given caching is turned on
|
8
|
+
And a clear cache
|
9
|
+
When I visit "http://www.example.com"
|
10
|
+
And I save the cache
|
11
|
+
Then the cache should contain the example body
|
12
|
+
|
13
|
+
Scenario: Cache a page with a Net::HTTP request with a block
|
14
|
+
Given caching is turned on
|
15
|
+
And a clear cache
|
16
|
+
When I visit "http://www.example.com" using a Net::HTTP request with a block
|
17
|
+
And I save the cache
|
18
|
+
Then the cache should contain the example body
|
19
|
+
And the Net::HTTP request should return the response
|
20
|
+
|
21
|
+
Scenario: Clear the cache
|
22
|
+
Given caching is turned on
|
23
|
+
And a clear cache
|
24
|
+
And a cached example page
|
25
|
+
When I delete the cache
|
26
|
+
Then the cache should be empty
|
27
|
+
|
28
|
+
Scenario: Cache the same page twice
|
29
|
+
Given caching is turned on
|
30
|
+
And a clear cache
|
31
|
+
When I visit "http://www.example.com"
|
32
|
+
And I visit "http://www.example.com"
|
33
|
+
And I save the cache
|
34
|
+
Then the example entry should have 2 responses
|
35
|
+
|
36
|
+
Scenario: Load from a cache
|
37
|
+
Given caching is turned on
|
38
|
+
And a clear cache
|
39
|
+
And a cached example page
|
40
|
+
And I have turned on fakeweb
|
41
|
+
Then I should not hit the web if i visit the example page
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fakeweb'
|
3
|
+
require "#{File.dirname(__FILE__)}/../../lib/netrecorder"
|
4
|
+
|
5
|
+
module NetRecorderMatchers
|
6
|
+
def be_the_example_dot_com_response
|
7
|
+
simple_matcher("the example.com response") do |given|
|
8
|
+
given =~ /You have reached this web page by typing.*example\.com/
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
World(NetRecorderMatchers)
|
14
|
+
|
15
|
+
Then "caching is turned on" do
|
16
|
+
NetRecorder.config do |config|
|
17
|
+
config.cache_file = File.join(File.dirname(__FILE__), '..', 'support', 'cache')
|
18
|
+
config.record_net_calls = true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
And /^I save the cache$/ do
|
23
|
+
NetRecorder.cache!
|
24
|
+
end
|
25
|
+
|
26
|
+
And /^I visit "([^\"]*)"$/ do |url|
|
27
|
+
Net::HTTP.get URI.parse(url)
|
28
|
+
end
|
29
|
+
|
30
|
+
When /^I visit "([^\"]*)" using a Net::HTTP request with a block$/ do |url|
|
31
|
+
uri = URI.parse(url)
|
32
|
+
@last_response = Net::HTTP.new(uri.host, uri.port).start do |http|
|
33
|
+
http.get(uri.path.empty? ? '/' : uri.path)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Then /^the Net::HTTP request should return the response$/ do
|
38
|
+
@last_response.should_not be_nil
|
39
|
+
@last_response.body.should be_the_example_dot_com_response
|
40
|
+
end
|
41
|
+
|
42
|
+
Given /^(?:a clear cache|I delete the cache)$/ do
|
43
|
+
NetRecorder.clear_cache!
|
44
|
+
end
|
45
|
+
|
46
|
+
Then /^the cache should contain the example body$/ do
|
47
|
+
NetRecorder.fakes.first[1]['global'][:response].first[:response].body.should be_the_example_dot_com_response
|
48
|
+
end
|
49
|
+
|
50
|
+
Given /^a cached example page$/ do
|
51
|
+
Given "caching is turned on"
|
52
|
+
When %Q{I visit "http://www.example.com"}
|
53
|
+
And "I save the cache"
|
54
|
+
end
|
55
|
+
|
56
|
+
Then /^the cache should be empty$/ do
|
57
|
+
NetRecorder.fakes.should == []
|
58
|
+
end
|
59
|
+
|
60
|
+
Then /^the example entry should have (.+) responses$/ do |count|
|
61
|
+
NetRecorder.fakes.first[1]['global'][:response].length.should == count.to_i
|
62
|
+
end
|
63
|
+
|
64
|
+
Given /^I have turned on fakeweb$/ do
|
65
|
+
NetRecorder.config do |config|
|
66
|
+
config.cache_file = File.join(File.dirname(__FILE__), '..', 'support', 'cache')
|
67
|
+
config.fakeweb = true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Then /^I should not hit the web if i visit the example page$/ do
|
72
|
+
FakeWeb.allow_net_connect = false
|
73
|
+
Proc.new{Net::HTTP.get URI.parse('http://www.example.com/')}.should_not raise_error
|
74
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# Empty for now
|
data/lib/config.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Config class is used to capture configuration options
|
2
|
+
module NetRecorder
|
3
|
+
class Config
|
4
|
+
# set to true to record net requests and responses to the cache file
|
5
|
+
attr_accessor :record_net_calls
|
6
|
+
# set to true to use fakeweb and the cache
|
7
|
+
attr_accessor :fakeweb
|
8
|
+
# path to the cache file
|
9
|
+
attr_accessor :cache_file
|
10
|
+
# clear the cache
|
11
|
+
attr_accessor :clear_cache
|
12
|
+
end
|
13
|
+
end
|
data/lib/http.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Extend Net:HTTP to record requests and responses
|
2
|
+
module NetRecorder
|
3
|
+
module NetHTTP
|
4
|
+
def self.extended(base) #:nodoc:
|
5
|
+
base.class_eval do
|
6
|
+
alias :alias_for_request :request
|
7
|
+
@@fakes = fakes_cache || []
|
8
|
+
|
9
|
+
# request is overridden and the request and response are stored as a hash that can be written to a cache file
|
10
|
+
def request(req, body = nil, &block)
|
11
|
+
response = alias_for_request(req, body)
|
12
|
+
|
13
|
+
if NetRecorder.recording?
|
14
|
+
scope = NetRecorder.scope || 'global'
|
15
|
+
path = "http://#{req.bauth if req.bauth}#{req['host']}#{req.path}"
|
16
|
+
|
17
|
+
existing_fake = @@fakes.detect{|fake| fake[0] == path && fake[1][scope] && fake[1][scope][:method] == req.method}
|
18
|
+
existing_fake[1][scope][:response] << {:response => response} and return response if existing_fake
|
19
|
+
|
20
|
+
@@fakes << [path, {scope => {:method => req.method, :response => [{:response => response}]}}]
|
21
|
+
end
|
22
|
+
|
23
|
+
yield response if block
|
24
|
+
response
|
25
|
+
end
|
26
|
+
|
27
|
+
# returns the fakes hash
|
28
|
+
def self.fakes
|
29
|
+
@@fakes
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.clear_netrecorder_cache! #:nodoc:
|
33
|
+
@@fakes = []
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def fakes_cache #:nodoc:
|
42
|
+
fakes =
|
43
|
+
if File.exist?(NetRecorder.cache_file)
|
44
|
+
File.open(NetRecorder.cache_file, "r") do |f|
|
45
|
+
YAML.load(f.read)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
return fakes if fakes.class == Hash
|
50
|
+
nil
|
51
|
+
end
|
data/lib/http_header.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Override Net:HTTP_Header to capture basic auth
|
2
|
+
module NetRecorder
|
3
|
+
module NetHTTPHeader
|
4
|
+
def self.extended(base) #:nodoc:
|
5
|
+
base.class_eval do
|
6
|
+
alias :alias_for_basic_auth :basic_auth
|
7
|
+
attr_accessor :bauth
|
8
|
+
|
9
|
+
# override basic auth to make grabbing the basic auth easy
|
10
|
+
def basic_auth(account, password)
|
11
|
+
@bauth = "#{account}:#{password}@"
|
12
|
+
alias_for_basic_auth(account, password)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/netrecorder.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# NetRecorder allows you to record requests and responses from the web
|
2
|
+
|
3
|
+
require 'fakeweb'
|
4
|
+
require 'yaml'
|
5
|
+
require "#{File.dirname(__FILE__)}/http"
|
6
|
+
require "#{File.dirname(__FILE__)}/http_header"
|
7
|
+
require "#{File.dirname(__FILE__)}/config"
|
8
|
+
|
9
|
+
# NetRecorder - the global namespace
|
10
|
+
module NetRecorder
|
11
|
+
|
12
|
+
# the path to the cache file
|
13
|
+
def self.cache_file
|
14
|
+
@@config.cache_file
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.fakes
|
18
|
+
if File.exist?(@@config.cache_file)
|
19
|
+
File.open(@@config.cache_file, "r") do |f|
|
20
|
+
YAML.load(f.read)
|
21
|
+
end
|
22
|
+
end || []
|
23
|
+
end
|
24
|
+
|
25
|
+
# configure netrecorder
|
26
|
+
def self.config
|
27
|
+
@@configured ||= nil
|
28
|
+
@@config = Config.new
|
29
|
+
yield @@config
|
30
|
+
record_net_calls
|
31
|
+
clear_cache! if @@config.clear_cache
|
32
|
+
fakeweb if @@config.fakeweb
|
33
|
+
end
|
34
|
+
|
35
|
+
# returns true if record_net_calls is set to true in the config
|
36
|
+
def self.recording?
|
37
|
+
@@config.record_net_calls
|
38
|
+
end
|
39
|
+
|
40
|
+
# save the fakes hash to the cash file
|
41
|
+
def self.cache!
|
42
|
+
File.open(@@config.cache_file, 'w') {|f| f.write Net::HTTP.fakes.to_yaml}
|
43
|
+
end
|
44
|
+
|
45
|
+
# delete the cache file
|
46
|
+
def self.clear_cache!
|
47
|
+
if File.exist?(@@config.cache_file)
|
48
|
+
File.delete(@@config.cache_file)
|
49
|
+
end
|
50
|
+
Net::HTTP.clear_netrecorder_cache!
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.register_scope(name)
|
54
|
+
fakeweb(name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.scope=(name)
|
58
|
+
@@scope = name
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.scope
|
62
|
+
return @@scope if defined?(@@scope)
|
63
|
+
'global'
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# load the cache and register all of the urls with fakeweb
|
69
|
+
def self.fakeweb(scope='global')
|
70
|
+
fakes.each do |fake|
|
71
|
+
if fake[1][scope]
|
72
|
+
FakeWeb.register_uri(fake[1][scope][:method].downcase.to_sym, fake[0], fake[1][scope][:response])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# extend NET library to record requests and responses
|
78
|
+
def self.record_net_calls
|
79
|
+
return if @@configured
|
80
|
+
@@configured = true
|
81
|
+
|
82
|
+
Net::HTTP.extend(NetHTTP)
|
83
|
+
Net::HTTPHeader.extend(NetHTTPHeader)
|
84
|
+
end
|
85
|
+
end
|
data/netrecorder.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{hashrocket-netrecorder}
|
5
|
+
s.version = "0.2.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Chris Young", "Josh Graham", "Jim Remsik"]
|
9
|
+
s.date = %q{2010-01-26}
|
10
|
+
s.description = %q{Record network responses for easy stubbing of external calls}
|
11
|
+
s.email = %q{dev@hashrocket.com}
|
12
|
+
s.extra_rdoc_files = ["README.rdoc", "lib/config.rb", "lib/http.rb", "lib/http_header.rb", "lib/netrecorder.rb"]
|
13
|
+
s.files = ["Manifest", "README.rdoc", "Rakefile", "features/manage_cache.feature", "features/step_definitions/manage_cache_steps.rb", "features/support/env.rb", "lib/config.rb", "lib/http.rb", "lib/http_header.rb", "lib/netrecorder.rb", "netrecorder.gemspec"]
|
14
|
+
s.homepage = %q{http://github.com/hashrocket/netrecorder}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Netrecorder", "--main", "README.rdoc"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{netrecorder}
|
18
|
+
s.rubygems_version = %q{1.3.5}
|
19
|
+
s.summary = %q{Record network responses for easy stubbing of external calls}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_runtime_dependency(%q<fakeweb>, [">= 0"])
|
27
|
+
s.add_development_dependency(%q<echoe>, [">= 0"])
|
28
|
+
s.add_development_dependency(%q<cucumber>, [">= 0"])
|
29
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
30
|
+
else
|
31
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
32
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
33
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
34
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
35
|
+
end
|
36
|
+
else
|
37
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
38
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
39
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
40
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hashrocket-netrecorder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Young
|
8
|
+
- Josh Graham
|
9
|
+
- Jim Remsik
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
|
14
|
+
date: 2010-01-26 00:00:00 -05:00
|
15
|
+
default_executable:
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: fakeweb
|
19
|
+
type: :runtime
|
20
|
+
version_requirement:
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: "0"
|
26
|
+
version:
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: echoe
|
29
|
+
type: :development
|
30
|
+
version_requirement:
|
31
|
+
version_requirements: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
version:
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: cucumber
|
39
|
+
type: :development
|
40
|
+
version_requirement:
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
version:
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
type: :development
|
50
|
+
version_requirement:
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
description: Record network responses for easy stubbing of external calls
|
58
|
+
email: dev@hashrocket.com
|
59
|
+
executables: []
|
60
|
+
|
61
|
+
extensions: []
|
62
|
+
|
63
|
+
extra_rdoc_files:
|
64
|
+
- README.rdoc
|
65
|
+
- lib/config.rb
|
66
|
+
- lib/http.rb
|
67
|
+
- lib/http_header.rb
|
68
|
+
- lib/netrecorder.rb
|
69
|
+
files:
|
70
|
+
- Manifest
|
71
|
+
- README.rdoc
|
72
|
+
- Rakefile
|
73
|
+
- features/manage_cache.feature
|
74
|
+
- features/step_definitions/manage_cache_steps.rb
|
75
|
+
- features/support/env.rb
|
76
|
+
- lib/config.rb
|
77
|
+
- lib/http.rb
|
78
|
+
- lib/http_header.rb
|
79
|
+
- lib/netrecorder.rb
|
80
|
+
- netrecorder.gemspec
|
81
|
+
has_rdoc: true
|
82
|
+
homepage: http://github.com/hashrocket/netrecorder
|
83
|
+
licenses: []
|
84
|
+
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options:
|
87
|
+
- --line-numbers
|
88
|
+
- --inline-source
|
89
|
+
- --title
|
90
|
+
- Netrecorder
|
91
|
+
- --main
|
92
|
+
- README.rdoc
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
version:
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: "1.2"
|
106
|
+
version:
|
107
|
+
requirements: []
|
108
|
+
|
109
|
+
rubyforge_project: netrecorder
|
110
|
+
rubygems_version: 1.3.5
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: Record network responses for easy stubbing of external calls
|
114
|
+
test_files: []
|
115
|
+
|