vcr 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +5 -2
  2. data/.travis.yml +3 -1
  3. data/Appraisals +0 -4
  4. data/CHANGELOG.md +90 -54
  5. data/Gemfile +6 -6
  6. data/{gemfiles/typhoeus-new.gemfile.lock → Gemfile.lock} +34 -37
  7. data/LICENSE +1 -1
  8. data/README.md +14 -7
  9. data/Rakefile +8 -6
  10. data/cucumber.yml +10 -7
  11. data/features/.nav +3 -0
  12. data/features/configuration/preserve_exact_body_bytes.feature +2 -2
  13. data/features/configuration/query_parser.feature +84 -0
  14. data/features/configuration/uri_parser.feature +1 -1
  15. data/features/hooks/around_http_request.feature +1 -1
  16. data/features/request_matching/README.md +2 -0
  17. data/features/request_matching/query.feature +97 -0
  18. data/gemfiles/{typhoeus-old.gemfile → typhoeus_old.gemfile} +1 -3
  19. data/gemfiles/{typhoeus-old.gemfile.lock → typhoeus_old.gemfile.lock} +25 -17
  20. data/lib/vcr.rb +5 -1
  21. data/lib/vcr/configuration.rb +20 -0
  22. data/lib/vcr/deprecations.rb +62 -1
  23. data/lib/vcr/errors.rb +9 -9
  24. data/lib/vcr/library_hooks/fakeweb.rb +1 -0
  25. data/lib/vcr/library_hooks/typhoeus.rb +1 -0
  26. data/lib/vcr/library_hooks/webmock.rb +1 -1
  27. data/lib/vcr/request_matcher_registry.rb +8 -1
  28. data/lib/vcr/structs.rb +2 -2
  29. data/lib/vcr/test_frameworks/rspec.rb +0 -56
  30. data/lib/vcr/version.rb +1 -1
  31. data/script/ci.sh +2 -2
  32. data/spec/monkey_patches.rb +1 -1
  33. data/spec/spec_helper.rb +12 -13
  34. data/spec/support/http_library_adapters.rb +9 -1
  35. data/spec/vcr/deprecations_spec.rb +11 -9
  36. data/spec/vcr/library_hooks/fakeweb_spec.rb +5 -0
  37. data/spec/vcr/library_hooks/typhoeus_spec.rb +55 -0
  38. data/spec/vcr/request_matcher_registry_spec.rb +39 -0
  39. data/vcr.gemspec +4 -3
  40. metadata +79 -85
  41. data/gemfiles/typhoeus-new.gemfile +0 -18
@@ -14,6 +14,8 @@ Specify an array of attributes to match on. Supported attributes are:
14
14
  - `:path` - The path of the URI. You can use this (alone, or in combination
15
15
  with `:host`) as an alternative to `:uri` to cause VCR to match using a regex
16
16
  that matches the path.
