webmock 1.3.5 → 1.4.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.
@@ -1,5 +1,28 @@
1
1
  #Changelog
2
2
 
3
+ ## 1.4.0
4
+
5
+ * Curb support!!! Thanks to the awesome work of Pete Higgins!
6
+
7
+ * `include WebMock` is now deprecated to avoid method and constant name conflicts. Please `include WebMock::API` instead.
8
+
9
+ * `WebMock::API#request` is renamed to `WebMock::API#a_request` to prevent method name conflicts with i.e. Rails controller specs.
10
+ WebMock.request is still available.
11
+
12
+ * Deprecated `WebMock#request`, `WebMock#allow_net_connect!`, `WebMock#net_connect_allowed?`, `WebMock#registered_request?`, `WebMock#reset_callbacks`, `WebMock#after_request` instance methods. These methods are still available, but only as WebMock class methods.
13
+
14
+ * Removed `WebMock.response_for_request` and `WebMock.assertion_failure` which were only used internally and were not documented.
15
+
16
+ * :allow_localhost => true' now permits 0.0.0.0 in addition to 127.0.0.1 and 'localhost'. Thanks to Myron Marston and Mike Gehard for suggesting this.
17
+
18
+ * Fixed issue with both RSpec 1.x and 2.x being available.
19
+
20
+ WebMock now tries to use already loaded version of RSpec (1.x or 2.x). Previously it was loading RSpec 2.0 if available, even if RSpec 1.3 was already loaded.
21
+
22
+ Thanks to Hans de Graaff for reporting this.
23
+
24
+ * Changed runtime dependency on Addressable version 2.2.2 which fixes handling of percent-escaped '+'
25
+
3
26
  ## 1.3.5
4
27
 
5
28
  * External requests can be disabled while allowing selected hosts. Thanks to Charles Li and Ryan Bigg
data/README.md CHANGED
@@ -21,6 +21,7 @@ Supported HTTP libraries
21
21
  * HTTPClient
22
22
  * Patron
23
23
  * EM-HTTP-Request
24
+ * Curb
24
25
 
25
26
  ##Installation
26
27
 
@@ -33,7 +34,7 @@ Add the following code to `test/test_helper.rb`
33
34
  require 'webmock/test_unit'
34
35
 
35
36
  class Test::Unit::TestCase
36
- config.include WebMock
37
+ include WebMock::API
37
38
  end
38
39
 
39
40
  ### RSpec
@@ -43,7 +44,7 @@ Add the following code to `spec/spec_helper`:
43
44
  require 'webmock/rspec'
44
45
 
45
46
  Spec::Runner.configure do |config|
46
- config.include WebMock
47
+ config.include WebMock::API
47
48
  end
48
49
 
49
50
  ### RSpec 2
@@ -53,25 +54,20 @@ Add the following code to `spec/spec_helper`:
53
54
  require 'webmock/rspec'
54
55
 
55
56
  RSpec.configure do |config|
56
- config.include WebMock
57
+ config.include WebMock::API
57
58
  end
58
59
 
59
60
  ### Cucumber
60
61
 
61
62
  Add the following code to `features/support/env.rb`
62
63
 
63
- require 'webmock/rspec'
64
- module WebMockWorld
65
- include WebMock
66
- include WebMock::Matchers
67
- end
68
-
69
- World(WebMockWorld)
64
+ require 'webmock/rspec'
65
+ World(WebMock::API, WebMock::Matchers)
70
66
 
71
67
  You can also use WebMock outside a test framework:
72
68
 
73
69
  require 'webmock'
74
- include WebMock
70
+ include WebMock::API
75
71
  include WebMock::Matchers
76
72
 
77
73
  ## Examples
@@ -357,19 +353,19 @@ You can also use WebMock outside a test framework:
357
353
 
358
354
  ### Different way of setting expectations in RSpec
359
355
 
360
- request(:post, "www.example.com").with(:body => "abc", :headers => {'Content-Length' => 3}).should have_been_made.once
356
+ a_request(:post, "www.example.com").with(:body => "abc", :headers => {'Content-Length' => 3}).should have_been_made.once
361
357
 
362
- request(:post, "www.something.com").should have_been_made.times(3)
358
+ a_request(:post, "www.something.com").should have_been_made.times(3)
363
359
 
