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.
@@ -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
@@ -75,5 +75,9 @@ module HTTPClientSpecHelper
75
75
 
76
76
  socket.should_receive(:readpartial).any_number_of_times.and_raise(EOFError)
77
77
  end
78
+
79
+ def http_library
80
+ :http_client
81
+ end
78
82
 
79
83
  end
@@ -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"]
@@ -47,4 +47,8 @@ module PatronSpecHelper
47
47
  #TODO
48
48
  end
49
49
 
50
+ def http_library
51
+ :patron
52
+ end
53
+
50
54
  end
@@ -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 'abc' with headers {'A'=>'a', 'B'=>'b'}"
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 'abc' with headers {'A'=>'a', 'B'=>'b'} with given block"
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
- it "should match if request body and body pattern are the same" do
125
- RequestPattern.new(:get, "www.example.com", :body => "abc").
126
- should match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
127
- end
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
- it "should match if request body matches regexp" do
130
- RequestPattern.new(:get, "www.example.com", :body => /^abc$/).
131
- should match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
132
- end
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
- it "should not match if body pattern is different than request body" do
135
- RequestPattern.new(:get, "www.example.com", :body => "def").
136
- should_not match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
137
- end
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
- it "should not match if request body doesn't match regexp pattern" do
140
- RequestPattern.new(:get, "www.example.com", :body => /^abc$/).
141
- should_not match(RequestSignature.new(:get, "www.example.com", :body => "xabc"))
142
- end
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
- it "should not match if pattern has body specified as nil but request body is not empty" do
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
- it "should not match if pattern has empty body but request body is not empty" do
155
- RequestPattern.new(:get, "www.example.com", :body => "").
156
- should_not match(RequestSignature.new(:get, "www.example.com", :body => "abc"))
157
- end
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
- it "should not match if pattern has body specified but request has no body" do
160
- RequestPattern.new(:get, "www.example.com", :body => "abc").
161
- should_not match(RequestSignature.new(:get, "www.example.com"))
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'}))
@@ -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
@@ -1,6 +1,9 @@
1
1
  require 'rubygems'
2
2
  require 'httpclient'
3
- require 'patron' unless RUBY_PLATFORM =~ /java/
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
@@ -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("The request GET http://www.example.com/ with body 'def' was expected to execute 1 time but it executed 0 times")
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
- it "should succeed if request was executed with the same body" do
847
- lambda {
848
- http_request(:post, "http://www.example.com/", :body => "abc")
849
- request(:post, "www.example.com").with(:body => /^abc$/).should have_been_made
850
- }.should_not raise_error
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
- it "should fail if request was executed with different body" do
854
- lambda {
855
- http_request(:get, "http://www.example.com/", :body => /^abc/)
856
- request(:get, "www.example.com").
857
- with(:body => "xabc").should have_been_made
858
- }.should fail_with("The request GET http://www.example.com/ with body 'xabc' was expected to execute 1 time but it executed 0 times")
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