17
+ - `:query` - The query string values of the URI. The query string ordering does
18
+ not affect matching results (it's order-agnostic).
17
19
  - `:body` - The body of the request.
18
20
  - `:headers` - The request headers.
19
21
 
@@ -0,0 +1,97 @@
1
+ Feature: Matching on Query string
2
+
3
+ Use the `:query` request matcher to match requests on the query string
4
+ portion of the request URI.
5
+
6
+ You can use this (alone, or in combination with others) as an
7
+ alternative to `:uri` so that non-deterministic portions of the URI
8
+ are not considered as part of the request matching.
9
+
10
+ Background:
11
+ Given a previously recorded cassette file "cassettes/example.yml" with:
12
+ """
13
+ ---
14
+ http_interactions:
15
+ - request:
16
+ method: post
17
+ uri: http://host1.com/query?date=2011-09-01
18
+ body:
19
+ encoding: UTF-8
20
+ string: ""
21
+ headers: {}
22
+ response:
23
+ status:
24
+ code: 200
25
+ message: OK
26
+ headers:
27
+ Content-Length:
28
+ - "19"
29
+ body:
30
+ encoding: UTF-8
31
+ string: 2011-09-01 response
32
+ http_version: "1.1"
33
+ recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
34
+ - request:
35
+ method: post
36
+ uri: http://host1.com/query?date=2011-09-02
37
+ body:
38
+ encoding: UTF-8
39
+ string: ""
40
+ headers: {}
41
+ response:
42
+ status:
43
+ code: 200
44
+ message: OK
45
+ headers:
46
+ Content-Length:
47
+ - "19"
48
+ body:
49
+ encoding: UTF-8
50
+ string: 2011-09-02 response
51
+ http_version: "1.1"
52
+ recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
53
+ recorded_with: VCR 2.0.0
54
+ """
55
+
56
+ Scenario Outline: Replay interaction that matches the query string
57
+ And a file named "query_matching.rb" with:
58
+ """ruby
59
+ include_http_adapter_for("<http_lib>")
60
+
61
+ require 'vcr'
62
+
63
+ VCR.configure do |c|
64
+ <configuration>
65
+ c.default_cassette_options = { :match_requests_on => [:query] }
66
+ c.cassette_library_dir = 'cassettes'
67
+ end
68
+
69
+ VCR.use_cassette('example', :match_requests_on => [:query]) do
70
+ puts "Response for 2011-09-01 /query: " + response_body_for(:get, "http://example.com/query?date=2011-09-01")
71
+ end
72
+
73
+ VCR.use_cassette('example', :match_requests_on => [:query]) do
74
+ puts "Response for 2011-09-02 /query: " + response_body_for(:get, "http://example.com/query?date=2011-09-02")
75
+ end
76
+ """
77
+ When I run `ruby query_matching.rb`
78
+ Then it should pass with:
79
+ """
80
+ Response for 2011-09-01 /query: 2011-09-01 response
81
+ Response for 2011-09-02 /query: 2011-09-02 response
82
+ """
83
+
84
+ Examples:
85
+ | configuration | http_lib |
86
+ | c.hook_into :fakeweb | net/http |
87
+ | c.hook_into :webmock | net/http |
88
+ | c.hook_into :webmock | httpclient |
89
+ | c.hook_into :webmock | curb |
90
+ | c.hook_into :webmock | patron |
91
+ | c.hook_into :webmock | em-http-request |
92
+ | c.hook_into :webmock | typhoeus |
93
+ | c.hook_into :typhoeus | typhoeus |
94
+ | c.hook_into :excon | excon |
95
+ | c.hook_into :faraday | faraday (w/ net_http) |
96
+ | c.hook_into :faraday | faraday (w/ typhoeus) |
97
+
@@ -8,10 +8,8 @@ gem "yard"
8
8
  gem "relish", "~> 0.6"
9
9
  gem "fuubar"
10
10
  gem "fuubar-cucumber"
11
- gem "redcarpet", "~> 1.17.2"
11
+ gem "redcarpet", "~> 1.17.2", :platforms=>:ruby
12
12
  gem "github-markup"
13
- gem "ruby-debug", :platforms=>[:mri_18, :jruby]
14
- gem "debugger", :platforms=>:mri_19
15
13
  gem "typhoeus", "~> 0.4.2"
16
14
  gem "webmock", "1.8.11"
17
15
 
@@ -1,13 +1,13 @@
1
1
  PATH
2
- remote: /Users/myron/code/vcr
2
+ remote: /Users/hungerandthirst/Code/Ruby/vcr
3
3
  specs:
4
- vcr (2.2.5)
4
+ vcr (2.3.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
9
  addressable (2.3.2)
10
- appraisal (0.4.1)
10
+ appraisal (0.5.1)
11
11
  bundler
12
12
  rake
13
13
  archive-tar-minitar (0.5.2)
@@ -19,6 +19,7 @@ GEM
19
19
  builder (3.1.4)
20
20
  childprocess (0.3.6)
21
21
  ffi (~> 1.0, >= 1.0.6)
22
+ coderay (1.0.8)
22
23
  columnize (0.3.6)
23
24
  cookiejar (0.3.0)
24
25
  crack (0.3.1)
@@ -28,14 +29,14 @@ GEM
28
29
  gherkin (~> 2.9.0)
29
30
  json (>= 1.4.6)
30
31
  term-ansicolor (>= 1.0.6)
31
- curb (0.8.1)
32
- debugger (1.2.1)
32
+ curb (0.8.3)
33
+ debugger (1.2.2)
33
34
  columnize (>= 0.3.1)
34
35
  debugger-linecache (~> 1.1.1)
35
- debugger-ruby_core_source (~> 1.1.4)
36
+ debugger-ruby_core_source (~> 1.1.5)
36
37
  debugger-linecache (1.1.2)
37
38
  debugger-ruby_core_source (>= 1.1.1)
38
- debugger-ruby_core_source (1.1.4)
39
+ debugger-ruby_core_source (1.1.5)
39
40
  diff-lcs (1.1.3)
40
41
  em-http-request (1.0.3)
41
42
  addressable (>= 2.2.3)
@@ -46,11 +47,11 @@ GEM
46
47
  em-socksify (0.2.1)
47
48
  eventmachine (>= 1.0.0.beta.4)
48
49
  eventmachine (1.0.0)
49
- excon (0.16.7)
50
+ excon (0.16.10)
50
51
  fakeweb (1.3.0)
51
52
  faraday (0.8.4)
52
53
  multipart-post (~> 1.1)
53
- ffi (1.1.5)
54
+ ffi (1.2.0)
54
55
  fuubar (1.0.0)
55
56
  rspec (~> 2.0)
56
57
  rspec-instafail (~> 0.2.0)
@@ -66,14 +67,19 @@ GEM
66
67
  json (1.6.7)
67
68
  linecache (0.46)
68
69
  rbx-require-relative (> 0.0.4)
70
+ method_source (0.8.1)
69
71
  mime-types (1.19)
70
72
  multi_json (1.0.4)
71
73
  multipart-post (1.1.5)
72
74
  patron (0.4.18)
75
+ pry (0.9.10)
76
+ coderay (~> 1.0.5)
77
+ method_source (~> 0.8)
78
+ slop (~> 3.3.1)
73
79
  rack (1.3.6)
74
80
  rack-protection (1.2.0)
75
81
  rack
76
- rake (0.9.2.2)
82
+ rake (0.9.5)
77
83
  rbx-require-relative (0.0.9)
78
84
  redcarpet (1.17.2)
79
85
  redis (2.2.2)
@@ -83,15 +89,15 @@ GEM
83
89
  rest-client (>= 1.6.1)
84
90
  rest-client (1.6.7)
85
91
  mime-types (>= 1.16)
86
- rspec (2.11.0)
87
- rspec-core (~> 2.11.0)
88
- rspec-expectations (~> 2.11.0)
89
- rspec-mocks (~> 2.11.0)
90
- rspec-core (2.11.1)
91
- rspec-expectations (2.11.3)
92
+ rspec (2.12.0)
93
+ rspec-core (~> 2.12.0)
94
+ rspec-expectations (~> 2.12.0)
95
+ rspec-mocks (~> 2.12.0)
96
+ rspec-core (2.12.0)
97
+ rspec-expectations (2.12.0)
92
98
  diff-lcs (~> 1.1.3)
93
99
  rspec-instafail (0.2.4)
94
- rspec-mocks (2.11.3)
100
+ rspec-mocks (2.12.0)
95
101
  ruby-debug (0.10.4)
96
102
  columnize (>= 0.1)
97
103
  ruby-debug-base (~> 0.10.4.0)
@@ -107,6 +113,7 @@ GEM
107
113
  rack (~> 1.3, >= 1.3.6)
108
114
  rack-protection (~> 1.2)
109
115
  tilt (~> 1.3, >= 1.3.3)
116
+ slop (3.3.3)
110
117
  term-ansicolor (1.0.7)
111
118
  tilt (1.3.3)
112
119
  timecop (0.3.5)
@@ -141,6 +148,7 @@ DEPENDENCIES
141
148
  json (~> 1.6.5)
142
149
  multi_json (~> 1.0.3)
143
150
  patron (~> 0.4.15)
151
+ pry
144
152
  rack (~> 1.3.6)
145
153
  rake (~> 0.9.2)
146
154
  redcarpet (~> 1.17.2)
data/lib/vcr.rb CHANGED
@@ -24,7 +24,11 @@ module VCR
24
24
 
25
25
  autoload :CucumberTags, 'vcr/test_frameworks/cucumber'
26
26
  autoload :InternetConnection, 'vcr/util/internet_connection'
27
- autoload :RSpec, 'vcr/test_frameworks/rspec'
27
+
28
+ module RSpec
29
+ autoload :Metadata, 'vcr/test_frameworks/rspec'
30
+ autoload :Macros, 'vcr/deprecations'
31
+ end
28
32
 
29
33
  module Middleware
30
34
  autoload :Faraday, 'vcr/middleware/faraday'
@@ -1,5 +1,6 @@
1
1
  require 'vcr/util/hooks'
2
2
  require 'uri'
3
+ require 'cgi'
3
4
 
4
5
  module VCR
5
6
  # Stores the VCR configuration.
@@ -124,6 +125,24 @@ module VCR
124
125
  !!@allow_http_connections_when_no_cassette
125
126
  end
126
127
 
128
+ # Sets a parser for VCR to use when parsing query strings for request
129
+ # comparisons. The new parser must implement a method `call` that returns
130
+ # an object which is both equalivant and consistent when given an HTTP
131
+ # query string of possibly differing value ordering.
132
+ #
133
+ # * `#== # => Boolean`
134
+ #
135
+ # The `#==` method must return true if both objects represent the
136
+ # same query string.
137
+ #
138
+ # This defaults to `CGI.parse` from the ruby standard library.
139
+ #
140
+ # @overload query_parser
141
+ # @return [#call] the current query string parser object
142
+ # @overload query_parser=
143
+ # @param value [#call] sets the query_parser
144
+ attr_accessor :query_parser
145
+
127
146
  # Sets a parser for VCR to use when parsing URIs. The new parser
128
147
  # must implement a method `parse` that returns an instance of the
129
148
  # URI object. This URI object must implement the following
@@ -452,6 +471,7 @@ module VCR
452
471
  }
453
472
 
454
473
  self.uri_parser = URI
474
+ self.query_parser = CGI.method(:parse)
455
475
  self.debug_logger = NullDebugLogger
456
476
 
457
477
  register_built_in_hooks
@@ -24,7 +24,7 @@ module VCR
24
24
  # @deprecated Use #hook_into instead.
25
25
  # @see #hook_into
26
26
  def stub_with(*adapters)
27
- warn "WARNING: `VCR.config { |c| c.stub_with ... }` is deprecated. Use `VCR.configure { |c| c.hook_into ... }` instead."
27
+ warn "WARNING: `VCR.configure { |c| c.stub_with ... }` is deprecated. Use `VCR.configure { |c| c.hook_into ... }` instead."
28
28
  hook_into(*adapters)
29
29
  end
30
30
  end
@@ -43,5 +43,66 @@ module VCR
43
43
  end
44
44
  end
45
45
  end
46
+
47
+ module RSpec
48
+ # Contains macro methods to assist with VCR usage. These methods are
49
+ # intended to be used directly in an RSpec example group. To make these
50
+ # available in your RSpec example groups, extend the module in an individual
51
+ # example group, or configure RSpec to extend the module in all example groups.
52
+ #
53
+ # @example
54
+ # RSpec.configure do |c|
55
+ # c.extend VCR::RSpec::Macros
56
+ # end
57
+ #
58
+ module Macros
59
+ def self.extended(base)
60
+ Kernel.warn "WARNING: VCR::RSpec::Macros is deprecated. Use RSpec metadata options instead `:vcr => vcr_options`"
61
+ end
62
+
63
+ # Sets up a `before` and `after` hook that will insert and eject a
64
+ # cassette, respectively.
65
+ #
66
+ # @example
67
+ # describe "Some API Client" do
68
+ # use_vcr_cassette "some_api", :record => :new_episodes
69
+ # end
70
+ #
71
+ # @param [(optional) String] name the cassette name; it will be inferred by the example
72
+ # group descriptions if not given.
73
+ # @param [(optional) Hash] options the cassette options
74
+ # @deprecated Use RSpec metadata options
75
+ def use_vcr_cassette(*args)
76
+ options = args.last.is_a?(Hash) ? args.pop : {}
77
+ name = args.first || infer_cassette_name
78
+
79
+ before(:each) do
80
+ VCR.insert_cassette(name, options)
81
+ end
82
+
83
+ after(:each) do
84
+ VCR.eject_cassette
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def infer_cassette_name
91
+ # RSpec 1 exposes #description_parts; use that if its available
92
+ return description_parts.join("/") if respond_to?(:description_parts)
93
+
94
+ # Otherwise use RSpec 2 metadata...
95
+ group_descriptions = []
96
+ klass = self
97
+
98
+ while klass.respond_to?(:metadata) && klass.metadata
99
+ group_descriptions << klass.metadata[:example_group][:description]
100
+ klass = klass.superclass
101
+ end
102
+
103
+ group_descriptions.compact.reverse.join('/')
104
+ end
105
+ end
106
+ end
46
107
  end
47
108
 
@@ -132,41 +132,41 @@ module VCR
132
132
  :use_new_episodes => [
133
133
  ["You can use the :new_episodes record mode to allow VCR to",
134
134
  "record this new request to the existing cassette"],
135
- "https://www.relishapp.com/myronmarston/vcr/v/%s/docs/record-modes/new-episodes"
135
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/record-modes/new-episodes"
136
136
  ],
137
137
 
138
138
  :delete_cassette_for_once => [
139
139
  ["The current record mode (:once) does not allow new requests to be recorded",
140
140
  "to a previously recorded cassette. You can delete the cassette file and re-run",
141
141
  "your tests to allow the cassette to be recorded with this request"],
142
- "https://www.relishapp.com/myronmarston/vcr/v/%s/docs/record-modes/once"
142
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/record-modes/once"
143
143
  ],
144
144
 
145
145
  :deal_with_none => [
146
146
  ["The current record mode (:none) does not allow requests to be recorded. You",
147
147
  "can temporarily change the record mode to :once, delete the cassette file ",
148
148
  "and re-run your tests to allow the cassette to be recorded with this request"],
149
- "https://www.relishapp.com/myronmarston/vcr/v/%s/docs/record-modes/none"
149
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/record-modes/none"
150
150
  ],
151
151
 
152
152
  :use_a_cassette => [
153
153
  ["If you want VCR to record this request and play it back during future test",
154
154
  "runs, you should wrap your test (or this portion of your test) in a",
155
155
  "`VCR.use_cassette` block"],
156
- "https://www.relishapp.com/myronmarston/vcr/v/%s/docs/getting-started"
156
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/getting-started"
157
157
  ],
158
158
 
159
159
  :allow_http_connections_when_no_cassette => [
160
160
  ["If you only want VCR to handle requests made while a cassette is in use,",
161
161
  "configure `allow_http_connections_when_no_cassette = true`. VCR will",
162
162
  "ignore this request since it is made when there is no cassette"],
163
- "https://www.relishapp.com/myronmarston/vcr/v/%s/docs/configuration/allow-http-connections-when-no-cassette"
163
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/configuration/allow-http-connections-when-no-cassette"
164
164
  ],
165
165
 
166
166
  :ignore_request => [
167
167
  ["If you want VCR to ignore this request (and others like it), you can",
168
168
  "set an `ignore_request` callback"],
169
- "https://www.relishapp.com/myronmarston/vcr/v/%s/docs/configuration/ignore-request"
169
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/configuration/ignore-request"
170
170
  ],
171
171
 
172
172
  :allow_playback_repeats => [
@@ -174,7 +174,7 @@ module VCR
174
174
  "but it has already been played back. If you wish to allow a single HTTP",
175
175
  "interaction to be played back multiple times, set the `:allow_playback_repeats`",
176
176
  "cassette option"],
177
- "https://www.relishapp.com/myronmarston/vcr/v/%s/docs/request-matching/playback-repeats"
177
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/request-matching/playback-repeats"
178
178
  ],