364
- request(:any, "www.example.com").should_not have_been_made
360
+ a_request(:any, "www.example.com").should_not have_been_made
365
361
 
366
- request(:post, "www.example.com").with { |req| req.body == "abc" }.should have_been_made
367
-
368
- request(:get, "www.example.com").with(:query => {"a" => ["b", "c"]}).should have_been_made
369
-
370
- request(:post, "www.example.com").
362
+ a_request(:post, "www.example.com").with { |req| req.body == "abc" }.should have_been_made
363
+
364
+ a_request(:get, "www.example.com").with(:query => {"a" => ["b", "c"]}).should have_been_made
365
+
366
+ a_request(:post, "www.example.com").
371
367
  with(:body => {"a" => ["b", "c"]}, :headers => 'Content-Type' => 'application/json').should have_been_made
372
-
368
+
373
369
  ## Clearing stubs and request history
374
370
 
375
371
  If you want to reset all current stubs and history of requests use `WebMock.reset_webmock`
@@ -535,6 +531,7 @@ People who submitted patches and new features or suggested improvements. Many th
535
531
  * Muness Alrubaie
536
532
  * Charles Li
537
533
  * Ryan Bigg
534
+ * Pete Higgins
538
535
 
539
536
  ## Background
540
537
 
data/Rakefile CHANGED
@@ -10,12 +10,13 @@ begin
10
10
  gem.email = "bartosz.blimke@gmail.com"
11
11
  gem.homepage = "http://github.com/bblimke/webmock"
12
12
  gem.authors = ["Bartosz Blimke"]
13
- gem.add_dependency "addressable", ">= 2.1.1"
13
+ gem.add_dependency "addressable", ">= 2.2.2"
14
14
  gem.add_dependency "crack", ">=0.1.7"
15
15
  gem.add_development_dependency "rspec", ">= 1.2.9"
16
16
  gem.add_development_dependency "httpclient", ">= 2.1.5.2"
17
- gem.add_development_dependency "patron", ">= 0.4.5" unless RUBY_PLATFORM =~ /java/
18
- gem.add_development_dependency "em-http-request", ">= 0.2.7" unless RUBY_PLATFORM =~ /java/
17
+ gem.add_development_dependency "patron", ">= 0.4.9" unless RUBY_PLATFORM =~ /java/
18
+ gem.add_development_dependency "em-http-request", ">= 0.2.14" unless RUBY_PLATFORM =~ /java/
19
+ gem.add_development_dependency "curb", ">= 0.7.8" unless RUBY_PLATFORM =~ /java/
19
20
  end
20
21
  Jeweler::GemcutterTasks.new
21
22
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.5
1
+ 1.4.0
@@ -3,9 +3,12 @@ require 'singleton'
3
3
  require 'addressable/uri'
4
4
  require 'crack'
5
5
 
6
+ require 'webmock/deprecation'
7
+
6
8
  require 'webmock/http_lib_adapters/net_http'
7
9
  require 'webmock/http_lib_adapters/httpclient'
8
10
  require 'webmock/http_lib_adapters/patron'
11
+ require 'webmock/http_lib_adapters/curb'
9
12
  require 'webmock/http_lib_adapters/em_http_request'
10
13
 
11
14
  require 'webmock/errors'
@@ -20,8 +23,10 @@ require 'webmock/responses_sequence'
20
23
  require 'webmock/request_stub'
21
24
  require 'webmock/response'
22
25
 
26
+ require 'webmock/assertion_failure'
23
27
  require 'webmock/request_execution_verifier'
24
28
  require 'webmock/config'
25
29
  require 'webmock/callback_registry'
26
30
  require 'webmock/request_registry'
31
+ require 'webmock/api'
27
32
  require 'webmock/webmock'
@@ -1,13 +1,20 @@
1
1
  require 'webmock'
2
2
 
3
3
  # RSpec 1.x and 2.x compatibility
4
- begin
5
- require 'rspec'
4
+ if defined?(Rspec)
6
5
  RSPEC_NAMESPACE = RSPEC_CONFIGURER = Rspec
7
- rescue LoadError
8
- require 'spec'
6
+ elsif defined?(Spec)
9
7
  RSPEC_NAMESPACE = Spec
