alice 0.1.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,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