179
179
 
180
180
  :match_requests_on => [
@@ -182,14 +182,14 @@ module VCR
182
182
  "played back. If your request is non-deterministic, you may need to",
183
183
  "change your :match_requests_on cassette option to be more lenient",
184
184
  "or use a custom request matcher to allow it to match"],
185
- "https://www.relishapp.com/myronmarston/vcr/v/%s/docs/request-matching"
185
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/request-matching"
186
186
  ],
187
187
 
188
188
  :try_debug_logger => [
189
189
  ["If you're surprised VCR is raising this error",
190
190
  "and want insight about how VCR attempted to handle the request,",
191
191
  "you can use the debug_logger configuration option to log more details"],
192
- "https://www.relishapp.com/myronmarston/vcr/v/%s/docs/configuration/debug-logging"
192
+ "https://www.relishapp.com/vcr/vcr/v/%s/docs/configuration/debug-logging"
193
193
  ]
194
194
  }
195
195
 
@@ -191,5 +191,6 @@ VCR.configuration.after_library_hooks_loaded do
191
191
  if defined?(WebMock)
192
192
  raise ArgumentError.new("You have configured VCR to hook into both :fakeweb and :webmock. You cannot use both.")
193
193
  end
194
+ ::Kernel.warn "WARNING: VCR's FakeWeb integration is deprecated and will be removed in VCR 3.0."
194
195
  end
195
196
 
@@ -50,6 +50,7 @@ else
50
50
  :status_message => stubbed_response.status.message,
51
51
  :headers => stubbed_response_headers,
52
52
  :body => stubbed_response.body,
53
+ :effective_url => request.url,
53
54
  :mock => true
54
55
  end
55
56