10
8
  RSPEC_CONFIGURER = Spec::Runner
9
+ else
10
+ begin
11
+ require 'rspec'
12
+ RSPEC_NAMESPACE = RSPEC_CONFIGURER = Rspec
13
+ rescue LoadError
14
+ require 'spec'
15
+ RSPEC_NAMESPACE = Spec
16
+ RSPEC_CONFIGURER = Spec::Runner
17
+ end
11
18
  end
12
19
 
13
20
  require 'webmock/adapters/rspec/request_pattern_matcher'
@@ -23,8 +30,4 @@ RSPEC_CONFIGURER.configure { |config|
23
30
  end
24
31
  }
25
32
 
26
- module WebMock
27
- def assertion_failure(message)
28
- raise RSPEC_NAMESPACE::Expectations::ExpectationNotMetError.new(message)
29
- end
30
- end
33
+ WebMock::AssertionFailure.error_class = RSPEC_NAMESPACE::Expectations::ExpectationNotMetError
@@ -15,10 +15,5 @@ class Test::Unit::TestCase
15
15
  end
16
16
  end
17
17
 
18
- module WebMock
19
- AssertionFailedError = Test::Unit::AssertionFailedError rescue MiniTest::Assertion # ruby1.9 compat
20
- def assertion_failure(message)
21
- raise AssertionFailedError.new(message)
22
- end
23
- end
24
18
 
