vcr 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +156 -0
  5. data/Rakefile +60 -0
  6. data/VERSION +1 -0
  7. data/features/fixtures/vcr_cassettes/1.8.6/cucumber_tags/replay_cassette1.yml +43 -0
  8. data/features/fixtures/vcr_cassettes/1.8.6/cucumber_tags/replay_cassette2.yml +45 -0
  9. data/features/fixtures/vcr_cassettes/1.8.6/nested_replay_cassette.yml +23 -0
  10. data/features/fixtures/vcr_cassettes/1.8.6/not_the_real_response.yml +43 -0
  11. data/features/fixtures/vcr_cassettes/1.8.7/cucumber_tags/replay_cassette1.yml +43 -0
  12. data/features/fixtures/vcr_cassettes/1.8.7/cucumber_tags/replay_cassette2.yml +45 -0
  13. data/features/fixtures/vcr_cassettes/1.8.7/nested_replay_cassette.yml +23 -0
  14. data/features/fixtures/vcr_cassettes/1.8.7/not_the_real_response.yml +43 -0
  15. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette1.yml +43 -0
  16. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette2.yml +61 -0
  17. data/features/fixtures/vcr_cassettes/1.9.1/nested_replay_cassette.yml +31 -0
  18. data/features/fixtures/vcr_cassettes/1.9.1/not_the_real_response.yml +43 -0
  19. data/features/record_response.feature +55 -0
  20. data/features/replay_recorded_response.feature +53 -0
  21. data/features/step_definitions/vcr_steps.rb +88 -0
  22. data/features/support/env.rb +55 -0
  23. data/lib/vcr.rb +48 -0
  24. data/lib/vcr/cassette.rb +89 -0
  25. data/lib/vcr/config.rb +19 -0
  26. data/lib/vcr/cucumber_tags.rb +38 -0
  27. data/lib/vcr/fake_web_extensions.rb +18 -0
  28. data/lib/vcr/net_http_extensions.rb +39 -0
  29. data/lib/vcr/recorded_response.rb +4 -0
  30. data/spec/cassette_spec.rb +185 -0
  31. data/spec/config_spec.rb +27 -0
  32. data/spec/cucumber_tags_spec.rb +71 -0
  33. data/spec/fake_web_extensions_spec.rb +26 -0
  34. data/spec/fixtures/1.8.6/cassette_spec/example.yml +78 -0
  35. data/spec/fixtures/1.8.7/cassette_spec/example.yml +78 -0
  36. data/spec/fixtures/1.9.1/cassette_spec/example.yml +77 -0
  37. data/spec/net_http_extensions_spec.rb +40 -0
  38. data/spec/recorded_response_spec.rb +25 -0
  39. data/spec/spec.opts +2 -0
  40. data/spec/spec_helper.rb +22 -0
  41. data/spec/support/temp_cache_dir.rb +16 -0
  42. data/spec/vcr_spec.rb +95 -0
  43. metadata +154 -0
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,22 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ features/fixtures/vcr_cassettes/**/temp/
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Myron Marston
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,156 @@
1
+ = VCR
2
+
3
+ VCR provides helpers to record HTTP requests for URIs that are not registered with fakeweb, and replay them later.
4
+ It provides built-in support for cucumber, but works with any ruby testing framework.
5
+
6
+ == Installation
7
+
8
+ gem install vcr
9
+
10
+ == Background
11
+
12
+ This README assumes you are familiar with FakeWeb; if not, please checkout the {README}[http://github.com/chrisk/fakeweb/blob/master/README.rdoc].
13
+
14
+ VCR was inspired by {NetRecorder}[http://github.com/chrisyoung/netrecorder], but was designed from the ground up to support
15
+ localized recording and replaying, rather than the global recording and replaying of NetRecorder.
16
+
17
+ == Cassettes
18
+
19
+ Cassettes are central to the way VCR works. They are a similar to VHS cassettes--your library of cassettes
20
+ is your library of previously recorded responses that can be replayed. When you create a cassette, it does
21
+ the following:
22
+
23
+ * It loads the previously recorded responses from the cache file corresponding to the cassette name.
24
+ * It register these responses with fakeweb (depending on the cassette's :record option--see below)
25
+ * It sets the <tt>FakeWeb.allow_net_connect</tt> setting based on the cassette's :record option.
26
+
27
+ While a cassette is active, any HTTP requests to a URL of a previously recorded responses will use get
28
+ the recorded response. New HTTP requests (i.e. HTTP requests that have not been previously recorded)
29
+ will be recorded to the same cache file, depending on your :record option. When you destroy a cassette,
30
+ it does the following:
31
+
32
+ * It saves all of the recorded responses (both old and new) to a cached yml file corresponding to the cassette name.
33
+ * It removes the registrations it made with fakeweb, to prevent "leakage" into other tests.
34
+ * It reverts the <tt>FakeWeb.allow_net_connect</tt> back to whatever it was before the cassette was created.
35
+
36
+ == Record modes
37
+
38
+ VCR supports 3 record modes, which configures when it records new responses. You can set a default
39
+ record mode in your configuration (see below) and a per-cassette record mode when creating a cassette. The record
40
+ modes are:
41
+
42
+ * :all - This will cause VCR to re-record all HTTP requests that occur while the cassette is the current one.
43
+ When the cassette is created, it will not register any of the cached responses with fakeweb.
44
+ <tt>FakeWeb.allow_net_connect</tt> will be set to true, so it can record the requests.
45
+ * :none - This will prevent VCR from recording, or even allowing, any new HTTP requests while the cassette is the current one.
46
+ The previously recorded responses will be registered with fakeweb. <tt>FakeWeb.allow_net_connect</tt> will be set to
47
+ false, so that no new HTTP connections are allowed.
48
+ * :unregistered - This will use the previously recorded responses, and record any new requests that are not registered with
49
+ fakeweb. The previously recorded responses will be registered with fakeweb. <tt>FakeWeb.allow_net_connect</tt> will be
50
+ set to true, so that VCR will record any new HTTP requests within the cassette.
51
+
52
+ Note that :none and :unregistered will usually at the same. The difference is when your code changes and
53
+ it makes a new HTTP request that wasn't made when the cassette was first recorded. With :none, you would
54
+ get an error from FakeWeb (since allow_net_connect is set to false). With :unregistered, the new response
55
+ would get saved in the cassette's yaml file, and automatically get used in the future.
56
+
57
+ == Configuration
58
+
59
+ # Set the default allow_net_connect option--usually you'll want this off.
60
+ # You don't usually want your test suite to make HTTP connections, do you?
61
+ FakeWeb.allow_net_connect = false
62
+
63
+ VCR.config do |c|
64
+ # the cache_dir is where the cassette yml files will be saved.
65
+ c.cache_dir = File.join(Rails.root, 'features', 'fixtures', 'vcr_cassettes')
66
+
67
+ # this record mode will be used for any cassette you create without specifying a record mode.
68
+ c.default_cassette_record_mode = :none
69
+ end
70
+
71
+ This can go pretty much wherever, as long as this code is run before your tests, specs or scenarios.
72
+
73
+ == Usage with your favorite test/spec framework
74
+
75
+ VCR can easily be used with any ruby test/spec framework. Usually, you'll want to use <tt>VCR.with_cassette</tt>:
76
+
77
+ VCR.with_cassette('geocoding/Seattle, WA', :record => :unregistered) do
78
+ # do something that causes an HTTP request.
79
+ end
80
+
81
+ Alternately, you can create and destroy the cassette with individual method calls from setup/before and teardown/after:
82
+
83
+ describe "Something that makes an HTTP request" do
84
+ before(:each) do
85
+ VCR.create_cassette!('geocoding/Seattle, WA', :record => :unregistered)
86
+ end
87
+
88
+ it "should do something that makes an HTTP request"
89
+
90
+ after(:each) do
91
+ VCR.destroy_cassette!
92
+ end
93
+ end
94
+
95
+ In both of these cases, VCR would use the file geocoding/Seattle_WA.yml within the configured
96
+ cache dir. The :record setting is optional--if you leave it blank, your configured default will be used.
97
+
98
+ == Usage with Cucumber
99
+
100
+ VCR provides special support for cucumber. You can of course use <tt>VCR.with_cassette</tt> within a step definition,
101
+ and that's the recommended way for any of your step definitions. But many times I find myself using generic step definitions
102
+ provided by another library (such as the webrat/capybara web steps generated by cucumber-rails), and I don't want to modify
103
+ these. VCR provides cucumber tagging support to help in these cases:
104
+
105
+ # in a cucumber feature file...
106
+ @facebook_http_request
107
+ Scenario: Sign up with facebook connect
108
+
109
+ # in features/support/vcr.rb (or some similar support file)
110
+ VCR.cucumber_tags do |t|
111
+ t.tags '@facebook_http_request', '@twitter_status_update', :record => :none
112
+ t.tags '@another_scenario_tag' # the default record mode will be used for this tag.
113
+ end
114
+
115
+ # Note: you'd probably also want to put your VCR config in this file (see above).
116
+
117
+ For each of the tags you specify in your cucumber_tags block, VCR will set up the appropriate
118
+ {Before and After hooks}[http://wiki.github.com/aslakhellesoy/cucumber/hooks] to use a cassette
119
+ for the entire scenario. The tag (minus the '@') will be used as the cassette name, and it'll
120
+ go in the cucumber_tags subdirectory of the configured cache dir.
121
+
122
+ == Ruby Version Compatibility
123
+
124
+ specs.should pass if RUBY_VERSION =~ /^1.(8.6|8.7|9.1)$/
125
+
126
+ == Notes, etc.
127
+
128
+ * The cassette name determines the name of the cache file for the given cassette. Strings or symbols are fine,
129
+ and you can include any characters, but spaces and invalid file name characters will be removed
130
+ before the cassette reads or writes to the file.
131
+ * You can use a directory separator (i.e. '/') in your cassette names to cause it to use a subdirectory
132
+ of the cache_dir. The cucumber tagging support uses this.
133
+ * VCR maintains a simple stack of cassette. This allows you to nest them as deeply as you want.
134
+ This is particularly useful when you have a cucumber step definition that uses a cassette, and
135
+ you also want to use a cassette for the entire scenario using the tagging support.
136
+
137
+ == Note on Patches/Pull Requests
138
+
139
+ * Fork the project.
140
+ * Make your feature addition or bug fix.
141
+ * Add tests for it. This is important so I don't break it in a
142
+ future version unintentionally.
143
+ * Commit, do not mess with rakefile, version, or history.
144
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
145
+ * Send me a pull request. Bonus points for topic branches.
146
+
147
+ == Thanks
148
+
149
+ * {Aslak Hellesøy}[http://github.com/aslakhellesoy] for {Cucumber}[http://github.com/aslakhellesoy/cucumber].
150
+ * {Chris Kampmeier}[http://github.com/chrisk] for {FakeWeb}[http://github.com/chrisk/fakeweb].
151
+ * {Chris Young}[http://github.com/chrisyoung] for {NetRecorder}[http://github.com/chrisyoung/netrecorder], the inspiration
152
+ for VCR.
153
+
154
+ == Copyright
155
+
156
+ Copyright (c) 2010 Myron Marston. See LICENSE for details.
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "vcr"
8
+ gem.summary = %Q{Use VCR to record HTTP responses and replay them using fakeweb.}
9
+ gem.description = %Q{VCR provides helpers to record HTTP requests for URIs that are not registered with fakeweb, and replay them later. It provides built-in support for cucumber, but works with any ruby testing framework.}
10
+ gem.email = "myron.marston@gmail.com"
11
+ gem.homepage = "http://github.com/myronmarston/vcr"
12
+ gem.authors = ["Myron Marston"]
13
+
14
+ gem.add_dependency 'fakeweb', '>= 1.2.8'
15
+
16
+ gem.add_development_dependency "rspec", ">= 1.2.9"
17
+ gem.add_development_dependency "cucumber", ">= 0.6.1"
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+ require 'spec/rake/spectask'
26
+ Spec::Rake::SpecTask.new(:spec) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.spec_files = FileList['spec/**/*_spec.rb']
29
+ end
30
+
31
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
32
+ spec.libs << 'lib' << 'spec'
33
+ spec.pattern = 'spec/**/*_spec.rb'
34
+ spec.rcov = true
35
+ end
36
+
37
+ task :spec => :check_dependencies if defined?(Jeweler)
38
+
39
+ begin
40
+ require 'cucumber/rake/task'
41
+ Cucumber::Rake::Task.new(:features)
42
+
43
+ task :features => :check_dependencies
44
+ rescue LoadError
45
+ task :features do
46
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
47
+ end
48
+ end
49
+
50
+ task :default => [:spec, :features]
51
+
52
+ require 'rake/rdoctask'
53
+ Rake::RDocTask.new do |rdoc|
54
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
55
+
56
+ rdoc.rdoc_dir = 'rdoc'
57
+ rdoc.title = "vcr #{version}"
58
+ rdoc.rdoc_files.include('README*')
59
+ rdoc.rdoc_files.include('lib/**/*.rb')
60
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,43 @@
1
+ ---
2
+ - !ruby/struct:VCR::RecordedResponse
3
+ method: :get
4
+ uri: http://example.com:80/
5
+ response: !ruby/object:Net::HTTPOK
6
+ body: |
7
+ <HTML>
8
+ <HEAD>
9
+ <TITLE>Example Web Page</TITLE>
10
+ </HEAD>
11
+ <body>
12
+ <p>
13
+ This is not the real response from example.com
14
+ </p>
15
+ </BODY>
16
+ </HTML>
17
+
18
+
19
+ body_exist: true
20
+ code: "200"
21
+ header:
22
+ etag:
23
+ - "\"24ec5-1b6-4059a80bfd280\""
24
+ last-modified:
25
+ - Tue, 15 Nov 2005 13:24:10 GMT
26
+ connection:
27
+ - Keep-Alive
28
+ content-type:
29
+ - text/html; charset=UTF-8
30
+ date:
31
+ - Thu, 25 Feb 2010 15:22:32 GMT
32
+ server:
33
+ - Apache/2.2.3 (CentOS)
34
+ content-length:
35
+ - "438"
36
+ age:
37
+ - "2643"
38
+ accept-ranges:
39
+ - bytes
40
+ http_version: "1.1"
41
+ message: OK
42
+ read: true
43
+ socket:
@@ -0,0 +1,45 @@
1
+ ---
2
+ - !ruby/struct:VCR::RecordedResponse
3
+ method: :get
4
+ uri: http://example.com:80/before_nested
5
+ response: !ruby/object:Net::HTTPNotFound
6
+ body: The before_nested response
7
+ body_exist: true
8
+ code: "404"
9
+ header:
10
+ content-type:
11
+ - text/html; charset=iso-8859-1
12
+ connection:
13
+ - close
14
+ server:
15
+ - Apache/2.2.3 (CentOS)
16
+ date:
17
+ - Thu, 25 Feb 2010 15:23:39 GMT
18
+ content-length:
19
+ - "287"
20
+ http_version: "1.1"
21
+ message: Not Found
22
+ read: true
23
+ socket:
24
+ - !ruby/struct:VCR::RecordedResponse
25
+ method: :get
26
+ uri: http://example.com:80/after_nested
27
+ response: !ruby/object:Net::HTTPNotFound
28
+ body: The after_nested response
29
+ body_exist: true
30
+ code: "404"
31
+ header:
32
+ content-type:
33
+ - text/html; charset=iso-8859-1
34
+ connection:
35
+ - close
36
+ server:
37
+ - Apache/2.2.3 (CentOS)
38
+ date:
39
+ - Thu, 25 Feb 2010 15:23:39 GMT
40
+ content-length:
41
+ - "286"
42
+ http_version: "1.1"
43
+ message: Not Found
44
+ read: true
45
+ socket:
@@ -0,0 +1,23 @@
1
+ ---
2
+ - !ruby/struct:VCR::RecordedResponse
3
+ method: :get
4
+ uri: http://example.com:80/nested
5
+ response: !ruby/object:Net::HTTPNotFound
6
+ body: The nested response
7
+ body_exist: true
8
+ code: "404"
9
+ header:
10
+ content-type:
11
+ - text/html; charset=iso-8859-1
12
+ connection:
13
+ - close
14
+ server:
15
+ - Apache/2.2.3 (CentOS)
16
+ date:
17
+ - Thu, 25 Feb 2010 15:19:40 GMT
18
+ content-length:
19
+ - "280"
20
+ http_version: "1.1"
21
+ message: Not Found
22
+ read: true
23
+ socket:
@@ -0,0 +1,43 @@
1
+ ---
2
+ - !ruby/struct:VCR::RecordedResponse
3
+ method: :get
4
+ uri: http://example.com:80/
5
+ response: !ruby/object:Net::HTTPOK
6
+ body: |
7
+ <HTML>
8
+ <HEAD>
9
+ <TITLE>Example Web Page</TITLE>
10
+ </HEAD>
11
+ <body>
12
+ <p>
13
+ This is not the real response from example.com
14
+ </p>
15
+ </BODY>
16
+ </HTML>
17
+
18
+
19
+ body_exist: true
20
+ code: "200"
21
+ header:
22
+ etag:
23
+ - "\"24ec5-1b6-4059a80bfd280\""
24
+ last-modified:
25
+ - Tue, 15 Nov 2005 13:24:10 GMT
26
+ connection:
27
+ - Keep-Alive
28
+ content-type:
29
+ - text/html; charset=UTF-8
30
+ date:
31
+ - Thu, 25 Feb 2010 15:20:47 GMT
32
+ server:
33
+ - Apache/2.2.3 (CentOS)
34
+ content-length:
35
+ - "438"
36
+ age:
37
+ - "2546"
38
+ accept-ranges:
39
+ - bytes
40
+ http_version: "1.1"
41
+ message: OK
42
+ read: true
43
+ socket:
@@ -0,0 +1,43 @@
1
+ ---
2
+ - !ruby/struct:VCR::RecordedResponse
3
+ method: :get
4
+ uri: http://example.com:80/
5
+ response: !ruby/object:Net::HTTPOK
6
+ body: |
7
+ <HTML>
8
+ <HEAD>
9
+ <TITLE>Example Web Page</TITLE>
10
+ </HEAD>
11
+ <body>
12
+ <p>
13
+ This is not the real response from example.com
14
+ </p>
15
+ </BODY>
16
+ </HTML>
17
+
18
+
19
+ body_exist: true
20
+ code: "200"
21
+ header:
22
+ etag:
23
+ - "\"24ec5-1b6-4059a80bfd280\""
24
+ last-modified:
25
+ - Tue, 15 Nov 2005 13:24:10 GMT
26
+ connection:
27
+ - Keep-Alive
28
+ content-type:
29
+ - text/html; charset=UTF-8
30
+ date:
31
+ - Thu, 25 Feb 2010 15:22:32 GMT
32
+ server:
33
+ - Apache/2.2.3 (CentOS)
34
+ content-length:
35
+ - "438"
36
+ age:
37
+ - "2643"
38
+ accept-ranges:
39
+ - bytes
40
+ http_version: "1.1"
41
+ message: OK
42
+ read: true
43
+ socket: