webmock 1.2.2 → 1.3.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.
- data/CHANGELOG.md +55 -0
- data/README.md +63 -4
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/lib/webmock.rb +3 -0
- data/lib/webmock/callback_registry.rb +35 -0
- data/lib/webmock/http_lib_adapters/em_http_request.rb +114 -0
- data/lib/webmock/http_lib_adapters/httpclient.rb +34 -7
- data/lib/webmock/http_lib_adapters/net_http.rb +24 -2
- data/lib/webmock/http_lib_adapters/net_http_response.rb +49 -0
- data/lib/webmock/http_lib_adapters/patron.rb +22 -3
- data/lib/webmock/request_pattern.rb +90 -17
- data/lib/webmock/response.rb +15 -7
- data/lib/webmock/util/uri.rb +18 -7
- data/lib/webmock/webmock.rb +8 -0
- data/spec/benchmark.rb +61 -0
- data/spec/em_http_request_spec.rb +29 -0
- data/spec/em_http_request_spec_helper.rb +64 -0
- data/spec/httpclient_spec_helper.rb +4 -0
- data/spec/net_http_spec.rb +46 -1
- data/spec/net_http_spec_helper.rb +4 -0
- data/spec/other_net_http_libs_spec.rb +1 -0
- data/spec/patron_spec_helper.rb +4 -0
- data/spec/request_pattern_spec.rb +143 -32
- data/spec/response_spec.rb +14 -0
- data/spec/spec_helper.rb +4 -1
- data/spec/vendor/crack/lib/crack.rb +0 -0
- data/spec/webmock_spec.rb +362 -13
- data/test/test_webmock.rb +2 -2
- data/webmock.gemspec +21 -5
- metadata +58 -11
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'webmock_spec'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
unless RUBY_PLATFORM =~ /java/
|
6
|
+
require 'em_http_request_spec_helper'
|
7
|
+
|
8
|
+
describe "Webmock with EM::HttpRequest" do
|
9
|
+
include EMHttpRequestSpecHelper
|
10
|
+
|
11
|
+
it_should_behave_like "WebMock"
|
12
|
+
|
13
|
+
it "should work with streaming" do
|
14
|
+
stub_http_request(:get, "www.example.com").to_return(:body => "abc")
|
15
|
+
response = ""
|
16
|
+
EM.run {
|
17
|
+
http = EventMachine::HttpRequest.new('http://www.example.com/').get
|
18
|
+
http.stream { |chunk| response = chunk; EM.stop }
|
19
|
+
}
|
20
|
+
response.should == "abc"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should work with optional query params" do
|
24
|
+
stub_http_request(:get, "www.example.com/?x=3&a[]=b&a[]=c").to_return(:body => "abc")
|
25
|
+
http_request(:get, "http://www.example.com/?x=3", :query => {"a" => ["b", "c"]}).body.should == "abc"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module EMHttpRequestSpecHelper
|
2
|
+
|
3
|
+
def failed
|
4
|
+
EventMachine.stop
|
5
|
+
fail
|
6
|
+
end
|
7
|
+
|
8
|
+
def http_request(method, uri, options = {}, &block)
|
9
|
+
response = nil
|
10
|
+
error = nil
|
11
|
+
uri = Addressable::URI.heuristic_parse(uri)
|
12
|
+
EventMachine.run {
|
13
|
+
request = EventMachine::HttpRequest.new("#{uri.omit(:userinfo).normalize.to_s}")
|
14
|
+
http = request.send(:setup_request, method, {
|
15
|
+
:timeout => 2,
|
16
|
+
:body => options[:body],
|
17
|
+
:query => options[:query],
|
18
|
+
'authorization' => [uri.user, uri.password],
|
19
|
+
:head => options[:headers]}, &block)
|
20
|
+
http.errback {
|
21
|
+
error = http.errors
|
22
|
+
failed
|
23
|
+
}
|
24
|
+
headers = {}
|
25
|
+
if http.response_header
|
26
|
+
http.response_header.each do |k,v|
|
27
|
+
v = v.join(", ") if v.is_a?(Array)
|
28
|
+
headers[k] = v
|
29
|
+
end
|
30
|
+
end
|
31
|
+
http.callback {
|
32
|
+
response = OpenStruct.new({
|
33
|
+
:body => http.response,
|
34
|
+
:headers => WebMock::Util::Headers.normalize_headers(headers),
|
35
|
+
:message => http.response_header.http_reason,
|
36
|
+
:status => http.response_header.status.to_s
|
37
|
+
})
|
38
|
+
EventMachine.stop
|
39
|
+
}
|
40
|
+
}
|
41
|
+
raise error if error
|
42
|
+
response
|
43
|
+
end
|
44
|
+
|
45
|
+
def client_timeout_exception_class
|
46
|
+
"WebMock timeout error"
|
47
|
+
end
|
48
|
+
|
49
|
+
def connection_refused_exception_class
|
50
|
+
""
|
51
|
+
end
|
52
|
+
|
53
|
+
def default_client_request_headers(request_method = nil, has_body = false)
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def setup_expectations_for_real_request(options = {})
|
58
|
+
end
|
59
|
+
|
60
|
+
def http_library
|
61
|
+
:em_http_request
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
data/spec/net_http_spec.rb
CHANGED
@@ -49,9 +49,54 @@ describe "Webmock with Net:HTTP" do
|
|
49
49
|
it "should handle real requests with readable body" do
|
50
50
|
WebMock.allow_net_connect!
|
51
51
|
req = Net::HTTP::Post.new("/")
|
52
|
-
Net::HTTP.start("www.example.com") {|http|
|
52
|
+
Net::HTTP.start("www.example.com") {|http|
|
53
53
|
http.request(req, StringIO.new("my_params"))
|
54
54
|
}.body.should =~ /Example Web Page/
|
55
55
|
end
|
56
56
|
|
57
|
+
describe 'after_request callback support' do
|
58
|
+
let(:expected_body_regex) { /You have reached this web page by typing.*example\.com/ }
|
59
|
+
|
60
|
+
before(:each) do
|
61
|
+
WebMock.allow_net_connect!
|
62
|
+
@callback_invocation_count = 0
|
63
|
+
WebMock.after_request do |_, response|
|
64
|
+
@callback_invocation_count += 1
|
65
|
+
@callback_response = response
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
after(:each) do
|
70
|
+
WebMock.reset_callbacks
|
71
|
+
end
|
72
|
+
|
73
|
+
def perform_get_with_returning_block
|
74
|
+
http_request(:get, "http://www.example.com/") do |response|
|
75
|
+
return response.body
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should support the after_request callback on an request with block and read_body" do
|
80
|
+
response_body = ''
|
81
|
+
http_request(:get, "http://www.example.com/") do |response|
|
82
|
+
response.read_body { |fragment| response_body << fragment }
|
83
|
+
end
|
84
|
+
response_body.should =~ expected_body_regex
|
85
|
+
|
86
|
+
@callback_response.body.should == response_body
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should support the after_request callback on a request with a returning block" do
|
90
|
+
response_body = perform_get_with_returning_block
|
91
|
+
response_body.should =~ expected_body_regex
|
92
|
+
@callback_response.should be_instance_of(WebMock::Response)
|
93
|
+
@callback_response.body.should == response_body
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should only invoke the after_request callback once, even for a recursive post request" do
|
97
|
+
Net::HTTP.new('example.com', 80).post('/', nil)
|
98
|
+
@callback_invocation_count.should == 1
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
57
102
|
end
|
@@ -79,4 +79,8 @@ module NetHTTPSpecHelper
|
|
79
79
|
socket.should_receive(read_method).once.and_return("HTTP/1.1 #{options[:response_code]} #{options[:response_message]}\nContent-Length: #{options[:response_body].length}\n\n#{options[:response_body]}")
|
80
80
|
socket.should_receive(read_method).any_number_of_times.and_raise(EOFError)
|
81
81
|
end
|
82
|
+
|
83
|
+
def http_library
|
84
|
+
:net_http
|
85
|
+
end
|
82
86
|
end
|
@@ -5,6 +5,7 @@ describe "loading other Net::HTTP based libraries" do
|
|
5
5
|
def capture_output_from_requiring(libs, additional_code = "")
|
6
6
|
requires = libs.map { |lib| "require '#{lib}'" }
|
7
7
|
requires << " require 'addressable/uri'"
|
8
|
+
requires << " require 'crack'"
|
8
9
|
requires = requires.join("; ")
|
9
10
|
webmock_dir = "#{File.dirname(__FILE__)}/../lib"
|
10
11
|
vendor_dirs = Dir["#{File.dirname(__FILE__)}/vendor/*/lib"]
|
data/spec/patron_spec_helper.rb
CHANGED
@@ -5,13 +5,18 @@ describe RequestPattern do
|
|
5
5
|
it "should report string describing itself" do
|
6
6
|
RequestPattern.new(:get, "www.example.com",
|
7
7
|
:body => "abc", :headers => {'A' => 'a', 'B' => 'b'}).to_s.should ==
|
8
|
-
"GET http://www.example.com/ with body
|
8
|
+
"GET http://www.example.com/ with body \"abc\" with headers {'A'=>'a', 'B'=>'b'}"
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should report string describing itself with block" do
|
12
12
|
RequestPattern.new(:get, "www.example.com",
|
13
13
|
:body => "abc", :headers => {'A' => 'a', 'B' => 'b'}).with {|req| true}.to_s.should ==
|
14
|
-
"GET http://www.example.com/ with body
|
14
|
+
"GET http://www.example.com/ with body \"abc\" with headers {'A'=>'a', 'B'=>'b'} with given block"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should report string describing itself with query params" do
|
18
|
+
RequestPattern.new(:get, /.*example.*/, :query => {'a' => ['b', 'c']}).to_s.should ==
|
19
|
+
"GET /.*example.*/ with query params {\"a\"=>[\"b\", \"c\"]}"
|
15
20
|
end
|
16
21
|
|
17
22
|
describe "with" do
|
@@ -119,48 +124,154 @@ describe RequestPattern do
|
|
119
124
|
|
120
125
|
end
|
121
126
|
|
127
|
+
describe "when matching requests on query params" do
|
122
128
|
|
129
|
+
it "should match request query params even if uri is declared as regexp" do
|
130
|
+
RequestPattern.new(:get, /.*example.*/, :query => {"a" => ["b", "c"]}).
|
131
|
+
should match(RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
|
132
|
+
end
|
123
133
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
134
|
+
it "should match request query params if uri is declared as regexp but params don't match" do
|
135
|
+
RequestPattern.new(:get, /.*example.*/, :query => {"x" => ["b", "c"]}).
|
136
|
+
should_not match(RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
|
137
|
+
end
|
128
138
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
139
|
+
it "should match for query params are the same as declared in hash" do
|
140
|
+
RequestPattern.new(:get, "www.example.com", :query => {"a" => ["b", "c"]}).
|
141
|
+
should match(RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should not match for query params are different than the declared in hash" do
|
145
|
+
RequestPattern.new(:get, "www.example.com", :query => {"a" => ["b", "c"]}).
|
146
|
+
should_not match(RequestSignature.new(:get, "www.example.com?x[]=b&a[]=c"))
|
147
|
+
end
|
133
148
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
149
|
+
it "should match for query params are the same as declared as string" do
|
150
|
+
RequestPattern.new(:get, "www.example.com", :query => "a[]=b&a[]=c").
|
151
|
+
should match(RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c"))
|
152
|
+
end
|
138
153
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
154
|
+
it "should match for query params are the same as declared both in query option or url" do
|
155
|
+
RequestPattern.new(:get, "www.example.com/?x=3", :query => "a[]=b&a[]=c").
|
156
|
+
should match(RequestSignature.new(:get, "www.example.com/?x=3&a[]=b&a[]=c"))
|
157
|
+
end
|
143
158
|
|
144
|
-
it "should match if pattern doesn't have specified body" do
|
145
|
-
RequestPattern.new(:get, "www.example.com").
|
146
|
-
should match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
|
147
159
|
end
|
148
160
|
|
149
|
-
|
150
|
-
RequestPattern.new(:get, "www.example.com", :body => nil).
|
151
|
-
should_not match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
|
152
|
-
end
|
161
|
+
describe "when matching requests with body" do
|
153
162
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
163
|
+
it "should match if request body and body pattern are the same" do
|
164
|
+
RequestPattern.new(:get, "www.example.com", :body => "abc").
|
165
|
+
should match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
|
166
|
+
end
|
158
167
|
|
159
|
-
|
160
|
-
|
161
|
-
|
168
|
+
it "should match if request body matches regexp" do
|
169
|
+
RequestPattern.new(:get, "www.example.com", :body => /^abc$/).
|
170
|
+
should match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should not match if body pattern is different than request body" do
|
174
|
+
RequestPattern.new(:get, "www.example.com", :body => "def").
|
175
|
+
should_not match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should not match if request body doesn't match regexp pattern" do
|
179
|
+
RequestPattern.new(:get, "www.example.com", :body => /^abc$/).
|
180
|
+
should_not match(RequestSignature.new(:get, "www.example.com", :body => "xabc"))
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should match if pattern doesn't have specified body" do
|
184
|
+
RequestPattern.new(:get, "www.example.com").
|
185
|
+
should match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should not match if pattern has body specified as nil but request body is not empty" do
|
189
|
+
RequestPattern.new(:get, "www.example.com", :body => nil).
|
190
|
+
should_not match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should not match if pattern has empty body but request body is not empty" do
|
194
|
+
RequestPattern.new(:get, "www.example.com", :body => "").
|
195
|
+
should_not match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should not match if pattern has body specified but request has no body" do
|
199
|
+
RequestPattern.new(:get, "www.example.com", :body => "abc").
|
200
|
+
should_not match(RequestSignature.new(:get, "www.example.com"))
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "when body in pattern is declared as a hash" do
|
204
|
+
let(:body_hash) { {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']}} }
|
205
|
+
|
206
|
+
describe "for request with url encoded body" do
|
207
|
+
it "should match when hash matches body" do
|
208
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
209
|
+
should match(RequestSignature.new(:post, "www.example.com", :body => 'a=1&c[d][]=e&c[d][]=f&b=five'))
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should match when hash matches body in different order of params" do
|
213
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
214
|
+
should match(RequestSignature.new(:post, "www.example.com", :body => 'a=1&c[d][]=e&b=five&c[d][]=f'))
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should not match when hash doesn't match url encoded body" do
|
218
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
219
|
+
should_not match(RequestSignature.new(:post, "www.example.com", :body => 'c[d][]=f&a=1&c[d][]=e'))
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should not match when body is not url encoded" do
|
223
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
224
|
+
should_not match(RequestSignature.new(:post, "www.example.com", :body => 'foo bar'))
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "for request with json body and content type is set to json" do
|
230
|
+
it "should match when hash matches body" do
|
231
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
232
|
+
should match(RequestSignature.new(:post, "www.example.com", :headers => {:content_type => 'application/json'},
|
233
|
+
:body => "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}"))
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should match if hash matches body in different form" do
|
237
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
238
|
+
should match(RequestSignature.new(:post, "www.example.com", :headers => {:content_type => 'application/json'},
|
239
|
+
:body => "{\"a\":\"1\",\"b\":\"five\",\"c\":{\"d\":[\"e\",\"f\"]}}"))
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should not match when body is not json" do
|
243
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
244
|
+
should_not match(RequestSignature.new(:post, "www.example.com",
|
245
|
+
:headers => {:content_type => 'application/json'}, :body => "foo bar"))
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe "for request with xml body and content type is set to xml" do
|
250
|
+
let(:body_hash) { {"opt" => {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']}}} }
|
251
|
+
|
252
|
+
it "should match when hash matches body" do
|
253
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
254
|
+
should match(RequestSignature.new(:post, "www.example.com", :headers => {:content_type => 'application/xml'},
|
255
|
+
:body => "<opt a=\"1\" b=\"five\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n"))
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should match if hash matches body in different form" do
|
259
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
260
|
+
should match(RequestSignature.new(:post, "www.example.com", :headers => {:content_type => 'application/xml'},
|
261
|
+
:body => "<opt b=\"five\" a=\"1\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n"))
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should not match when body is not xml" do
|
265
|
+
RequestPattern.new(:post, 'www.example.com', :body => body_hash).
|
266
|
+
should_not match(RequestSignature.new(:post, "www.example.com",
|
267
|
+
:headers => {:content_type => 'application/xml'}, :body => "foo bar"))
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
162
271
|
end
|
163
272
|
|
273
|
+
|
274
|
+
|
164
275
|
it "should match if pattern and request have the same headers" do
|
165
276
|
RequestPattern.new(:get, "www.example.com", :headers => {'Content-Type' => 'image/jpeg'}).
|
166
277
|
should match(RequestSignature.new(:get, "www.example.com", :headers => {'Content-Type' => 'image/jpeg'}))
|
data/spec/response_spec.rb
CHANGED
@@ -58,6 +58,20 @@ describe Response do
|
|
58
58
|
@response.raise_error_if_any
|
59
59
|
}.should raise_error(ArgumentError, "Exception from WebMock")
|
60
60
|
end
|
61
|
+
|
62
|
+
it "should raise error if any assigned as instance" do
|
63
|
+
@response = Response.new(:exception => ArgumentError.new("hello world"))
|
64
|
+
lambda {
|
65
|
+
@response.raise_error_if_any
|
66
|
+
}.should raise_error(ArgumentError, "hello world")
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should raise error if any assigned as string" do
|
70
|
+
@response = Response.new(:exception => "hello world")
|
71
|
+
lambda {
|
72
|
+
@response.raise_error_if_any
|
73
|
+
}.should raise_error("hello world")
|
74
|
+
end
|
61
75
|
|
62
76
|
it "should not raise error if no error assigned" do
|
63
77
|
@response.raise_error_if_any
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'httpclient'
|
3
|
-
|
3
|
+
unless RUBY_PLATFORM =~ /java/
|
4
|
+
require 'patron'
|
5
|
+
require 'em-http'
|
6
|
+
end
|
4
7
|
|
5
8
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
9
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
File without changes
|
data/spec/webmock_spec.rb
CHANGED
@@ -16,6 +16,7 @@ describe "WebMock version" do
|
|
16
16
|
|
17
17
|
end
|
18
18
|
|
19
|
+
|
19
20
|
describe "WebMock", :shared => true do
|
20
21
|
before(:each) do
|
21
22
|
WebMock.disable_net_connect!
|
@@ -39,9 +40,10 @@ describe "WebMock", :shared => true do
|
|
39
40
|
setup_expectations_for_real_example_com_request(
|
40
41
|
:host => "www.paypal.com",
|
41
42
|
:port => 443,
|
43
|
+
:path => "/uk/cgi-bin/webscr",
|
42
44
|
:response_body => "hello paypal"
|
43
45
|
)
|
44
|
-
http_request(:get, "https://www.paypal.com/").
|
46
|
+
http_request(:get, "https://www.paypal.com/uk/cgi-bin/webscr").
|
45
47
|
body.should =~ /.*paypal.*/
|
46
48
|
end
|
47
49
|
|
@@ -116,7 +118,26 @@ describe "WebMock", :shared => true do
|
|
116
118
|
stub_http_request(:get, /.*x=ab c.*/).to_return(:body => "abc")
|
117
119
|
http_request(:get, "http://www.example.com/?#{ESCAPED_PARAMS}").body.should == "abc"
|
118
120
|
end
|
121
|
+
|
122
|
+
end
|
119
123
|
|
124
|
+
describe "on query params" do
|
125
|
+
|
126
|
+
it "should match the request by query params declared as a hash" do
|
127
|
+
stub_http_request(:get, "www.example.com").with(:query => {"a" => ["b", "c"]}).to_return(:body => "abc")
|
128
|
+
http_request(:get, "http://www.example.com/?a[]=b&a[]=c").body.should == "abc"
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should match the request by query declared as a string" do
|
132
|
+
stub_http_request(:get, "www.example.com").with(:query => "a[]=b&a[]=c").to_return(:body => "abc")
|
133
|
+
http_request(:get, "http://www.example.com/?a[]=b&a[]=c").body.should == "abc"
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should match the request by query params declared both in uri and query option" do
|
137
|
+
stub_http_request(:get, "www.example.com/?x=3").with(:query => {"a" => ["b", "c"]}).to_return(:body => "abc")
|
138
|
+
http_request(:get, "http://www.example.com/?x=3&a[]=b&a[]=c").body.should == "abc"
|
139
|
+
end
|
140
|
+
|
120
141
|
end
|
121
142
|
|
122
143
|
describe "on method" do
|
@@ -180,6 +201,78 @@ describe "WebMock", :shared => true do
|
|
180
201
|
end
|
181
202
|
|
182
203
|
end
|
204
|
+
|
205
|
+
describe "when body is declared as a hash" do
|
206
|
+
before(:each) do
|
207
|
+
stub_http_request(:post, "www.example.com").
|
208
|
+
with(:body => {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']} })
|
209
|
+
end
|
210
|
+
|
211
|
+
describe "for request with url encoded body" do
|
212
|
+
|
213
|
+
it "should match request if hash matches body" do
|
214
|
+
http_request(
|
215
|
+
:post, "http://www.example.com/",
|
216
|
+
:body => 'a=1&c[d][]=e&c[d][]=f&b=five').status.should == "200"
|
217
|
+
end
|
218
|
+
|
219
|
+
it "should match request if hash matches body in different order of params" do
|
220
|
+
http_request(
|
221
|
+
:post, "http://www.example.com/",
|
222
|
+
:body => 'a=1&c[d][]=e&b=five&c[d][]=f').status.should == "200"
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should not match if hash doesn't match url encoded body" do
|
226
|
+
lambda {
|
227
|
+
http_request(
|
228
|
+
:post, "http://www.example.com/",
|
229
|
+
:body => 'c[d][]=f&a=1&c[d][]=e').status.should == "200"
|
230
|
+
}.should raise_error(WebMock::NetConnectNotAllowedError, client_specific_request_string(
|
231
|
+
"Real HTTP connections are disabled. Unregistered request: "+
|
232
|
+
"POST http://www.example.com/ with body 'c[d][]=f&a=1&c[d][]=e'"))
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
describe "for request with json body and content type is set to json" do
|
239
|
+
|
240
|
+
it "should match if hash matches body" do
|
241
|
+
http_request(
|
242
|
+
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
|
243
|
+
:body => "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}").status.should == "200"
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should match if hash matches body in different form" do
|
247
|
+
http_request(
|
248
|
+
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
|
249
|
+
:body => "{\"a\":\"1\",\"b\":\"five\",\"c\":{\"d\":[\"e\",\"f\"]}}").status.should == "200"
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "for request with xml body and content type is set to xml" do
|
255
|
+
before(:each) do
|
256
|
+
WebMock.reset_webmock
|
257
|
+
stub_http_request(:post, "www.example.com").
|
258
|
+
with(:body => { "opt" => {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']} }})
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should match if hash matches body" do
|
262
|
+
http_request(
|
263
|
+
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/xml'},
|
264
|
+
:body => "<opt a=\"1\" b=\"five\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n").status.should == "200"
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should match if hash matches body in different form" do
|
268
|
+
http_request(
|
269
|
+
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/xml'},
|
270
|
+
:body => "<opt b=\"five\" a=\"1\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n").status.should == "200"
|
271
|
+
end
|
272
|
+
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
183
276
|
|
184
277
|
end
|
185
278
|
|
@@ -351,6 +444,20 @@ describe "WebMock", :shared => true do
|
|
351
444
|
http_request(:get, "http://www.example.com/")
|
352
445
|
}.should raise_error(MyException, "Exception from WebMock")
|
353
446
|
end
|
447
|
+
|
448
|
+
it "should raise exception if declared in a stubbed response as exception instance" do
|
449
|
+
stub_http_request(:get, "www.example.com").to_raise(MyException.new("hello world"))
|
450
|
+
lambda {
|
451
|
+
http_request(:get, "http://www.example.com/")
|
452
|
+
}.should raise_error(MyException, "hello world")
|
453
|
+
end
|
454
|
+
|
455
|
+
it "should raise exception if declared in a stubbed response as exception instance" do
|
456
|
+
stub_http_request(:get, "www.example.com").to_raise("hello world")
|
457
|
+
lambda {
|
458
|
+
http_request(:get, "http://www.example.com/")
|
459
|
+
}.should raise_error("hello world")
|
460
|
+
end
|
354
461
|
|
355
462
|
it "should raise exception if declared in a stubbed response after returning declared response" do
|
356
463
|
stub_http_request(:get, "www.example.com").to_return(:body => "abc").then.to_raise(MyException)
|
@@ -804,6 +911,35 @@ describe "WebMock", :shared => true do
|
|
804
911
|
request(:get, /.*example.*/).should have_been_made
|
805
912
|
}.should_not raise_error
|
806
913
|
end
|
914
|
+
|
915
|
+
end
|
916
|
+
|
917
|
+
describe "when matching requests with query params" do
|
918
|
+
before(:each) do
|
919
|
+
stub_http_request(:any, /.*example.*/)
|
920
|
+
end
|
921
|
+
|
922
|
+
it "should pass if the request was executed with query params declared in a hash in query option" do
|
923
|
+
lambda {
|
924
|
+
http_request(:get, "http://www.example.com/?a[]=b&a[]=c")
|
925
|
+
request(:get, "www.example.com").with(:query => {"a" => ["b", "c"]}).should have_been_made
|
926
|
+
}.should_not raise_error
|
927
|
+
end
|
928
|
+
|
929
|
+
it "should pass if the request was executed with query params declared as string in query option" do
|
930
|
+
lambda {
|
931
|
+
http_request(:get, "http://www.example.com/?a[]=b&a[]=c")
|
932
|
+
request(:get, "www.example.com").with(:query => "a[]=b&a[]=c").should have_been_made
|
933
|
+
}.should_not raise_error
|
934
|
+
end
|
935
|
+
|
936
|
+
it "should pass if the request was executed with query params both in uri and in query option" do
|
937
|
+
lambda {
|
938
|
+
http_request(:get, "http://www.example.com/?x=3&a[]=b&a[]=c")
|
939
|
+
request(:get, "www.example.com/?x=3").with(:query => {"a" => ["b", "c"]}).should have_been_made
|
940
|
+
}.should_not raise_error
|
941
|
+
end
|
942
|
+
|
807
943
|
end
|
808
944
|
|
809
945
|
it "should fail if requested more times than expected" do
|
@@ -840,22 +976,99 @@ describe "WebMock", :shared => true do
|
|
840
976
|
http_request(:get, "http://www.example.com/", :body => "abc")
|
841
977
|
request(:get, "www.example.com").
|
842
978
|
with(:body => "def").should have_been_made
|
843
|
-
}.should fail_with(
|
979
|
+
}.should fail_with('The request GET http://www.example.com/ with body "def" was expected to execute 1 time but it executed 0 times')
|
844
980
|
end
|
845
981
|
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
982
|
+
describe "when expected body is declared as regexp" do
|
983
|
+
|
984
|
+
it "should succeed if request was executed with the same body" do
|
985
|
+
lambda {
|
986
|
+
http_request(:post, "http://www.example.com/", :body => "abc")
|
987
|
+
request(:post, "www.example.com").with(:body => /^abc$/).should have_been_made
|
988
|
+
}.should_not raise_error
|
989
|
+
end
|
990
|
+
|
991
|
+
it "should fail if request was executed with different body" do
|
992
|
+
lambda {
|
993
|
+
http_request(:get, "http://www.example.com/", :body => /^abc/)
|
994
|
+
request(:get, "www.example.com").
|
995
|
+
with(:body => "xabc").should have_been_made
|
996
|
+
}.should fail_with('The request GET http://www.example.com/ with body "xabc" was expected to execute 1 time but it executed 0 times')
|
997
|
+
end
|
998
|
+
|
851
999
|
end
|
1000
|
+
|
1001
|
+
describe "when expected body is declared as a hash" do
|
1002
|
+
let(:body_hash) { {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']}} }
|
1003
|
+
let(:fail_message) {'The request POST http://www.example.com/ with body {"a"=>"1", "b"=>"five", "c"=>{"d"=>["e", "f"]}} was expected to execute 1 time but it executed 0 times'}
|
852
1004
|
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
1005
|
+
describe "when request is executed with url encoded body matching hash" do
|
1006
|
+
|
1007
|
+
it "should succeed" do
|
1008
|
+
lambda {
|
1009
|
+
http_request(:post, "http://www.example.com/", :body => 'a=1&c[d][]=e&c[d][]=f&b=five')
|
1010
|
+
request(:post, "www.example.com").with(:body => body_hash).should have_been_made
|
1011
|
+
}.should_not raise_error
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
it "should succeed if url encoded params have different order" do
|
1015
|
+
lambda {
|
1016
|
+
http_request(:post, "http://www.example.com/", :body => 'a=1&c[d][]=e&b=five&c[d][]=f')
|
1017
|
+
request(:post, "www.example.com").with(:body => body_hash).should have_been_made
|
1018
|
+
}.should_not raise_error
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
it "should fail if request is executed with url encoded body not matching hash" do
|
1022
|
+
lambda {
|
1023
|
+
http_request(:post, "http://www.example.com/", :body => 'c[d][]=f&a=1&c[d][]=e')
|
1024
|
+
request(:post, "www.example.com").with(:body => body_hash).should have_been_made
|
1025
|
+
}.should fail_with(fail_message)
|
1026
|
+
end
|
1027
|
+
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
describe "when request is executed with json body matching hash and content type is set to json" do
|
1031
|
+
|
1032
|
+
it "should succeed" do
|
1033
|
+
lambda {
|
1034
|
+
http_request(:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
|
1035
|
+
:body => "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}")
|
1036
|
+
request(:post, "www.example.com").with(:body => body_hash).should have_been_made
|
1037
|
+
}.should_not raise_error
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
it "should succeed if json body is in different form" do
|
1041
|
+
lambda {
|
1042
|
+
http_request(:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
|
1043
|
+
:body => "{\"a\":\"1\",\"b\":\"five\",\"c\":{\"d\":[\"e\",\"f\"]}}")
|
1044
|
+
request(:post, "www.example.com").with(:body => body_hash).should have_been_made
|
1045
|
+
}.should_not raise_error
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
end
|
1049
|
+
|
1050
|
+
|
1051
|
+
describe "when request is executed with xml body matching hash and content type is set to xml" do
|
1052
|
+
let(:body_hash) { { "opt" => {:a => "1", :b => 'five', 'c' => {'d' => ['e', 'f']}} }}
|
1053
|
+
|
1054
|
+
it "should succeed" do
|
1055
|
+
lambda {
|
1056
|
+
http_request(:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/xml'},
|
1057
|
+
:body => "<opt a=\"1\" b=\"five\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n")
|
1058
|
+
request(:post, "www.example.com").with(:body => body_hash).should have_been_made
|
1059
|
+
}.should_not raise_error
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
it "should succeed if xml body is in different form" do
|
1063
|
+
lambda {
|
1064
|
+
http_request(:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/xml'},
|
1065
|
+
:body => "<opt b=\"five\" a=\"1\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n")
|
1066
|
+
request(:post, "www.example.com").with(:body => body_hash).should have_been_made
|
1067
|
+
}.should_not raise_error
|
1068
|
+
end
|
1069
|
+
|
1070
|
+
end
|
1071
|
+
|
859
1072
|
end
|
860
1073
|
|
861
1074
|
it "should succeed if request was executed with the same headers" do
|
@@ -1137,4 +1350,140 @@ describe "WebMock", :shared => true do
|
|
1137
1350
|
|
1138
1351
|
end
|
1139
1352
|
|
1353
|
+
|
1354
|
+
describe "callbacks" do
|
1355
|
+
|
1356
|
+
describe "after_request" do
|
1357
|
+
before(:each) do
|
1358
|
+
WebMock.reset_callbacks
|
1359
|
+
stub_request(:get, "http://www.example.com")
|
1360
|
+
end
|
1361
|
+
|
1362
|
+
it "should not invoke callback unless request is made" do
|
1363
|
+
WebMock.after_request {
|
1364
|
+
@called = true
|
1365
|
+
}
|
1366
|
+
@called.should == nil
|
1367
|
+
end
|
1368
|
+
|
1369
|
+
it "should invoke a callback after request is made" do
|
1370
|
+
WebMock.after_request {
|
1371
|
+
@called = true
|
1372
|
+
}
|
1373
|
+
http_request(:get, "http://www.example.com/")
|
1374
|
+
@called.should == true
|
1375
|
+
end
|
1376
|
+
|
1377
|
+
it "should not invoke a callback if specific http library should be ignored" do
|
1378
|
+
WebMock.after_request(:except => [http_library()]) {
|
1379
|
+
@called = true
|
1380
|
+
}
|
1381
|
+
http_request(:get, "http://www.example.com/")
|
1382
|
+
@called.should == nil
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
it "should invoke a callback even if other http libraries should be ignored" do
|
1386
|
+
WebMock.after_request(:except => [:other_lib]) {
|
1387
|
+
@called = true
|
1388
|
+
}
|
1389
|
+
http_request(:get, "http://www.example.com/")
|
1390
|
+
@called.should == true
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
it "should pass request signature to the callback" do
|
1394
|
+
WebMock.after_request(:except => [:other_lib]) do |request_signature, _|
|
1395
|
+
@request_signature = request_signature
|
1396
|
+
end
|
1397
|
+
http_request(:get, "http://www.example.com/")
|
1398
|
+
@request_signature.uri.to_s.should == "http://www.example.com:80/"
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
describe "passing response to callback" do
|
1402
|
+
|
1403
|
+
describe "for stubbed requests" do
|
1404
|
+
before(:each) do
|
1405
|
+
stub_request(:get, "http://www.example.com").
|
1406
|
+
to_return(
|
1407
|
+
:status => ["200", "hello"],
|
1408
|
+
:headers => {'Content-Length' => '666', 'Hello' => 'World'},
|
1409
|
+
:body => "foo bar"
|
1410
|
+
)
|
1411
|
+
WebMock.after_request(:except => [:other_lib]) do |_, response|
|
1412
|
+
@response = response
|
1413
|
+
end
|
1414
|
+
http_request(:get, "http://www.example.com/")
|
1415
|
+
end
|
1416
|
+
|
1417
|
+
it "should pass response with status and message" do
|
1418
|
+
@response.status.should == ["200", "hello"]
|
1419
|
+
end
|
1420
|
+
|
1421
|
+
it "should pass response with headers" do
|
1422
|
+
@response.headers.should == {
|
1423
|
+
'Content-Length' => '666',
|
1424
|
+
'Hello' => 'World'
|
1425
|
+
}
|
1426
|
+
end
|
1427
|
+
|
1428
|
+
it "should pass response with body" do
|
1429
|
+
@response.body.should == "foo bar"
|
1430
|
+
end
|
1431
|
+
|
1432
|
+
end
|
1433
|
+
|
1434
|
+
describe "for real requests" do
|
1435
|
+
before(:each) do
|
1436
|
+
WebMock.reset_webmock
|
1437
|
+
WebMock.allow_net_connect!
|
1438
|
+
WebMock.after_request(:except => [:other_lib]) do |_, response|
|
1439
|
+
@response = response
|
1440
|
+
end
|
1441
|
+
http_request(:get, "http://www.example.com/")
|
1442
|
+
end
|
1443
|
+
|
1444
|
+
it "should pass response with status and message" do
|
1445
|
+
@response.status[0].should == 200
|
1446
|
+
@response.status[1].should == "OK"
|
1447
|
+
end
|
1448
|
+
|
1449
|
+
it "should pass response with headers" do
|
1450
|
+
@response.headers["Content-Length"].should == "574"
|
1451
|
+
end
|
1452
|
+
|
1453
|
+
it "should pass response with body" do
|
1454
|
+
@response.body.size.should == 574
|
1455
|
+
end
|
1456
|
+
|
1140
1457
|
end
|
1458
|
+
|
1459
|
+
end
|
1460
|
+
|
1461
|
+
it "should invoke multiple callbacks in order of their declarations" do
|
1462
|
+
WebMock.after_request { @called = 1 }
|
1463
|
+
WebMock.after_request { @called += 1 }
|
1464
|
+
http_request(:get, "http://www.example.com/")
|
1465
|
+
@called.should == 2
|
1466
|
+
end
|
1467
|
+
|
1468
|
+
it "should invoke callbacks only for real requests if requested" do
|
1469
|
+
WebMock.after_request(:real_requests_only => true) { @called = true }
|
1470
|
+
http_request(:get, "http://www.example.com/")
|
1471
|
+
@called.should == nil
|
1472
|
+
WebMock.allow_net_connect!
|
1473
|
+
http_request(:get, "http://www.example.net/")
|
1474
|
+
@called.should == true
|
1475
|
+
end
|
1476
|
+
|
1477
|
+
it "should clear all declared callbacks on reset callbacks" do
|
1478
|
+
WebMock.after_request { @called = 1 }
|
1479
|
+
WebMock.reset_callbacks
|
1480
|
+
stub_request(:get, "http://www.example.com")
|
1481
|
+
http_request(:get, "http://www.example.com/")
|
1482
|
+
@called.should == nil
|
1483
|
+
end
|
1484
|
+
|
1485
|
+
end
|
1486
|
+
|
1487
|
+
end
|
1488
|
+
|
1489
|
+
end
|