typhoeus 0.1.3 → 0.1.4
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/ext/typhoeus/typhoeus_multi.c +7 -2
- data/lib/typhoeus.rb +1 -1
- data/lib/typhoeus/easy.rb +1 -0
- data/lib/typhoeus/hydra.rb +2 -1
- data/spec/servers/app.rb +37 -0
- data/spec/spec_helper.rb +1 -19
- data/spec/typhoeus/easy_spec.rb +6 -27
- data/spec/typhoeus/multi_spec.rb +4 -12
- data/spec/typhoeus/remote_proxy_object_spec.rb +1 -9
- data/spec/typhoeus/remote_spec.rb +684 -688
- metadata +2 -3
- data/spec/servers/delay_fixture_server.rb +0 -66
- data/spec/servers/method_server.rb +0 -51
@@ -75,6 +75,11 @@ static void multi_read_info(VALUE self, CURLM *multi_handle) {
|
|
75
75
|
// this next bit is a horrible hack. For some reason my tests against a local server on my laptop
|
76
76
|
// fail intermittently and return this result number. However, it will succeed if you try it a few
|
77
77
|
// more times. Also noteworthy is that this doens't happen when hitting an external server. WTF?!
|
78
|
+
|
79
|
+
// Sandofsky says:
|
80
|
+
// This is caused by OS X first attempting to resolve using IPV6.
|
81
|
+
// Hack solution: connect to yourself with 127.0.0.1, not localhost
|
82
|
+
// http://curl.haxx.se/mail/tracker-2009-09/0018.html
|
78
83
|
if (result == 7) {
|
79
84
|
VALUE max_retries = rb_funcall(easy, rb_intern("max_retries?"), 0);
|
80
85
|
if (max_retries != Qtrue) {
|
@@ -146,7 +151,7 @@ static VALUE multi_perform(VALUE self) {
|
|
146
151
|
rb_curl_multi_run( self, curl_multi->multi, &(curl_multi->running) );
|
147
152
|
continue;
|
148
153
|
}
|
149
|
-
else if (timeout
|
154
|
+
else if (timeout < 0) {
|
150
155
|
timeout = 1;
|
151
156
|
}
|
152
157
|
|
@@ -159,7 +164,7 @@ static VALUE multi_perform(VALUE self) {
|
|
159
164
|
rb_raise((VALUE)mcode, "an error occured getting the fdset");
|
160
165
|
}
|
161
166
|
|
162
|
-
rc =
|
167
|
+
rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
|
163
168
|
if (rc < 0) {
|
164
169
|
rb_raise(rb_eRuntimeError, "error on thread select");
|
165
170
|
}
|
data/lib/typhoeus.rb
CHANGED
data/lib/typhoeus/easy.rb
CHANGED
data/lib/typhoeus/hydra.rb
CHANGED
data/spec/servers/app.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
@@fail_count = 0
|
6
|
+
get '/fail/:number' do
|
7
|
+
if @@fail_count >= params[:number].to_i
|
8
|
+
"ok"
|
9
|
+
else
|
10
|
+
@@fail_count += 1
|
11
|
+
error 500, "oh noes!"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
get '/fail_forever' do
|
16
|
+
error 500, "oh noes!"
|
17
|
+
end
|
18
|
+
|
19
|
+
get '/**' do
|
20
|
+
sleep params["delay"].to_i if params.has_key?("delay")
|
21
|
+
request.env.merge!(:body => request.body.read).to_json
|
22
|
+
end
|
23
|
+
|
24
|
+
put '/**' do
|
25
|
+
puts request.inspect
|
26
|
+
request.env.merge!(:body => request.body.read).to_json
|
27
|
+
end
|
28
|
+
|
29
|
+
post '/**' do
|
30
|
+
puts request.inspect
|
31
|
+
request.env.merge!(:body => request.body.read).to_json
|
32
|
+
end
|
33
|
+
|
34
|
+
delete '/**' do
|
35
|
+
puts request.inspect
|
36
|
+
request.env.merge!(:body => request.body.read).to_json
|
37
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "rubygems"
|
2
|
+
require 'json'
|
2
3
|
require "spec"
|
3
4
|
|
4
5
|
# gem install redgreen for colored test output
|
@@ -8,22 +9,3 @@ path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
|
8
9
|
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
9
10
|
|
10
11
|
require "lib/typhoeus"
|
11
|
-
|
12
|
-
# local servers for running tests
|
13
|
-
require File.dirname(__FILE__) + "/servers/method_server.rb"
|
14
|
-
|
15
|
-
def start_method_server(port, sleep = 0)
|
16
|
-
MethodServer.sleep_time = sleep
|
17
|
-
pid = Process.fork do
|
18
|
-
EventMachine::run {
|
19
|
-
EventMachine.epoll
|
20
|
-
EventMachine::start_server("0.0.0.0", port, MethodServer)
|
21
|
-
}
|
22
|
-
end
|
23
|
-
sleep 0.2
|
24
|
-
pid
|
25
|
-
end
|
26
|
-
|
27
|
-
def stop_method_server(pid)
|
28
|
-
Process.kill("HUP", pid)
|
29
|
-
end
|
data/spec/typhoeus/easy_spec.rb
CHANGED
@@ -1,28 +1,17 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
|
-
describe Typhoeus::Easy do
|
4
|
-
before(:all) do
|
5
|
-
@pid = start_method_server(3002)
|
6
|
-
end
|
7
|
-
|
8
|
-
after(:all) do
|
9
|
-
stop_method_server(@pid)
|
10
|
-
end
|
11
|
-
|
3
|
+
describe Typhoeus::Easy do
|
12
4
|
describe "options" do
|
13
5
|
it "should allow for following redirects"
|
14
6
|
it "should allow you to set the user agent"
|
15
7
|
it "should provide a timeout in milliseconds" do
|
16
|
-
pid = start_method_server(3001, 5)
|
17
8
|
e = Typhoeus::Easy.new
|
18
9
|
e.url = "http://localhost:3001"
|
19
10
|
e.method = :get
|
20
11
|
e.timeout = 50
|
21
12
|
e.perform
|
22
|
-
|
23
|
-
puts e.total_time_taken
|
13
|
+
# this doesn't work on a mac for some reason
|
24
14
|
# e.timed_out?.should == true
|
25
|
-
stop_method_server(pid)
|
26
15
|
end
|
27
16
|
end
|
28
17
|
|
@@ -33,17 +22,7 @@ describe Typhoeus::Easy do
|
|
33
22
|
easy.method = :get
|
34
23
|
easy.perform
|
35
24
|
easy.response_code.should == 200
|
36
|
-
easy.response_body.should
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should send a request body" do
|
40
|
-
easy = Typhoeus::Easy.new
|
41
|
-
easy.url = "http://localhost:3002"
|
42
|
-
easy.method = :get
|
43
|
-
easy.request_body = "this is a body!"
|
44
|
-
easy.perform
|
45
|
-
easy.response_code.should == 200
|
46
|
-
easy.response_body.should include("this is a body!")
|
25
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "GET"
|
47
26
|
end
|
48
27
|
end
|
49
28
|
|
@@ -80,7 +59,7 @@ describe Typhoeus::Easy do
|
|
80
59
|
easy.method = :put
|
81
60
|
easy.perform
|
82
61
|
easy.response_code.should == 200
|
83
|
-
easy.response_body.should
|
62
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "PUT"
|
84
63
|
end
|
85
64
|
|
86
65
|
it "should send a request body" do
|
@@ -101,7 +80,7 @@ describe Typhoeus::Easy do
|
|
101
80
|
easy.method = :post
|
102
81
|
easy.perform
|
103
82
|
easy.response_code.should == 200
|
104
|
-
easy.response_body.should
|
83
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "POST"
|
105
84
|
end
|
106
85
|
|
107
86
|
it "should send a request body" do
|
@@ -132,7 +111,7 @@ describe Typhoeus::Easy do
|
|
132
111
|
easy.method = :delete
|
133
112
|
easy.perform
|
134
113
|
easy.response_code.should == 200
|
135
|
-
easy.response_body.should
|
114
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "DELETE"
|
136
115
|
end
|
137
116
|
|
138
117
|
it "should send a request body" do
|
data/spec/typhoeus/multi_spec.rb
CHANGED
@@ -1,14 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
3
|
describe Typhoeus::Easy do
|
4
|
-
before(:all) do
|
5
|
-
@pid = start_method_server(3002)
|
6
|
-
end
|
7
|
-
|
8
|
-
after(:all) do
|
9
|
-
stop_method_server(@pid)
|
10
|
-
end
|
11
|
-
|
12
4
|
it "should save easy handles that get added" do
|
13
5
|
multi = Typhoeus::Multi.new
|
14
6
|
easy = Typhoeus::Easy.new
|
@@ -30,7 +22,7 @@ describe Typhoeus::Easy do
|
|
30
22
|
multi.add(easy)
|
31
23
|
multi.perform
|
32
24
|
easy.response_code.should == 200
|
33
|
-
easy.response_body.should
|
25
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "GET"
|
34
26
|
|
35
27
|
e2 = Typhoeus::Easy.new
|
36
28
|
e2.url = "http://localhost:3002"
|
@@ -39,7 +31,7 @@ describe Typhoeus::Easy do
|
|
39
31
|
multi.perform
|
40
32
|
|
41
33
|
e2.response_code.should == 200
|
42
|
-
e2.response_body.should
|
34
|
+
JSON.parse(e2.response_body)["REQUEST_METHOD"].should == "POST"
|
43
35
|
end
|
44
36
|
|
45
37
|
it "should perform easy handles added after the first one runs" do
|
@@ -58,9 +50,9 @@ describe Typhoeus::Easy do
|
|
58
50
|
|
59
51
|
multi.perform
|
60
52
|
easy.response_code.should == 200
|
61
|
-
easy.response_body.should
|
53
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "GET"
|
62
54
|
e2.response_code.should == 200
|
63
|
-
e2.response_body.should
|
55
|
+
JSON.parse(e2.response_body)["REQUEST_METHOD"].should == "POST"
|
64
56
|
end
|
65
57
|
|
66
58
|
# it "should do multiple gets" do
|
@@ -6,14 +6,6 @@ describe Typhoeus::RemoteProxyObject do
|
|
6
6
|
@easy.method = :get
|
7
7
|
@easy.url = "http://localhost:3001"
|
8
8
|
end
|
9
|
-
|
10
|
-
before(:all) do
|
11
|
-
@pid = start_method_server(3001)
|
12
|
-
end
|
13
|
-
|
14
|
-
after(:all) do
|
15
|
-
stop_method_server(@pid)
|
16
|
-
end
|
17
9
|
|
18
10
|
it "should take a caller and call the clear_memoized_proxy_objects" do
|
19
11
|
clear_proxy = lambda {}
|
@@ -66,7 +58,7 @@ describe Typhoeus::RemoteProxyObject do
|
|
66
58
|
@response.code
|
67
59
|
end
|
68
60
|
end
|
69
|
-
@easy.url = "http://localhost:
|
61
|
+
@easy.url = "http://localhost:3005" #bad port
|
70
62
|
k = Typhoeus::RemoteProxyObject.new(lambda {}, @easy, :on_failure => lambda {|e| klass.new(e)})
|
71
63
|
k.blah.should == 0
|
72
64
|
end
|
@@ -1,699 +1,695 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
3
|
describe Typhoeus do
|
4
|
-
|
5
|
-
|
6
|
-
include Typhoeus
|
7
|
-
end
|
4
|
+
it "should be deprecated" do
|
5
|
+
fail "This entire interface is deprecated!"
|
8
6
|
end
|
9
7
|
|
10
|
-
before(:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
it "should take expected request headers" do
|
220
|
-
@header_klass.get("http://asdf", :headers => {"If-None-Match" => "\"lkjsd90823\""})
|
221
|
-
end
|
222
|
-
|
223
|
-
it "should raise if the expected request headers don't match" do
|
224
|
-
lambda {
|
225
|
-
@header_klass.get("http://asdf")
|
226
|
-
}.should raise_error
|
227
|
-
end
|
228
|
-
|
229
|
-
it "should raise if an unexpected header shows up" do
|
230
|
-
lambda {
|
231
|
-
@header_klass.get("http://asdf",
|
232
|
-
:headers => { "Content-Type" => "text/xml" })
|
233
|
-
}.should raise_error
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
describe "remote methods" do
|
238
|
-
it "should work for defined remote methods" do
|
239
|
-
@klass.instance_eval do
|
240
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_success => lambda {|r| r.body.should == "hi"; :great_success}
|
241
|
-
end
|
242
|
-
@klass.mock(:get, :url => "http://localhost:3001", :body => "hi")
|
243
|
-
@klass.do_stuff.should == :great_success
|
244
|
-
end
|
245
|
-
|
246
|
-
it "should call the on failure handler for remote methods" do
|
247
|
-
@klass.instance_eval do
|
248
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_failure => lambda {|r| r.body.should == "hi"; :fail}
|
249
|
-
end
|
250
|
-
@klass.mock(:get, :url => "http://localhost:3001", :body => "hi", :code => 500)
|
251
|
-
@klass.do_stuff.should == :fail
|
252
|
-
end
|
253
|
-
|
254
|
-
it "should allow for subclassing a class that includes Typhoeus, and merging defaults" do
|
255
|
-
class TestA
|
256
|
-
include Typhoeus
|
257
|
-
remote_defaults :on_failure => lambda { |response|
|
258
|
-
:fail
|
259
|
-
}
|
260
|
-
end
|
261
|
-
|
262
|
-
class TestB < TestA
|
263
|
-
remote_defaults :base_uri => "http://localhost"
|
264
|
-
define_remote_method :do_stuff
|
265
|
-
end
|
266
|
-
|
267
|
-
TestB.mock(:get, :url => "http://localhost", :body => "hi", :code => 500)
|
268
|
-
TestB.do_stuff.should == :fail
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
describe "response hash" do
|
273
|
-
it "should use provided code" do
|
274
|
-
@klass.mock(:get, :url => "http://localhost/whatever", :code => 301)
|
275
|
-
response = @klass.get("http://localhost/whatever")
|
276
|
-
response.code.should == 301
|
277
|
-
response.body.should == ""
|
278
|
-
response.headers.should == ""
|
279
|
-
response.time.should == 0
|
280
|
-
end
|
281
|
-
|
282
|
-
it "should use provided body" do
|
283
|
-
@klass.mock(:get, :url => "http://localhost/whatever", :body => "hey paul")
|
284
|
-
response = @klass.get("http://localhost/whatever")
|
285
|
-
response.code.should == 200
|
286
|
-
response.body.should == "hey paul"
|
287
|
-
response.headers.should == ""
|
288
|
-
response.time.should == 0
|
289
|
-
end
|
290
|
-
|
291
|
-
it "should use provided headers" do
|
292
|
-
@klass.mock(:get, :url => "http://localhost/whatever", :headers => "whooo, headers!")
|
293
|
-
response = @klass.get("http://localhost/whatever")
|
294
|
-
response.code.should == 200
|
295
|
-
response.body.should == ""
|
296
|
-
response.headers.should == "whooo, headers!"
|
297
|
-
response.time.should == 0
|
298
|
-
end
|
299
|
-
|
300
|
-
it "should use provided time" do
|
301
|
-
@klass.mock(:get, :url => "http://localhost/whatever", :time => 123)
|
302
|
-
response = @klass.get("http://localhost/whatever")
|
303
|
-
response.code.should == 200
|
304
|
-
response.body.should == ""
|
305
|
-
response.headers.should == ""
|
306
|
-
response.time.should == 123
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
describe "get" do
|
312
|
-
it "should add a get method" do
|
313
|
-
easy = @klass.get("http://localhost:3001/posts.xml")
|
314
|
-
easy.code.should == 200
|
315
|
-
easy.body.should include("REQUEST_METHOD=GET")
|
316
|
-
easy.body.should include("REQUEST_URI=/posts.xml")
|
317
|
-
end
|
318
|
-
|
319
|
-
it "should take passed in params and add them to the query string" do
|
320
|
-
easy = @klass.get("http://localhost:3001", {:params => {:foo => :bar}})
|
321
|
-
easy.body.should include("QUERY_STRING=foo=bar")
|
322
|
-
end
|
323
|
-
end # get
|
324
|
-
|
325
|
-
describe "post" do
|
326
|
-
it "should add a post method" do
|
327
|
-
easy = @klass.post("http://localhost:3001/posts.xml", {:params => {:post => {:author => "paul", :title => "a title", :body => "a body"}}})
|
328
|
-
easy.code.should == 200
|
329
|
-
easy.body.should include("post%5Bbody%5D=a+body")
|
330
|
-
easy.body.should include("post%5Bauthor%5D=paul")
|
331
|
-
easy.body.should include("post%5Btitle%5D=a+title")
|
332
|
-
easy.body.should include("REQUEST_METHOD=POST")
|
333
|
-
end
|
334
|
-
|
335
|
-
it "should add a body" do
|
336
|
-
easy = @klass.post("http://localhost:3001/posts.xml", {:body => "this is a request body"})
|
337
|
-
easy.code.should == 200
|
338
|
-
easy.body.should include("this is a request body")
|
339
|
-
easy.body.should include("REQUEST_METHOD=POST")
|
340
|
-
end
|
341
|
-
end # post
|
342
|
-
|
343
|
-
it "should add a put method" do
|
344
|
-
easy = @klass.put("http://localhost:3001/posts/3.xml")
|
345
|
-
easy.code.should == 200
|
346
|
-
easy.body.should include("REQUEST_METHOD=PUT")
|
347
|
-
end
|
348
|
-
|
349
|
-
it "should add a delete method" do
|
350
|
-
easy = @klass.delete("http://localhost:3001/posts/3.xml")
|
351
|
-
easy.code.should == 200
|
352
|
-
easy.body.should include("REQUEST_METHOD=DELETE")
|
353
|
-
end
|
354
|
-
|
355
|
-
describe "#define_remote_method" do
|
356
|
-
before(:each) do
|
357
|
-
@klass = Class.new do
|
358
|
-
include Typhoeus
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
describe "defined methods" do
|
363
|
-
before(:each) do
|
364
|
-
@klass.instance_eval do
|
365
|
-
define_remote_method :do_stuff
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
it "should take a method name as the first argument and define that as a class method" do
|
370
|
-
@klass.should respond_to(:do_stuff)
|
371
|
-
end
|
372
|
-
|
373
|
-
it "should optionally take arguments" do
|
374
|
-
@klass.should_receive(:get)
|
375
|
-
@klass.do_stuff
|
376
|
-
end
|
377
|
-
|
378
|
-
it "should take arguments" do
|
379
|
-
@klass.should_receive(:get).with("", {:params=>{:foo=>"bar"}, :body=>"whatever"})
|
380
|
-
@klass.do_stuff(:params => {:foo => "bar"}, :body => "whatever")
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
describe "base_uri" do
|
385
|
-
it "should take a :uri as an argument" do
|
386
|
-
@klass.instance_eval do
|
387
|
-
define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
388
|
-
end
|
389
|
-
|
390
|
-
@klass.should_receive(:get).with("http://pauldix.net", {})
|
391
|
-
@klass.do_stuff
|
392
|
-
end
|
393
|
-
|
394
|
-
it "should use default_base_uri if no base_uri provided" do
|
395
|
-
@klass.instance_eval do
|
396
|
-
remote_defaults :base_uri => "http://kgb.com"
|
397
|
-
define_remote_method :do_stuff
|
398
|
-
end
|
399
|
-
|
400
|
-
@klass.should_receive(:get).with("http://kgb.com", {})
|
401
|
-
@klass.do_stuff
|
402
|
-
end
|
403
|
-
|
404
|
-
it "should override default_base_uri if uri argument is provided" do
|
405
|
-
@klass.instance_eval do
|
406
|
-
remote_defaults :base_uri => "http://kgb.com"
|
407
|
-
define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
408
|
-
end
|
409
|
-
|
410
|
-
@klass.should_receive(:get).with("http://pauldix.net", {})
|
411
|
-
@klass.do_stuff
|
412
|
-
end
|
413
|
-
end
|
414
|
-
|
415
|
-
describe "path" do
|
416
|
-
it "should take :path as an argument" do
|
417
|
-
@klass.instance_eval do
|
418
|
-
define_remote_method :do_stuff, :base_uri => "http://kgb.com", :path => "/default.html"
|
419
|
-
end
|
420
|
-
|
421
|
-
@klass.should_receive(:get).with("http://kgb.com/default.html", {})
|
422
|
-
@klass.do_stuff
|
423
|
-
end
|
424
|
-
|
425
|
-
it "should use deafult_path if no path provided" do
|
426
|
-
@klass.instance_eval do
|
427
|
-
remote_defaults :path => "/index.html"
|
428
|
-
define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
429
|
-
end
|
430
|
-
|
431
|
-
@klass.should_receive(:get).with("http://pauldix.net/index.html", {})
|
432
|
-
@klass.do_stuff
|
433
|
-
end
|
434
|
-
|
435
|
-
it "should orverride default_path if path argument is provided" do
|
436
|
-
@klass.instance_eval do
|
437
|
-
remote_defaults :path => "/index.html"
|
438
|
-
define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :path => "/foo.html"
|
439
|
-
end
|
440
|
-
|
441
|
-
@klass.should_receive(:get).with("http://pauldix.net/foo.html", {})
|
442
|
-
@klass.do_stuff
|
443
|
-
end
|
444
|
-
|
445
|
-
it "should map symbols in path to arguments for the remote method" do
|
446
|
-
@klass.instance_eval do
|
447
|
-
define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :path => "/posts/:post_id/comments/:comment_id"
|
448
|
-
end
|
449
|
-
|
450
|
-
@klass.should_receive(:get).with("http://pauldix.net/posts/foo/comments/bar", {})
|
451
|
-
@klass.do_stuff(:post_id => "foo", :comment_id => "bar")
|
452
|
-
end
|
453
|
-
|
454
|
-
it "should use a path passed into the remote method call" do
|
455
|
-
@klass.instance_eval do
|
456
|
-
define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
457
|
-
end
|
458
|
-
|
459
|
-
@klass.should_receive(:get).with("http://pauldix.net/whatev?asdf=foo", {})
|
460
|
-
@klass.do_stuff(:path => "/whatev?asdf=foo")
|
461
|
-
end
|
462
|
-
end
|
463
|
-
|
464
|
-
describe "method" do
|
465
|
-
it "should take :method as an argument" do
|
466
|
-
@klass.instance_eval do
|
467
|
-
define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :method => :put
|
468
|
-
end
|
469
|
-
|
470
|
-
@klass.should_receive(:put).with("http://pauldix.net", {})
|
471
|
-
@klass.do_stuff
|
472
|
-
end
|
473
|
-
|
474
|
-
it "should use :get if no method or default_method exists" do
|
475
|
-
@klass.instance_eval do
|
476
|
-
define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
477
|
-
end
|
478
|
-
|
479
|
-
@klass.should_receive(:get).with("http://pauldix.net", {})
|
480
|
-
@klass.do_stuff
|
481
|
-
end
|
482
|
-
|
483
|
-
it "should use default_method if no method provided" do
|
484
|
-
@klass.instance_eval do
|
485
|
-
remote_defaults :method => :delete
|
486
|
-
define_remote_method :do_stuff, :base_uri => "http://kgb.com"
|
487
|
-
end
|
488
|
-
|
489
|
-
@klass.should_receive(:delete).with("http://kgb.com", {})
|
490
|
-
@klass.do_stuff
|
491
|
-
end
|
492
|
-
|
493
|
-
it "should override deafult_method if method argument is provided" do
|
494
|
-
@klass.instance_eval do
|
495
|
-
remote_defaults :method => :put
|
496
|
-
define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :method => :post
|
497
|
-
end
|
498
|
-
|
499
|
-
@klass.should_receive(:post).with("http://pauldix.net", {})
|
500
|
-
@klass.do_stuff
|
501
|
-
end
|
502
|
-
end
|
503
|
-
|
504
|
-
describe "on_success" do
|
505
|
-
it "should take :on_success as an argument" do
|
506
|
-
@klass.instance_eval do
|
507
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_success => lambda {|e| e.code.should == 200; :foo}
|
508
|
-
end
|
509
|
-
|
510
|
-
@klass.do_stuff.should == :foo
|
511
|
-
end
|
512
|
-
|
513
|
-
it "should use default_on_success if no on_success provided" do
|
514
|
-
@klass.instance_eval do
|
515
|
-
remote_defaults :on_success => lambda {|e| e.code.should == 200; :foo}
|
516
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001"
|
517
|
-
end
|
518
|
-
|
519
|
-
@klass.do_stuff.should == :foo
|
520
|
-
end
|
521
|
-
|
522
|
-
it "should override default_on_success if on_success is provided" do
|
523
|
-
@klass.instance_eval do
|
524
|
-
remote_defaults :on_success => lambda {|e| :foo}
|
525
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_success => lambda {|e| e.code.should == 200; :bar}
|
526
|
-
end
|
527
|
-
|
528
|
-
@klass.do_stuff.should == :bar
|
529
|
-
end
|
530
|
-
end
|
531
|
-
|
532
|
-
describe "on_failure" do
|
533
|
-
it "should take :on_failure as an argument" do
|
534
|
-
@klass.instance_eval do
|
535
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:9999", :on_failure => lambda {|e| e.code.should == 0; :foo}
|
536
|
-
end
|
537
|
-
|
538
|
-
@klass.do_stuff.should == :foo
|
539
|
-
end
|
540
|
-
|
541
|
-
it "should use default_on_failure if no on_success provided" do
|
542
|
-
@klass.instance_eval do
|
543
|
-
remote_defaults :on_failure => lambda {|e| e.code.should == 0; :bar}
|
544
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:9999"
|
545
|
-
end
|
546
|
-
|
547
|
-
@klass.do_stuff.should == :bar
|
548
|
-
end
|
549
|
-
|
550
|
-
it "should override default_on_failure if no method is provided" do
|
551
|
-
@klass.instance_eval do
|
552
|
-
remote_defaults :on_failure => lambda {|e| :foo}
|
553
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:9999", :on_failure => lambda {|e| e.code.should == 0; :bar}
|
554
|
-
end
|
555
|
-
|
556
|
-
@klass.do_stuff.should == :bar
|
557
|
-
end
|
558
|
-
end
|
559
|
-
|
560
|
-
describe "params" do
|
561
|
-
it "should take :params as an argument" do
|
562
|
-
@klass.instance_eval do
|
563
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :params => {:foo => :bar}
|
564
|
-
end
|
565
|
-
|
566
|
-
@klass.do_stuff.body.should include("QUERY_STRING=foo=bar")
|
567
|
-
end
|
568
|
-
|
569
|
-
it "should add :params from remote method definition with params passed in when called" do
|
570
|
-
@klass.instance_eval do
|
571
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :params => {:foo => :bar}
|
572
|
-
end
|
573
|
-
|
574
|
-
result = @klass.do_stuff(:params => {:asdf => :jkl})
|
575
|
-
|
576
|
-
# Make this test more robust to hash ordering.
|
577
|
-
query_string = result.body.match(/QUERY_STRING=([^\n]+)/)
|
578
|
-
params = query_string[1].split("&")
|
579
|
-
["asdf=jkl", "foo=bar"].each do |param|
|
580
|
-
params.should include(param)
|
581
|
-
end
|
582
|
-
end
|
583
|
-
end
|
584
|
-
|
585
|
-
describe "memoize_responses" do
|
586
|
-
it "should only make one call to the http method and the on_success handler if :memoize_responses => true" do
|
587
|
-
success_mock = mock("success")
|
588
|
-
success_mock.should_receive(:call).exactly(2).times
|
589
|
-
|
590
|
-
@klass.instance_eval do
|
591
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :path => "/:file", :on_success => lambda {|e| success_mock.call; :foo}
|
592
|
-
end
|
593
|
-
|
594
|
-
first_return_val = @klass.do_stuff(:file => "user.html")
|
595
|
-
second_return_val = @klass.do_stuff(:file => "post.html")
|
596
|
-
third_return_val = @klass.do_stuff(:file => "user.html")
|
597
|
-
|
598
|
-
first_return_val.should == :foo
|
599
|
-
second_return_val.should == :foo
|
600
|
-
third_return_val.should == :foo
|
601
|
-
end
|
602
|
-
|
603
|
-
it "should clear memoized responses after a full run" do
|
604
|
-
success_mock = mock("success")
|
605
|
-
success_mock.should_receive(:call).exactly(2).times
|
606
|
-
|
607
|
-
@klass.instance_eval do
|
608
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :path => "/:file", :on_success => lambda {|e| success_mock.call; :foo}
|
609
|
-
end
|
610
|
-
|
611
|
-
@klass.do_stuff(:file => "user.html").should == :foo
|
612
|
-
@klass.do_stuff(:file => "user.html").should == :foo
|
613
|
-
end
|
614
|
-
end
|
615
|
-
|
616
|
-
describe "cache_response" do
|
617
|
-
before(:each) do
|
618
|
-
@cache = Class.new do
|
619
|
-
def self.get(key)
|
620
|
-
@cache ||= {}
|
621
|
-
@cache[key]
|
622
|
-
end
|
623
|
-
|
624
|
-
def self.set(key, value, timeout = 0)
|
625
|
-
@cache ||= {}
|
626
|
-
@cache[key] = value
|
627
|
-
end
|
628
|
-
end
|
629
|
-
|
630
|
-
@klass.instance_eval do
|
631
|
-
define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :path => "/:file", :cache_responses => true, :on_success => lambda {|e| :foo}
|
632
|
-
end
|
633
|
-
end
|
634
|
-
|
635
|
-
it "should pull from the cache if :cache_response => true" do
|
636
|
-
@cache.should_receive(:get).and_return(:foo)
|
637
|
-
@klass.cache = @cache
|
638
|
-
Typhoeus.should_receive(:perform_easy_requests).exactly(0).times
|
639
|
-
@klass.do_stuff.should == :foo
|
640
|
-
end
|
641
|
-
|
642
|
-
it "should only hit the cache once for the same value" do
|
643
|
-
@cache.should_receive(:get).exactly(1).times.and_return(:foo)
|
644
|
-
@klass.cache = @cache
|
645
|
-
Typhoeus.should_receive(:perform_easy_requests).exactly(0).times
|
646
|
-
|
647
|
-
|
648
|
-
first = @klass.do_stuff
|
649
|
-
second = @klass.do_stuff
|
650
|
-
|
651
|
-
first.should == :foo
|
652
|
-
second.should == :foo
|
653
|
-
end
|
654
|
-
|
655
|
-
it "should only hit the cache once if there is a cache miss (don't check again and again inside the same block)." do
|
656
|
-
@cache.should_receive(:get).exactly(1).times.and_return(nil)
|
657
|
-
@cache.should_receive(:set).exactly(1).times
|
658
|
-
@klass.cache = @cache
|
659
|
-
|
660
|
-
first = @klass.do_stuff
|
661
|
-
second = @klass.do_stuff
|
662
|
-
|
663
|
-
first.should == :foo
|
664
|
-
second.should == :foo
|
665
|
-
end
|
666
|
-
|
667
|
-
it "should store an object in the cache with a set ttl"
|
668
|
-
it "should take a hash with get and set method pointers to enable custom caching behavior"
|
669
|
-
end
|
670
|
-
end # define_remote_method
|
671
|
-
|
672
|
-
describe "cache_server" do
|
673
|
-
it "should store a cache_server" do
|
674
|
-
@klass.cache = :foo
|
675
|
-
end
|
676
|
-
end
|
677
|
-
|
678
|
-
describe "get_memcache_resposne_key" do
|
679
|
-
it "should return a key that is an and of the method name, args, and options" do
|
680
|
-
@klass.get_memcache_response_key(:do_stuff, ["foo"]).should == "20630a9d4864c41cbbcb8bd8ac91ab4767e72107b93329aa2e6f5629037392f3"
|
681
|
-
end
|
682
|
-
end
|
683
|
-
|
684
|
-
# describe "multiple with post" do
|
685
|
-
# require 'rubygems'
|
686
|
-
# require 'json'
|
687
|
-
# it "shoudl do stuff" do
|
688
|
-
# @klass.instance_eval do
|
689
|
-
# define_remote_method :post_stuff, :path => "/entries/metas/:meta_id/ids", :base_uri => "http://localhost:4567", :method => :post
|
690
|
-
# define_remote_method :get_stuff, :base_uri => "http://localhost:4567"
|
8
|
+
# before(:each) do
|
9
|
+
# @klass = Class.new do
|
10
|
+
# include Typhoeus
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# describe "entirely disallowing HTTP connections in specs" do
|
15
|
+
# describe "allow_net_connect" do
|
16
|
+
# it "should default to true" do
|
17
|
+
# @klass.allow_net_connect.should be_true
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# it "should be settable" do
|
21
|
+
# @klass.allow_net_connect.should be_true
|
22
|
+
# @klass.allow_net_connect = false
|
23
|
+
# @klass.allow_net_connect.should be_false
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# describe "and hitting a URL that hasn't been mocked" do
|
28
|
+
# it "should raise an error for any HTTP verbs" do
|
29
|
+
# @klass.allow_net_connect = false
|
30
|
+
#
|
31
|
+
# [:get, :put, :post, :delete].each do |method|
|
32
|
+
# lambda {
|
33
|
+
# @klass.send(method, "http://crazy_url_that_isnt_mocked.com")
|
34
|
+
# }.should raise_error(Typhoeus::MockExpectedError)
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# describe "hitting a mocked URL that returns false" do
|
40
|
+
# it "should not raise a MockExpectedError" do
|
41
|
+
# @klass.allow_net_connect = false
|
42
|
+
# @klass.mock(:delete,
|
43
|
+
# :url => "http://test.com",
|
44
|
+
# :code => 500,
|
45
|
+
# :body => 'ok')
|
46
|
+
#
|
47
|
+
# lambda {
|
48
|
+
# @klass.delete("http://test.com",
|
49
|
+
# :on_failure => lambda { |response| false })
|
50
|
+
# }.should_not raise_error
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# describe "handlers" do
|
55
|
+
# it "should be able to return nil as part of their block" do
|
56
|
+
# @klass.allow_net_connect = false
|
57
|
+
# url = 'http://api.mysite.com/v1/stuff.json'
|
58
|
+
# @klass.mock(:get,
|
59
|
+
# :url => url,
|
60
|
+
# :body => '',
|
61
|
+
# :code => 500)
|
62
|
+
# result = @klass.get(url,
|
63
|
+
# :on_failure => lambda { |response| nil })
|
64
|
+
# result.should be_nil
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# describe "mocking" do
|
70
|
+
# it "should mock out GET" do
|
71
|
+
# @klass.mock(:get)
|
72
|
+
# response = @klass.get("http://mock_url")
|
73
|
+
# response.code.should == 200
|
74
|
+
# response.body.should == ""
|
75
|
+
# response.headers.should == ""
|
76
|
+
# response.time.should == 0
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# it "should mock out PUT" do
|
80
|
+
# @klass.mock(:put)
|
81
|
+
# response = @klass.put("http://mock_url")
|
82
|
+
# response.code.should == 200
|
83
|
+
# response.body.should == ""
|
84
|
+
# response.headers.should == ""
|
85
|
+
# response.time.should == 0
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# it "should mock out POST" do
|
89
|
+
# @klass.mock(:post)
|
90
|
+
# response = @klass.post("http://mock_url")
|
91
|
+
# response.code.should == 200
|
92
|
+
# response.body.should == ""
|
93
|
+
# response.headers.should == ""
|
94
|
+
# response.time.should == 0
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# it "should mock out DELETE" do
|
98
|
+
# @klass.mock(:delete)
|
99
|
+
# response = @klass.delete("http://mock_url")
|
100
|
+
# response.code.should == 200
|
101
|
+
# response.body.should == ""
|
102
|
+
# response.headers.should == ""
|
103
|
+
# response.time.should == 0
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# it "should take an optional url" do
|
107
|
+
# @klass.mock(:get, :url => "http://stuff")
|
108
|
+
# response = @klass.get("http://stuff")
|
109
|
+
# response.code.should == 200
|
110
|
+
# response.body.should == ""
|
111
|
+
# response.headers.should == ""
|
112
|
+
# response.time.should == 0
|
113
|
+
#
|
114
|
+
# @klass.get("http://localhost:234234234").code.should == 0
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# it "should be able to mock using specific params as well" do
|
118
|
+
# @klass.allow_net_connect = false
|
119
|
+
# @klass.mock(:get, :url => "http://stuff")
|
120
|
+
#
|
121
|
+
# lambda {
|
122
|
+
# @klass.get("http://stuff", :params => { :a => 'test' })
|
123
|
+
# }.should raise_error(Typhoeus::MockExpectedError)
|
124
|
+
#
|
125
|
+
# @klass.mock(:get,
|
126
|
+
# :url => "http://stuff",
|
127
|
+
# :params => { :a => 'test' })
|
128
|
+
# lambda {
|
129
|
+
# @klass.get("http://stuff", :params => { :a => 'test' })
|
130
|
+
# }.should_not raise_error(Typhoeus::MockExpectedError)
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# describe "request body expectations" do
|
134
|
+
# before(:all) do
|
135
|
+
# @body_klass = Class.new do
|
136
|
+
# include Typhoeus
|
137
|
+
# end
|
138
|
+
# @body_klass.mock(:put, :url => "http://whatev", :expected_body => "hi")
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# it "should take an expected request body" do
|
142
|
+
# @body_klass.put("http://whatev", :body => "hi").code.should == 200
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
# it "should raise if the expected request body doesn't match" do
|
146
|
+
# lambda {
|
147
|
+
# @body_klass.put("http://whatev", :body => "not what we expect")
|
148
|
+
# }.should raise_error
|
149
|
+
# end
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# describe "check_expected_headers!" do
|
153
|
+
# before(:each) do
|
154
|
+
# @header_klass = Class.new do
|
155
|
+
# include Typhoeus
|
156
|
+
# end
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# it "should match a header with :anything" do
|
160
|
+
# lambda {
|
161
|
+
# @header_klass.check_expected_headers!(
|
162
|
+
# { :expected_headers => { 'Content-Type' => :anything } },
|
163
|
+
# { :headers => { 'Content-Type' => 'text/xml' } }
|
164
|
+
# )
|
165
|
+
# }.should_not raise_error
|
166
|
+
# end
|
167
|
+
#
|
168
|
+
# it "should enforce exact matching" do
|
169
|
+
# lambda {
|
170
|
+
# @header_klass.check_expected_headers!(
|
171
|
+
# { :expected_headers => { 'Content-Type' => 'text/html' } },
|
172
|
+
# { :headers => { 'Content-Type' => 'text/xml' } }
|
173
|
+
# )
|
174
|
+
# }.should raise_error
|
175
|
+
# end
|
176
|
+
# end
|
177
|
+
#
|
178
|
+
# describe "check_unexpected_headers!" do
|
179
|
+
# before(:each) do
|
180
|
+
# @header_klass = Class.new do
|
181
|
+
# include Typhoeus
|
182
|
+
# end
|
183
|
+
# end
|
184
|
+
#
|
185
|
+
# it "should match a header with :anything" do
|
186
|
+
# lambda {
|
187
|
+
# @header_klass.check_unexpected_headers!(
|
188
|
+
# { :unexpected_headers => { 'Content-Type' => :anything } },
|
189
|
+
# { :headers => { "Content-Type" => "text/xml" } }
|
190
|
+
# )
|
191
|
+
# }.should raise_error
|
192
|
+
# end
|
193
|
+
#
|
194
|
+
# it "should not match if a header is different from the expected value" do
|
195
|
+
# lambda {
|
196
|
+
# @header_klass.check_unexpected_headers!(
|
197
|
+
# { :unexpected_headers => { 'Content-Type' => 'text/html' } },
|
198
|
+
# { :headers => { "Content-Type" => "text/xml" } }
|
199
|
+
# )
|
200
|
+
# }.should_not raise_error
|
201
|
+
# end
|
202
|
+
# end
|
203
|
+
#
|
204
|
+
# describe "request header expectations" do
|
205
|
+
# before(:all) do
|
206
|
+
# @header_klass = Class.new do
|
207
|
+
# include Typhoeus
|
208
|
+
# end
|
209
|
+
# @header_klass.mock(:get,
|
210
|
+
# :url => "http://asdf",
|
211
|
+
# :expected_headers => {"If-None-Match" => "\"lkjsd90823\""},
|
212
|
+
# :unexpected_headers => { 'Content-Type' => "text/xml" })
|
213
|
+
# end
|
214
|
+
#
|
215
|
+
# it "should take expected request headers" do
|
216
|
+
# @header_klass.get("http://asdf", :headers => {"If-None-Match" => "\"lkjsd90823\""})
|
691
217
|
# end
|
692
218
|
#
|
693
|
-
#
|
694
|
-
#
|
695
|
-
#
|
219
|
+
# it "should raise if the expected request headers don't match" do
|
220
|
+
# lambda {
|
221
|
+
# @header_klass.get("http://asdf")
|
222
|
+
# }.should raise_error
|
696
223
|
# end
|
224
|
+
#
|
225
|
+
# it "should raise if an unexpected header shows up" do
|
226
|
+
# lambda {
|
227
|
+
# @header_klass.get("http://asdf",
|
228
|
+
# :headers => { "Content-Type" => "text/xml" })
|
229
|
+
# }.should raise_error
|
230
|
+
# end
|
231
|
+
# end
|
232
|
+
#
|
233
|
+
# describe "remote methods" do
|
234
|
+
# it "should work for defined remote methods" do
|
235
|
+
# @klass.instance_eval do
|
236
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_success => lambda {|r| r.body.should == "hi"; :great_success}
|
237
|
+
# end
|
238
|
+
# @klass.mock(:get, :url => "http://localhost:3001", :body => "hi")
|
239
|
+
# @klass.do_stuff.should == :great_success
|
240
|
+
# end
|
241
|
+
#
|
242
|
+
# it "should call the on failure handler for remote methods" do
|
243
|
+
# @klass.instance_eval do
|
244
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_failure => lambda {|r| r.body.should == "hi"; :fail}
|
245
|
+
# end
|
246
|
+
# @klass.mock(:get, :url => "http://localhost:3001", :body => "hi", :code => 500)
|
247
|
+
# @klass.do_stuff.should == :fail
|
248
|
+
# end
|
249
|
+
#
|
250
|
+
# it "should allow for subclassing a class that includes Typhoeus, and merging defaults" do
|
251
|
+
# class TestA
|
252
|
+
# include Typhoeus
|
253
|
+
# remote_defaults :on_failure => lambda { |response|
|
254
|
+
# :fail
|
255
|
+
# }
|
256
|
+
# end
|
257
|
+
#
|
258
|
+
# class TestB < TestA
|
259
|
+
# remote_defaults :base_uri => "http://localhost"
|
260
|
+
# define_remote_method :do_stuff
|
261
|
+
# end
|
262
|
+
#
|
263
|
+
# TestB.mock(:get, :url => "http://localhost", :body => "hi", :code => 500)
|
264
|
+
# TestB.do_stuff.should == :fail
|
265
|
+
# end
|
266
|
+
# end
|
267
|
+
#
|
268
|
+
# describe "response hash" do
|
269
|
+
# it "should use provided code" do
|
270
|
+
# @klass.mock(:get, :url => "http://localhost/whatever", :code => 301)
|
271
|
+
# response = @klass.get("http://localhost/whatever")
|
272
|
+
# response.code.should == 301
|
273
|
+
# response.body.should == ""
|
274
|
+
# response.headers.should == ""
|
275
|
+
# response.time.should == 0
|
276
|
+
# end
|
277
|
+
#
|
278
|
+
# it "should use provided body" do
|
279
|
+
# @klass.mock(:get, :url => "http://localhost/whatever", :body => "hey paul")
|
280
|
+
# response = @klass.get("http://localhost/whatever")
|
281
|
+
# response.code.should == 200
|
282
|
+
# response.body.should == "hey paul"
|
283
|
+
# response.headers.should == ""
|
284
|
+
# response.time.should == 0
|
285
|
+
# end
|
286
|
+
#
|
287
|
+
# it "should use provided headers" do
|
288
|
+
# @klass.mock(:get, :url => "http://localhost/whatever", :headers => "whooo, headers!")
|
289
|
+
# response = @klass.get("http://localhost/whatever")
|
290
|
+
# response.code.should == 200
|
291
|
+
# response.body.should == ""
|
292
|
+
# response.headers.should == "whooo, headers!"
|
293
|
+
# response.time.should == 0
|
294
|
+
# end
|
295
|
+
#
|
296
|
+
# it "should use provided time" do
|
297
|
+
# @klass.mock(:get, :url => "http://localhost/whatever", :time => 123)
|
298
|
+
# response = @klass.get("http://localhost/whatever")
|
299
|
+
# response.code.should == 200
|
300
|
+
# response.body.should == ""
|
301
|
+
# response.headers.should == ""
|
302
|
+
# response.time.should == 123
|
303
|
+
# end
|
304
|
+
# end
|
305
|
+
# end
|
306
|
+
#
|
307
|
+
# describe "get" do
|
308
|
+
# it "should add a get method" do
|
309
|
+
# easy = @klass.get("http://localhost:3001/posts.xml")
|
310
|
+
# easy.code.should == 200
|
311
|
+
# easy.body.should include("REQUEST_METHOD=GET")
|
312
|
+
# easy.body.should include("REQUEST_URI=/posts.xml")
|
313
|
+
# end
|
314
|
+
#
|
315
|
+
# it "should take passed in params and add them to the query string" do
|
316
|
+
# easy = @klass.get("http://localhost:3001", {:params => {:foo => :bar}})
|
317
|
+
# easy.body.should include("QUERY_STRING=foo=bar")
|
318
|
+
# end
|
319
|
+
# end # get
|
320
|
+
#
|
321
|
+
# describe "post" do
|
322
|
+
# it "should add a post method" do
|
323
|
+
# easy = @klass.post("http://localhost:3001/posts.xml", {:params => {:post => {:author => "paul", :title => "a title", :body => "a body"}}})
|
324
|
+
# easy.code.should == 200
|
325
|
+
# easy.body.should include("post%5Bbody%5D=a+body")
|
326
|
+
# easy.body.should include("post%5Bauthor%5D=paul")
|
327
|
+
# easy.body.should include("post%5Btitle%5D=a+title")
|
328
|
+
# easy.body.should include("REQUEST_METHOD=POST")
|
329
|
+
# end
|
330
|
+
#
|
331
|
+
# it "should add a body" do
|
332
|
+
# easy = @klass.post("http://localhost:3001/posts.xml", {:body => "this is a request body"})
|
333
|
+
# easy.code.should == 200
|
334
|
+
# easy.body.should include("this is a request body")
|
335
|
+
# easy.body.should include("REQUEST_METHOD=POST")
|
336
|
+
# end
|
337
|
+
# end # post
|
338
|
+
#
|
339
|
+
# it "should add a put method" do
|
340
|
+
# easy = @klass.put("http://localhost:3001/posts/3.xml")
|
341
|
+
# easy.code.should == 200
|
342
|
+
# easy.body.should include("REQUEST_METHOD=PUT")
|
343
|
+
# end
|
344
|
+
#
|
345
|
+
# it "should add a delete method" do
|
346
|
+
# easy = @klass.delete("http://localhost:3001/posts/3.xml")
|
347
|
+
# easy.code.should == 200
|
348
|
+
# easy.body.should include("REQUEST_METHOD=DELETE")
|
349
|
+
# end
|
350
|
+
#
|
351
|
+
# describe "#define_remote_method" do
|
352
|
+
# before(:each) do
|
353
|
+
# @klass = Class.new do
|
354
|
+
# include Typhoeus
|
355
|
+
# end
|
356
|
+
# end
|
357
|
+
#
|
358
|
+
# describe "defined methods" do
|
359
|
+
# before(:each) do
|
360
|
+
# @klass.instance_eval do
|
361
|
+
# define_remote_method :do_stuff
|
362
|
+
# end
|
363
|
+
# end
|
364
|
+
#
|
365
|
+
# it "should take a method name as the first argument and define that as a class method" do
|
366
|
+
# @klass.should respond_to(:do_stuff)
|
367
|
+
# end
|
368
|
+
#
|
369
|
+
# it "should optionally take arguments" do
|
370
|
+
# @klass.should_receive(:get)
|
371
|
+
# @klass.do_stuff
|
372
|
+
# end
|
373
|
+
#
|
374
|
+
# it "should take arguments" do
|
375
|
+
# @klass.should_receive(:get).with("", {:params=>{:foo=>"bar"}, :body=>"whatever"})
|
376
|
+
# @klass.do_stuff(:params => {:foo => "bar"}, :body => "whatever")
|
377
|
+
# end
|
378
|
+
# end
|
379
|
+
#
|
380
|
+
# describe "base_uri" do
|
381
|
+
# it "should take a :uri as an argument" do
|
382
|
+
# @klass.instance_eval do
|
383
|
+
# define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
384
|
+
# end
|
385
|
+
#
|
386
|
+
# @klass.should_receive(:get).with("http://pauldix.net", {})
|
387
|
+
# @klass.do_stuff
|
388
|
+
# end
|
389
|
+
#
|
390
|
+
# it "should use default_base_uri if no base_uri provided" do
|
391
|
+
# @klass.instance_eval do
|
392
|
+
# remote_defaults :base_uri => "http://kgb.com"
|
393
|
+
# define_remote_method :do_stuff
|
394
|
+
# end
|
395
|
+
#
|
396
|
+
# @klass.should_receive(:get).with("http://kgb.com", {})
|
397
|
+
# @klass.do_stuff
|
398
|
+
# end
|
399
|
+
#
|
400
|
+
# it "should override default_base_uri if uri argument is provided" do
|
401
|
+
# @klass.instance_eval do
|
402
|
+
# remote_defaults :base_uri => "http://kgb.com"
|
403
|
+
# define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
404
|
+
# end
|
405
|
+
#
|
406
|
+
# @klass.should_receive(:get).with("http://pauldix.net", {})
|
407
|
+
# @klass.do_stuff
|
408
|
+
# end
|
409
|
+
# end
|
410
|
+
#
|
411
|
+
# describe "path" do
|
412
|
+
# it "should take :path as an argument" do
|
413
|
+
# @klass.instance_eval do
|
414
|
+
# define_remote_method :do_stuff, :base_uri => "http://kgb.com", :path => "/default.html"
|
415
|
+
# end
|
416
|
+
#
|
417
|
+
# @klass.should_receive(:get).with("http://kgb.com/default.html", {})
|
418
|
+
# @klass.do_stuff
|
419
|
+
# end
|
420
|
+
#
|
421
|
+
# it "should use deafult_path if no path provided" do
|
422
|
+
# @klass.instance_eval do
|
423
|
+
# remote_defaults :path => "/index.html"
|
424
|
+
# define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
425
|
+
# end
|
426
|
+
#
|
427
|
+
# @klass.should_receive(:get).with("http://pauldix.net/index.html", {})
|
428
|
+
# @klass.do_stuff
|
429
|
+
# end
|
430
|
+
#
|
431
|
+
# it "should orverride default_path if path argument is provided" do
|
432
|
+
# @klass.instance_eval do
|
433
|
+
# remote_defaults :path => "/index.html"
|
434
|
+
# define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :path => "/foo.html"
|
435
|
+
# end
|
436
|
+
#
|
437
|
+
# @klass.should_receive(:get).with("http://pauldix.net/foo.html", {})
|
438
|
+
# @klass.do_stuff
|
439
|
+
# end
|
440
|
+
#
|
441
|
+
# it "should map symbols in path to arguments for the remote method" do
|
442
|
+
# @klass.instance_eval do
|
443
|
+
# define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :path => "/posts/:post_id/comments/:comment_id"
|
444
|
+
# end
|
445
|
+
#
|
446
|
+
# @klass.should_receive(:get).with("http://pauldix.net/posts/foo/comments/bar", {})
|
447
|
+
# @klass.do_stuff(:post_id => "foo", :comment_id => "bar")
|
448
|
+
# end
|
449
|
+
#
|
450
|
+
# it "should use a path passed into the remote method call" do
|
451
|
+
# @klass.instance_eval do
|
452
|
+
# define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
453
|
+
# end
|
454
|
+
#
|
455
|
+
# @klass.should_receive(:get).with("http://pauldix.net/whatev?asdf=foo", {})
|
456
|
+
# @klass.do_stuff(:path => "/whatev?asdf=foo")
|
457
|
+
# end
|
458
|
+
# end
|
459
|
+
#
|
460
|
+
# describe "method" do
|
461
|
+
# it "should take :method as an argument" do
|
462
|
+
# @klass.instance_eval do
|
463
|
+
# define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :method => :put
|
464
|
+
# end
|
465
|
+
#
|
466
|
+
# @klass.should_receive(:put).with("http://pauldix.net", {})
|
467
|
+
# @klass.do_stuff
|
468
|
+
# end
|
469
|
+
#
|
470
|
+
# it "should use :get if no method or default_method exists" do
|
471
|
+
# @klass.instance_eval do
|
472
|
+
# define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
|
473
|
+
# end
|
474
|
+
#
|
475
|
+
# @klass.should_receive(:get).with("http://pauldix.net", {})
|
476
|
+
# @klass.do_stuff
|
477
|
+
# end
|
478
|
+
#
|
479
|
+
# it "should use default_method if no method provided" do
|
480
|
+
# @klass.instance_eval do
|
481
|
+
# remote_defaults :method => :delete
|
482
|
+
# define_remote_method :do_stuff, :base_uri => "http://kgb.com"
|
483
|
+
# end
|
484
|
+
#
|
485
|
+
# @klass.should_receive(:delete).with("http://kgb.com", {})
|
486
|
+
# @klass.do_stuff
|
487
|
+
# end
|
488
|
+
#
|
489
|
+
# it "should override deafult_method if method argument is provided" do
|
490
|
+
# @klass.instance_eval do
|
491
|
+
# remote_defaults :method => :put
|
492
|
+
# define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :method => :post
|
493
|
+
# end
|
494
|
+
#
|
495
|
+
# @klass.should_receive(:post).with("http://pauldix.net", {})
|
496
|
+
# @klass.do_stuff
|
497
|
+
# end
|
498
|
+
# end
|
499
|
+
#
|
500
|
+
# describe "on_success" do
|
501
|
+
# it "should take :on_success as an argument" do
|
502
|
+
# @klass.instance_eval do
|
503
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_success => lambda {|e| e.code.should == 200; :foo}
|
504
|
+
# end
|
505
|
+
#
|
506
|
+
# @klass.do_stuff.should == :foo
|
507
|
+
# end
|
508
|
+
#
|
509
|
+
# it "should use default_on_success if no on_success provided" do
|
510
|
+
# @klass.instance_eval do
|
511
|
+
# remote_defaults :on_success => lambda {|e| e.code.should == 200; :foo}
|
512
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001"
|
513
|
+
# end
|
514
|
+
#
|
515
|
+
# @klass.do_stuff.should == :foo
|
516
|
+
# end
|
517
|
+
#
|
518
|
+
# it "should override default_on_success if on_success is provided" do
|
519
|
+
# @klass.instance_eval do
|
520
|
+
# remote_defaults :on_success => lambda {|e| :foo}
|
521
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_success => lambda {|e| e.code.should == 200; :bar}
|
522
|
+
# end
|
523
|
+
#
|
524
|
+
# @klass.do_stuff.should == :bar
|
525
|
+
# end
|
526
|
+
# end
|
527
|
+
#
|
528
|
+
# describe "on_failure" do
|
529
|
+
# it "should take :on_failure as an argument" do
|
530
|
+
# @klass.instance_eval do
|
531
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:9999", :on_failure => lambda {|e| e.code.should == 0; :foo}
|
532
|
+
# end
|
533
|
+
#
|
534
|
+
# @klass.do_stuff.should == :foo
|
535
|
+
# end
|
536
|
+
#
|
537
|
+
# it "should use default_on_failure if no on_success provided" do
|
538
|
+
# @klass.instance_eval do
|
539
|
+
# remote_defaults :on_failure => lambda {|e| e.code.should == 0; :bar}
|
540
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:9999"
|
541
|
+
# end
|
542
|
+
#
|
543
|
+
# @klass.do_stuff.should == :bar
|
544
|
+
# end
|
545
|
+
#
|
546
|
+
# it "should override default_on_failure if no method is provided" do
|
547
|
+
# @klass.instance_eval do
|
548
|
+
# remote_defaults :on_failure => lambda {|e| :foo}
|
549
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:9999", :on_failure => lambda {|e| e.code.should == 0; :bar}
|
550
|
+
# end
|
551
|
+
#
|
552
|
+
# @klass.do_stuff.should == :bar
|
553
|
+
# end
|
554
|
+
# end
|
555
|
+
#
|
556
|
+
# describe "params" do
|
557
|
+
# it "should take :params as an argument" do
|
558
|
+
# @klass.instance_eval do
|
559
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :params => {:foo => :bar}
|
560
|
+
# end
|
561
|
+
#
|
562
|
+
# @klass.do_stuff.body.should include("QUERY_STRING=foo=bar")
|
563
|
+
# end
|
564
|
+
#
|
565
|
+
# it "should add :params from remote method definition with params passed in when called" do
|
566
|
+
# @klass.instance_eval do
|
567
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :params => {:foo => :bar}
|
568
|
+
# end
|
569
|
+
#
|
570
|
+
# result = @klass.do_stuff(:params => {:asdf => :jkl})
|
571
|
+
#
|
572
|
+
# # Make this test more robust to hash ordering.
|
573
|
+
# query_string = result.body.match(/QUERY_STRING=([^\n]+)/)
|
574
|
+
# params = query_string[1].split("&")
|
575
|
+
# ["asdf=jkl", "foo=bar"].each do |param|
|
576
|
+
# params.should include(param)
|
577
|
+
# end
|
578
|
+
# end
|
579
|
+
# end
|
580
|
+
#
|
581
|
+
# describe "memoize_responses" do
|
582
|
+
# it "should only make one call to the http method and the on_success handler if :memoize_responses => true" do
|
583
|
+
# success_mock = mock("success")
|
584
|
+
# success_mock.should_receive(:call).exactly(2).times
|
585
|
+
#
|
586
|
+
# @klass.instance_eval do
|
587
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :path => "/:file", :on_success => lambda {|e| success_mock.call; :foo}
|
588
|
+
# end
|
589
|
+
#
|
590
|
+
# first_return_val = @klass.do_stuff(:file => "user.html")
|
591
|
+
# second_return_val = @klass.do_stuff(:file => "post.html")
|
592
|
+
# third_return_val = @klass.do_stuff(:file => "user.html")
|
593
|
+
#
|
594
|
+
# first_return_val.should == :foo
|
595
|
+
# second_return_val.should == :foo
|
596
|
+
# third_return_val.should == :foo
|
597
|
+
# end
|
598
|
+
#
|
599
|
+
# it "should clear memoized responses after a full run" do
|
600
|
+
# success_mock = mock("success")
|
601
|
+
# success_mock.should_receive(:call).exactly(2).times
|
602
|
+
#
|
603
|
+
# @klass.instance_eval do
|
604
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :path => "/:file", :on_success => lambda {|e| success_mock.call; :foo}
|
605
|
+
# end
|
606
|
+
#
|
607
|
+
# @klass.do_stuff(:file => "user.html").should == :foo
|
608
|
+
# @klass.do_stuff(:file => "user.html").should == :foo
|
609
|
+
# end
|
610
|
+
# end
|
611
|
+
#
|
612
|
+
# describe "cache_response" do
|
613
|
+
# before(:each) do
|
614
|
+
# @cache = Class.new do
|
615
|
+
# def self.get(key)
|
616
|
+
# @cache ||= {}
|
617
|
+
# @cache[key]
|
618
|
+
# end
|
619
|
+
#
|
620
|
+
# def self.set(key, value, timeout = 0)
|
621
|
+
# @cache ||= {}
|
622
|
+
# @cache[key] = value
|
623
|
+
# end
|
624
|
+
# end
|
625
|
+
#
|
626
|
+
# @klass.instance_eval do
|
627
|
+
# define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :path => "/:file", :cache_responses => true, :on_success => lambda {|e| :foo}
|
628
|
+
# end
|
629
|
+
# end
|
630
|
+
#
|
631
|
+
# it "should pull from the cache if :cache_response => true" do
|
632
|
+
# @cache.should_receive(:get).and_return(:foo)
|
633
|
+
# @klass.cache = @cache
|
634
|
+
# Typhoeus.should_receive(:perform_easy_requests).exactly(0).times
|
635
|
+
# @klass.do_stuff.should == :foo
|
636
|
+
# end
|
637
|
+
#
|
638
|
+
# it "should only hit the cache once for the same value" do
|
639
|
+
# @cache.should_receive(:get).exactly(1).times.and_return(:foo)
|
640
|
+
# @klass.cache = @cache
|
641
|
+
# Typhoeus.should_receive(:perform_easy_requests).exactly(0).times
|
642
|
+
#
|
643
|
+
#
|
644
|
+
# first = @klass.do_stuff
|
645
|
+
# second = @klass.do_stuff
|
646
|
+
#
|
647
|
+
# first.should == :foo
|
648
|
+
# second.should == :foo
|
649
|
+
# end
|
650
|
+
#
|
651
|
+
# it "should only hit the cache once if there is a cache miss (don't check again and again inside the same block)." do
|
652
|
+
# @cache.should_receive(:get).exactly(1).times.and_return(nil)
|
653
|
+
# @cache.should_receive(:set).exactly(1).times
|
654
|
+
# @klass.cache = @cache
|
655
|
+
#
|
656
|
+
# first = @klass.do_stuff
|
657
|
+
# second = @klass.do_stuff
|
658
|
+
#
|
659
|
+
# first.should == :foo
|
660
|
+
# second.should == :foo
|
661
|
+
# end
|
662
|
+
#
|
663
|
+
# it "should store an object in the cache with a set ttl"
|
664
|
+
# it "should take a hash with get and set method pointers to enable custom caching behavior"
|
665
|
+
# end
|
666
|
+
# end # define_remote_method
|
667
|
+
#
|
668
|
+
# describe "cache_server" do
|
669
|
+
# it "should store a cache_server" do
|
670
|
+
# @klass.cache = :foo
|
671
|
+
# end
|
672
|
+
# end
|
673
|
+
#
|
674
|
+
# describe "get_memcache_resposne_key" do
|
675
|
+
# it "should return a key that is an and of the method name, args, and options" do
|
676
|
+
# @klass.get_memcache_response_key(:do_stuff, ["foo"]).should == "20630a9d4864c41cbbcb8bd8ac91ab4767e72107b93329aa2e6f5629037392f3"
|
697
677
|
# end
|
698
678
|
# end
|
679
|
+
#
|
680
|
+
# # describe "multiple with post" do
|
681
|
+
# # require 'rubygems'
|
682
|
+
# # require 'json'
|
683
|
+
# # it "shoudl do stuff" do
|
684
|
+
# # @klass.instance_eval do
|
685
|
+
# # define_remote_method :post_stuff, :path => "/entries/metas/:meta_id/ids", :base_uri => "http://localhost:4567", :method => :post
|
686
|
+
# # define_remote_method :get_stuff, :base_uri => "http://localhost:4567"
|
687
|
+
# # end
|
688
|
+
# #
|
689
|
+
# # Typhoeus.service_access do
|
690
|
+
# # @klass.post_stuff("paul-tv", :body => ["foo", "bar"].to_json) {|e| }
|
691
|
+
# # @klass.get_stuff {|e| }
|
692
|
+
# # end
|
693
|
+
# # end
|
694
|
+
# # end
|
699
695
|
end
|