alice 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ module Alice
2
+ class Response::ActiveSupportJson < Response::Middleware
3
+ begin
4
+ if !defined?(ActiveSupport::JSON)
5
+ require 'active_support'
6
+ end
7
+
8
+ def self.register_on_complete(env)
9
+ env[:response].on_complete do |finished_env|
10
+ finished_env[:body] = ActiveSupport::JSON.decode(finished_env[:body])
11
+ end
12
+ end
13
+ rescue LoadError => e
14
+ self.load_error = e
15
+ end
16
+
17
+ def initialize(app)
18
+ super
19
+ @parser = nil
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ module Alice
2
+ class Response::Yajl < Response::Middleware
3
+ begin
4
+ require 'yajl'
5
+
6
+ def self.register_on_complete(env)
7
+ env[:response].on_complete do |finished_env|
8
+ finished_env[:body] = Yajl::Parser.parse(finished_env[:body])
9
+ end
10
+ end
11
+ rescue LoadError => e
12
+ self.load_error = e
13
+ end
14
+
15
+ def initialize(app)
16
+ super
17
+ @parser = nil
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,157 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'helper'))
2
+
3
+ if Alice::TestCase::LIVE_SERVER
4
+ module Adapters
5
+ class LiveTest < Alice::TestCase
6
+ Alice::Adapter.all_loaded_constants.each do |adapter|
7
+ describe "with #{adapter} adapter" do
8
+ before do
9
+ @connection = Alice::Connection.new LIVE_SERVER do
10
+ use adapter
11
+ end
12
+ end
13
+
14
+ describe "#get" do
15
+ it "raises on 404" do
16
+ assert_raise(Alice::Error::ResourceNotFound) { @connection.get('/nothing') }
17
+ end
18
+
19
+ it "retrieves the response body" do
20
+ assert_equal 'hello world', @connection.get('hello_world').body
21
+ end
22
+
23
+ it "send url-encoded params" do
24
+ resp = @connection.get do |req|
25
+ req.url 'hello', 'name' => 'zack'
26
+ end
27
+ assert_equal('hello zack', resp.body)
28
+ end
29
+
30
+ it "retrieves the response headers" do
31
+ assert_equal 'text/html', @connection.get('hello_world').headers['content-type']
32
+ end
33
+ end
34
+
35
+ describe "#post" do
36
+ it "raises on 404" do
37
+ assert_raise(Alice::Error::ResourceNotFound) { @connection.post('/nothing') }
38
+ end
39
+
40
+ it "send url-encoded params" do
41
+ resp = @connection.post do |req|
42
+ req.url 'echo_name'
43
+ req.body = {'name' => 'zack'}
44
+ end
45
+ assert_equal %("zack"), resp.body
46
+ end
47
+
48
+ it "send url-encoded nested params" do
49
+ resp = @connection.post do |req|
50
+ req.url 'echo_name'
51
+ req.body = {'name' => {'first' => 'zack'}}
52
+ end
53
+ assert_equal %({"first"=>"zack"}), resp.body
54
+ end
55
+
56
+ it "retrieves the response headers" do
57
+ assert_equal 'text/html', @connection.post('echo_name').headers['content-type']
58
+ end
59
+ end
60
+
61
+ # http://github.com/toland/patron/issues/#issue/9
62
+ if ENV['FORCE'] || adapter != Alice::Adapter::Patron
63
+ describe "#put" do
64
+ it "raises on 404" do
65
+ assert_raise(Alice::Error::ResourceNotFound) { @connection.put('/nothing') }
66
+ end
67
+
68
+ it "send url-encoded params" do
69
+ resp = @connection.put do |req|
70
+ req.url 'echo_name'
71
+ req.body = {'name' => 'zack'}
72
+ end
73
+ assert_equal %("zack"), resp.body
74
+ end
75
+
76
+ it "send url-encoded nested params" do
77
+ resp = @connection.put do |req|
78
+ req.url 'echo_name'
79
+ req.body = {'name' => {'first' => 'zack'}}
80
+ end
81
+ assert_equal %({"first"=>"zack"}), resp.body
82
+ end
83
+
84
+ it "retrieves the response headers" do
85
+ assert_equal 'text/html', @connection.put('echo_name').headers['content-type']
86
+ end
87
+ end
88
+ end
89
+
90
+ # http://github.com/pauldix/typhoeus/issues#issue/7
91
+ if ENV['FORCE'] || adapter != Alice::Adapter::Typhoeus
92
+ describe "#head" do
93
+ it "raises on 404" do
94
+ assert_raise(Alice::Error::ResourceNotFound) { @connection.head('/nothing') }
95
+ end
96
+
97
+ it "send url-encoded params" do
98
+ resp = @connection.head do |req|
99
+ req.url 'hello', 'name' => 'zack'
100
+ end
101
+ assert_equal 'text/html', resp.headers['content-type']
102
+ end
103
+
104
+ it "retrieves no response body" do
105
+ assert_equal '', @connection.head('hello_world').body.to_s
106
+ end
107
+
108
+ it "retrieves the response headers" do
109
+ assert_equal 'text/html', @connection.head('hello_world').headers['content-type']
110
+ end
111
+ end
112
+ end
113
+
114
+ describe "#delete" do
115
+ it "raises on 404" do
116
+ assert_raise(Alice::Error::ResourceNotFound) { @connection.delete('/nothing') }
117
+ end
118
+
119
+ it "retrieves the response headers" do
120
+ assert_equal 'text/html', @connection.delete('delete_with_json').headers['content-type']
121
+ end
122
+
123
+ it "retrieves the body" do
124
+ assert_match /deleted/, @connection.delete('delete_with_json').body
125
+ end
126
+ end
127
+
128
+ describe "async requests" do
129
+ it "clears parallel manager after running a single request" do
130
+ assert !@connection.in_parallel?
131
+ resp = @connection.get('hello_world')
132
+ assert !@connection.in_parallel?
133
+ assert_equal 'hello world', @connection.get('hello_world').body
134
+ end
135
+
136
+ it "uses parallel manager to run multiple json requests" do
137
+ resp1, resp2 = nil, nil
138
+
139
+ @connection.in_parallel(adapter.setup_parallel_manager) do
140
+ resp1 = @connection.get('json')
141
+ resp2 = @connection.get('json')
142
+ if adapter.supports_parallel_requests?
143
+ assert @connection.in_parallel?
144
+ assert_nil resp1.body
145
+ assert_nil resp2.body
146
+ end
147
+ end
148
+ assert !@connection.in_parallel?
149
+ assert_equal '[1,2,3]', resp1.body
150
+ assert_equal '[1,2,3]', resp2.body
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'helper'))
2
+
3
+ module Adapters
4
+ class TestMiddleware < Alice::TestCase
5
+ describe "Test Middleware with simple path" do
6
+ before :all do
7
+ @conn = Alice::Connection.new do
8
+ adapter :test do |stub|
9
+ stub.get('/hello') { [200, {'Content-Type' => 'text/html'}, 'hello'] }
10
+ end
11
+ end
12
+ @resp = @conn.get('/hello')
13
+ end
14
+
15
+ it "sets status" do
16
+ assert_equal 200, @resp.status
17
+ end
18
+
19
+ it "sets headers" do
20
+ assert_equal 'text/html', @resp.headers['Content-Type']
21
+ end
22
+
23
+ it "sets body" do
24
+ assert_equal 'hello', @resp.body
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'helper'))
2
+
3
+ if Alice::Adapter::Typhoeus.loaded?
4
+ module Adapters
5
+ class TestTyphoeus < Alice::TestCase
6
+ describe "#parse_response_headers" do
7
+ before do
8
+ @adapter = Alice::Adapter::Typhoeus.new
9
+ end
10
+
11
+ it "leaves http status line out" do
12
+ headers = @adapter.parse_response_headers("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n")
13
+ assert_equal %w(content-type), headers.keys
14
+ end
15
+
16
+ it "parses lower-cased header name and value" do
17
+ headers = @adapter.parse_response_headers("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n")
18
+ assert_equal 'text/html', headers['content-type']
19
+ end
20
+
21
+ it "parses lower-cased header name and value with colon" do
22
+ headers = @adapter.parse_response_headers("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nLocation: http://sushi.com/\r\n\r\n")
23
+ assert_equal 'http://sushi.com/', headers['location']
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ class TestConnectionApps < Alice::TestCase
4
+ class TestAdapter
5
+ def initialize(app)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ [200, {}, env[:test]]
11
+ end
12
+ end
13
+
14
+ class TestMiddleWare
15
+ def initialize(app)
16
+ @app = app
17
+ end
18
+
19
+ def call(env)
20
+ env[:test] = 'hi'
21
+ @app.call(env)
22
+ end
23
+ end
24
+
25
+ before do
26
+ @conn = Alice::Connection.new do
27
+ use TestMiddleWare
28
+ use TestAdapter
29
+ end
30
+ class << @conn.builder
31
+ attr_reader :ins
32
+ end
33
+ end
34
+
35
+ describe "#builder" do
36
+ it "is built from Alice::Connection constructor" do
37
+ assert_kind_of Rack::Builder, @conn.builder
38
+ assert_equal 3, @conn.builder.ins.size
39
+ end
40
+
41
+ it "adds middleware to the Builder stack" do
42
+ assert_kind_of TestMiddleWare, @conn.builder.ins[0].call(nil)
43
+ assert_kind_of TestAdapter, @conn.builder.ins[1].call(nil)
44
+ end
45
+ end
46
+
47
+ describe "#to_app" do
48
+ it "returns rack-compatible object" do
49
+ assert @conn.to_app.respond_to?(:call)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,167 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ class TestConnection < Alice::TestCase
4
+ describe "#initialize" do
5
+ it "parses @host out of given url" do
6
+ conn = Alice::Connection.new "http://sushi.com"
7
+ assert_equal 'sushi.com', conn.host
8
+ end
9
+
10
+ it "parses nil @port out of given url" do
11
+ conn = Alice::Connection.new "http://sushi.com"
12
+ assert_nil conn.port
13
+ end
14
+
15
+ it "parses @scheme out of given url" do
16
+ conn = Alice::Connection.new "http://sushi.com"
17
+ assert_equal 'http', conn.scheme
18
+ end
19
+
20
+ it "parses @port out of given url" do
21
+ conn = Alice::Connection.new "http://sushi.com:815"
22
+ assert_equal 815, conn.port
23
+ end
24
+
25
+ it "parses nil @path_prefix out of given url" do
26
+ conn = Alice::Connection.new "http://sushi.com"
27
+ assert_equal '/', conn.path_prefix
28
+ end
29
+
30
+ it "parses @path_prefix out of given url" do
31
+ conn = Alice::Connection.new "http://sushi.com/fish"
32
+ assert_equal '/fish', conn.path_prefix
33
+ end
34
+
35
+ it "parses @path_prefix out of given url option" do
36
+ conn = Alice::Connection.new :url => "http://sushi.com/fish"
37
+ assert_equal '/fish', conn.path_prefix
38
+ end
39
+
40
+ it "stores default params from options" do
41
+ conn = Alice::Connection.new :params => {:a => 1}
42
+ assert_equal 1, conn.params['a']
43
+ end
44
+
45
+ it "stores default params from uri" do
46
+ conn = Alice::Connection.new "http://sushi.com/fish?a=1", :params => {'b' => '2'}
47
+ assert_equal '1', conn.params['a']
48
+ assert_equal '2', conn.params['b']
49
+ end
50
+
51
+ it "stores default headers from options" do
52
+ conn = Alice::Connection.new :headers => {:a => 1}
53
+ assert_equal '1', conn.headers['A']
54
+ end
55
+ end
56
+
57
+ describe "#build_url" do
58
+ it "uses Connection#host as default URI host" do
59
+ conn = Alice::Connection.new
60
+ conn.host = 'sushi.com'
61
+ uri = conn.build_url("/sake.html")
62
+ assert_equal 'sushi.com', uri.host
63
+ end
64
+
65
+ it "uses Connection#port as default URI port" do
66
+ conn = Alice::Connection.new
67
+ conn.port = 23
68
+ uri = conn.build_url("http://sushi.com")
69
+ assert_equal 23, uri.port
70
+ end
71
+
72
+ it "uses Connection#scheme as default URI scheme" do
73
+ conn = Alice::Connection.new 'http://sushi.com'
74
+ uri = conn.build_url("/sake.html")
75
+ assert_equal 'http', uri.scheme
76
+ end
77
+
78
+ it "uses Connection#path_prefix to customize the path" do
79
+ conn = Alice::Connection.new
80
+ conn.path_prefix = '/fish'
81
+ uri = conn.build_url("sake.html")
82
+ assert_equal '/fish/sake.html', uri.path
83
+ end
84
+
85
+ it "uses '/' Connection#path_prefix to customize the path" do
86
+ conn = Alice::Connection.new
87
+ conn.path_prefix = '/'
88
+ uri = conn.build_url("sake.html")
89
+ assert_equal '/sake.html', uri.path
90
+ end
91
+
92
+ it "forces Connection#path_prefix to be absolute" do
93
+ conn = Alice::Connection.new
94
+ conn.path_prefix = 'fish'
95
+ uri = conn.build_url("sake.html")
96
+ assert_equal '/fish/sake.html', uri.path
97
+ end
98
+
99
+ it "ignores Connection#path_prefix trailing slash" do
100
+ conn = Alice::Connection.new
101
+ conn.path_prefix = '/fish/'
102
+ uri = conn.build_url("sake.html")
103
+ assert_equal '/fish/sake.html', uri.path
104
+ end
105
+
106
+ it "allows absolute URI to ignore Connection#path_prefix" do
107
+ conn = Alice::Connection.new
108
+ conn.path_prefix = '/fish'
109
+ uri = conn.build_url("/sake.html")
110
+ assert_equal '/sake.html', uri.path
111
+ end
112
+
113
+ it "parses url/params into #path" do
114
+ conn = Alice::Connection.new
115
+ uri = conn.build_url("http://sushi.com/sake.html")
116
+ assert_equal '/sake.html', uri.path
117
+ end
118
+
119
+ it "parses url/params into #query" do
120
+ conn = Alice::Connection.new
121
+ uri = conn.build_url("http://sushi.com/sake.html", 'a[b]' => '1 + 2')
122
+ assert_equal "a%5Bb%5D=1%20%2B%202", uri.query
123
+ end
124
+
125
+ it "mashes default params and given params together" do
126
+ conn = Alice::Connection.new 'http://sushi.com/api?token=abc', :params => {'format' => 'json'}
127
+ url = conn.build_url("nigiri?page=1", :limit => 5)
128
+ assert_match /limit=5/, url.query
129
+ assert_match /page=1/, url.query
130
+ assert_match /format=json/, url.query
131
+ assert_match /token=abc/, url.query
132
+ end
133
+
134
+ it "overrides default params with given params" do
135
+ conn = Alice::Connection.new 'http://sushi.com/api?token=abc', :params => {'format' => 'json'}
136
+ url = conn.build_url("nigiri?page=1", :limit => 5, :token => 'def', :format => 'xml')
137
+ assert_match /limit=5/, url.query
138
+ assert_match /page=1/, url.query
139
+ assert_match /format=xml/, url.query
140
+ assert_match /token=def/, url.query
141
+ assert_no_match /format=json/, url.query
142
+ assert_no_match /token=abc/, url.query
143
+ end
144
+
145
+ it "parses url into #host" do
146
+ conn = Alice::Connection.new
147
+ uri = conn.build_url("http://sushi.com/sake.html")
148
+ assert_equal "sushi.com", uri.host
149
+ end
150
+
151
+ it "parses url into #port" do
152
+ conn = Alice::Connection.new
153
+ uri = conn.build_url("http://sushi.com/sake.html")
154
+ assert_nil uri.port
155
+ end
156
+ end
157
+
158
+ describe "#params_to_query" do
159
+ it "converts hash of params to URI-escaped query string" do
160
+ conn = Alice::Connection.new
161
+ class << conn
162
+ public :build_query
163
+ end
164
+ assert_equal "a%5Bb%5D=1%20%2B%202", conn.build_query('a[b]' => '1 + 2')
165
+ end
166
+ end
167
+ end