19
+ WebMock::AssertionFailure.error_class = Test::Unit::AssertionFailedError rescue MiniTest::Assertion # ruby1.9 compat
@@ -0,0 +1,32 @@
1
+ module WebMock
2
+ module API
3
+ extend self
4
+
5
+ def stub_request(method, uri)
6
+ WebMock::RequestRegistry.instance.register_request_stub(WebMock::RequestStub.new(method, uri))
7
+ end
8
+
9
+ alias_method :stub_http_request, :stub_request
10
+
11
+ def a_request(method, uri)
12
+ WebMock::RequestPattern.new(method, uri)
13
+ end
14
+
15
+ class << self
16
+ alias :request :a_request
17
+ end
18
+
19
+ def assert_requested(method, uri, options = {}, &block)
20
+ expected_times_executed = options.delete(:times) || 1
21
+ request = WebMock::RequestPattern.new(method, uri, options).with(&block)
22
+ verifier = WebMock::RequestExecutionVerifier.new(request, expected_times_executed)
23
+ WebMock::AssertionFailure.failure(verifier.failure_message) unless verifier.matches?
24
+ end
25
+
26
+ def assert_not_requested(method, uri, options = {}, &block)
27
+ request = WebMock::RequestPattern.new(method, uri, options).with(&block)
28
+ verifier = WebMock::RequestExecutionVerifier.new(request, options.delete(:times))
29
+ WebMock::AssertionFailure.failure(verifier.negative_failure_message) unless verifier.does_not_match?
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ module WebMock
2
+ class AssertionFailure
3
+ class << self
4
+ attr_writer :error_class
5
+ @error_class = RuntimeError
6
+
7
+ def failure(message)
8
+ raise @error_class.new(message)
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ module WebMock
2
+ class Deprecation
3
+ class << self
4
+ def warning(message)
5
+ warn "WebMock deprecation warning: #{message}"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,260 @@
1
+ if defined?(Curl)
2
+
3
+ module Curl
4
+ class Easy
5
+ def curb_or_webmock
6
+ request_signature = build_request_signature
7
+ WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
8
+
9
+ if WebMock::RequestRegistry.instance.registered_request?(request_signature)
10
+ webmock_response = WebMock::RequestRegistry.instance.response_for_request(request_signature)
11
+ build_curb_response(webmock_response)
12
+ WebMock::CallbackRegistry.invoke_callbacks(
13
+ {:lib => :curb}, request_signature, webmock_response)
14
+ invoke_curb_callbacks
15
+ true
16
+ elsif WebMock.net_connect_allowed?(request_signature.uri)
17
+ res = yield
18
+ if WebMock::CallbackRegistry.any_callbacks?
19
+ webmock_response = build_webmock_response
20
+ WebMock::CallbackRegistry.invoke_callbacks(
21
+ {:lib => :curb, :real_request => true}, request_signature,
22
+ webmock_response)
23
+ end
24
+ res
25
+ else
26
+ raise WebMock::NetConnectNotAllowedError.new(request_signature)
27
+ end
28
+ end
29
+
30
+ def build_request_signature
31
+ method = @webmock_method.to_s.downcase.to_sym
32
+
33
+ uri = WebMock::Util::URI.heuristic_parse(self.url)
34
+ uri.path = uri.normalized_path.gsub("[^:]//","/")
35
+ uri.user = self.username
36
+ uri.password = self.password
37
+
38
+ request_body = case method
39
+ when :post
40
+ self.post_body || @post_body
41
+ when :put
42
+ @put_data
43
+ else
44
+ nil
45
+ end
46
+
47
+ request_signature = WebMock::RequestSignature.new(
48
+ method,
49
+ uri.to_s,
50
+ :body => request_body,
51
+ :headers => self.headers
52
+ )
53
+ request_signature
54
+ end
55
+
56
+ def build_curb_response(webmock_response)
57
+ raise Curl::Err::TimeoutError if webmock_response.should_timeout
58
+ webmock_response.raise_error_if_any
59
+
60
+ @body_str = webmock_response.body
61
+ @response_code = webmock_response.status[0]
62
+
63
+ @header_str = "HTTP/1.1 #{webmock_response.status[0]} #{webmock_response.status[1]}\r\n"
64
+ if webmock_response.headers
65
+ @header_str << webmock_response.headers.map do |k,v|
66
+ "#{k}: #{v.is_a?(Array) ? v.join(", ") : v}"
67
+ end.join("\r\n")
68
+ end
69
+ end
70
+
71
+ def invoke_curb_callbacks
72
+ @on_progress.call(0.0,1.0,0.0,1.0) if @on_progress
73
+ @on_header.call(self.header_str) if @on_header
74
+ @on_body.call(self.body_str) if @on_body
75
+ @on_complete.call(self) if @on_complete
76
+
77
+ case response_code
78
+ when 200..299
79
+ @on_success.call(self) if @on_success
80
+ when 500..599
81
+ @on_failure.call(self, self.response_code) if @on_failure
82
+ end
83
+ end
84
+
85
+ def build_webmock_response
86
+ status, headers = WebmockHelper.parse_header_string(self.header_str)
87
+
88
+ webmock_response = WebMock::Response.new
89
+ webmock_response.status = [self.response_code, status]
90
+ webmock_response.body = self.body_str
91
+ webmock_response.headers = headers
92
+ webmock_response
93
+ end
94
+
95
+ ###
96
+ ### Mocks of Curl::Easy methods below here.
97
+ ###
98
+
99
+ def http_with_webmock(method)
100
+ @webmock_method = method
101
+ curb_or_webmock do
102
+ http_without_webmock(method)
103
+ end
104
+ end
105
+ alias_method :http_without_webmock, :http
106
+ alias_method :http, :http_with_webmock
107
+
108
+ %w[ get head delete ].each do |verb|
109
+ define_method "http_#{verb}_with_webmock" do
110
+ @webmock_method = verb
111
+ curb_or_webmock do
112
+ send( "http_#{verb}_without_webmock" )
113
+ end
114
+ end
115
+
116
+ alias_method "http_#{verb}_without_webmock", "http_#{verb}"
117
+ alias_method "http_#{verb}", "http_#{verb}_with_webmock"
118
+ end
119
+
120
+ def http_put_with_webmock data
121
+ @webmock_method = :put
122
+ @put_data = data
123
+ curb_or_webmock do
124
+ http_put_without_webmock(data)
125
+ end
126
+ end
127
+ alias_method :http_put_without_webmock, :http_put
128
+ alias_method :http_put, :http_put_with_webmock
129
+
130
+ def http_post_with_webmock data
131
+ @webmock_method = :post
132
+ @post_body = data
133
+ curb_or_webmock do
134
+ http_post_without_webmock(data)
135
+ end
136
+ end
137
+ alias_method :http_post_without_webmock, :http_post
138
+ alias_method :http_post, :http_post_with_webmock
139
+
140
+
141
+ def perform_with_webmock
142
+ @webmock_method ||= :get
143
+ curb_or_webmock do
144
+ perform_without_webmock
145
+ end
146
+ end
147
+ alias :perform_without_webmock :perform
148
+ alias :perform :perform_with_webmock
149
+
150
+ def put_data_with_webmock= data
151
+ @webmock_method = :put
152
+ @put_data = data
153
+ self.put_data_without_webmock = data
154
+ end
155
+ alias_method :put_data_without_webmock=, :put_data=
156
+ alias_method :put_data=, :put_data_with_webmock=
157
+
158
+ def post_body_with_webmock= data
159
+ @webmock_method = :post
160
+ self.post_body_without_webmock = data
161
+ end
162
+ alias_method :post_body_without_webmock=, :post_body=
163
+ alias_method :post_body=, :post_body_with_webmock=
164
+
165
+ def delete_with_webmock= value
166
+ @webmock_method = :delete if value
167
+ self.delete_without_webmock = value
168
+ end
169
+ alias_method :delete_without_webmock=, :delete=
170
+ alias_method :delete=, :delete_with_webmock=
171
+
172
+ def head_with_webmock= value
173
+ @webmock_method = :head if value
174
+ self.head_without_webmock = value
175
+ end
176
+ alias_method :head_without_webmock=, :head=
177
+ alias_method :head=, :head_with_webmock=
178
+
179
+ def body_str_with_webmock
180
+ @body_str || body_str_without_webmock
181
+ end
182
+ alias :body_str_without_webmock :body_str
183
+ alias :body_str :body_str_with_webmock
184
+
185
+ def response_code_with_webmock
186
+ @response_code || response_code_without_webmock
187
+ end
188
+ alias :response_code_without_webmock :response_code
189
+ alias :response_code :response_code_with_webmock
190
+
191
+ def header_str_with_webmock
192
+ @header_str || header_str_without_webmock
193
+ end
194
+ alias :header_str_without_webmock :header_str
195
+ alias :header_str :header_str_with_webmock
196
+
197
+ %w[ success failure header body complete progress ].each do |callback|
198
+ class_eval <<-METHOD, __FILE__, __LINE__
199
+ def on_#{callback}_with_webmock &block
200
+ @on_#{callback} = block
201
+ on_#{callback}_without_webmock &block
202
+ end
203
+ METHOD
204
+ alias_method "on_#{callback}_without_webmock", "on_#{callback}"
205
+ alias_method "on_#{callback}", "on_#{callback}_with_webmock"
206
+ end
207
+
208
+ %w[ http_get http_head http_delete perform ].each do |method|
209
+ class_eval <<-METHOD, __FILE__, __LINE__
210
+ def self.#{method}(url, &block)
211
+ c = new
212
+ c.url = url
213
+ block.call(c) if block
214
+ c.send("#{method}")
215
+ c
216
+ end
217
+ METHOD
218
+ end
219
+
220
+ %w[ put post ].each do |verb|
221
+ class_eval <<-METHOD, __FILE__, __LINE__
222
+ def self.http_#{verb}(url, data, &block)
223
+ c = new
224
+ c.url = url
225
+ block.call(c) if block
226
+ c.send("http_#{verb}", data)
227
+ c
228
+ end
229
+ METHOD
230
+ end
231
+
232
+ module WebmockHelper
233
+ # Borrowed from Patron:
234
+ # http://github.com/toland/patron/blob/master/lib/patron/response.rb
235
+ def self.parse_header_string(header_string)
236
+ status, headers = nil, {}
237
+
238
+ header_string.split(/\r\n/).each do |header|
239
+ if header =~ %r|^HTTP/1.[01] \d\d\d (.*)|
240
+ status = $1
241
+ else
242
+ parts = header.split(':', 2)
243
+ unless parts.empty?
244
+ parts[1].strip! unless parts[1].nil?
245
+ if headers.has_key?(parts[0])
246
+ headers[parts[0]] = [headers[parts[0]]] unless headers[parts[0]].kind_of? Array
247
+ headers[parts[0]] << parts[1]
248
+ else
249
+ headers[parts[0]] = parts[1]
250
+ end
251
+ end
252
+ end
253
+ end
254
+
255
+ return status, headers
256
+ end
257
+ end
258
+ end
259
+ end
260
+ end