goliath 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of goliath might be problematic. Click here for more details.
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.yardopts +2 -0
- data/Gemfile +3 -0
- data/LICENSE +66 -0
- data/README.md +86 -0
- data/Rakefile +18 -0
- data/examples/activerecord/config/srv.rb +7 -0
- data/examples/activerecord/srv.rb +37 -0
- data/examples/async_upload.rb +34 -0
- data/examples/conf_test.rb +27 -0
- data/examples/config/conf_test.rb +12 -0
- data/examples/config/echo.rb +1 -0
- data/examples/config/http_log.rb +7 -0
- data/examples/config/shared.rb +5 -0
- data/examples/custom_server.rb +57 -0
- data/examples/echo.rb +37 -0
- data/examples/gziped.rb +40 -0
- data/examples/hello_world.rb +10 -0
- data/examples/http_log.rb +85 -0
- data/examples/rack_routes.rb +44 -0
- data/examples/stream.rb +37 -0
- data/examples/valid.rb +19 -0
- data/goliath.gemspec +41 -0
- data/lib/goliath.rb +38 -0
- data/lib/goliath/api.rb +165 -0
- data/lib/goliath/application.rb +90 -0
- data/lib/goliath/connection.rb +94 -0
- data/lib/goliath/constants.rb +51 -0
- data/lib/goliath/env.rb +92 -0
- data/lib/goliath/goliath.rb +49 -0
- data/lib/goliath/headers.rb +37 -0
- data/lib/goliath/http_status_codes.rb +44 -0
- data/lib/goliath/plugins/latency.rb +33 -0
- data/lib/goliath/rack/default_mime_type.rb +30 -0
- data/lib/goliath/rack/default_response_format.rb +33 -0
- data/lib/goliath/rack/formatters/html.rb +90 -0
- data/lib/goliath/rack/formatters/json.rb +42 -0
- data/lib/goliath/rack/formatters/xml.rb +90 -0
- data/lib/goliath/rack/heartbeat.rb +23 -0
- data/lib/goliath/rack/jsonp.rb +38 -0
- data/lib/goliath/rack/params.rb +30 -0
- data/lib/goliath/rack/render.rb +66 -0
- data/lib/goliath/rack/tracer.rb +31 -0
- data/lib/goliath/rack/validation/boolean_value.rb +59 -0
- data/lib/goliath/rack/validation/default_params.rb +46 -0
- data/lib/goliath/rack/validation/numeric_range.rb +59 -0
- data/lib/goliath/rack/validation/request_method.rb +33 -0
- data/lib/goliath/rack/validation/required_param.rb +54 -0
- data/lib/goliath/rack/validation/required_value.rb +58 -0
- data/lib/goliath/rack/validation_error.rb +38 -0
- data/lib/goliath/request.rb +199 -0
- data/lib/goliath/response.rb +93 -0
- data/lib/goliath/runner.rb +236 -0
- data/lib/goliath/server.rb +149 -0
- data/lib/goliath/test_helper.rb +118 -0
- data/lib/goliath/version.rb +4 -0
- data/spec/integration/async_request_processing.rb +23 -0
- data/spec/integration/echo_spec.rb +27 -0
- data/spec/integration/keepalive_spec.rb +28 -0
- data/spec/integration/pipelining_spec.rb +43 -0
- data/spec/integration/valid_spec.rb +24 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/unit/connection_spec.rb +59 -0
- data/spec/unit/env_spec.rb +55 -0
- data/spec/unit/headers_spec.rb +53 -0
- data/spec/unit/rack/default_mime_type_spec.rb +34 -0
- data/spec/unit/rack/formatters/json_spec.rb +54 -0
- data/spec/unit/rack/formatters/xml_spec.rb +66 -0
- data/spec/unit/rack/heartbeat_spec.rb +47 -0
- data/spec/unit/rack/params_spec.rb +94 -0
- data/spec/unit/rack/render_spec.rb +87 -0
- data/spec/unit/rack/validation/boolean_value_spec.rb +54 -0
- data/spec/unit/rack/validation/default_params_spec.rb +71 -0
- data/spec/unit/rack/validation/numeric_range_spec.rb +96 -0
- data/spec/unit/rack/validation/request_method_spec.rb +47 -0
- data/spec/unit/rack/validation/required_param_spec.rb +92 -0
- data/spec/unit/rack/validation/required_value_spec.rb +99 -0
- data/spec/unit/rack/validation_error_spec.rb +40 -0
- data/spec/unit/request_spec.rb +59 -0
- data/spec/unit/response_spec.rb +35 -0
- data/spec/unit/runner_spec.rb +129 -0
- data/spec/unit/server_spec.rb +137 -0
- metadata +409 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/env'
|
3
|
+
require 'goliath/rack/default_mime_type'
|
4
|
+
|
5
|
+
describe Goliath::Rack::DefaultMimeType do
|
6
|
+
let(:app) { mock('app').as_null_object }
|
7
|
+
let(:dmt) { Goliath::Rack::DefaultMimeType.new(app) }
|
8
|
+
let(:env) do
|
9
|
+
env = Goliath::Env.new
|
10
|
+
env['status'] = mock('status').as_null_object
|
11
|
+
env
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'accept header cleanup' do
|
15
|
+
it 'handles a nil header' do
|
16
|
+
env['HTTP_ACCEPT'] = nil
|
17
|
+
lambda { dmt.call(env) }.should_not raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
%w(gzip deflate compressed identity).each do |type|
|
21
|
+
it "removes #{type} from the accept header" do
|
22
|
+
env['HTTP_ACCEPT'] = "text/html, #{type}, text/javascript"
|
23
|
+
dmt.call(env)
|
24
|
+
env['HTTP_ACCEPT'].should == 'text/html, text/javascript'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'sets to */* if all entries removed' do
|
29
|
+
env['HTTP_ACCEPT'] = 'identity'
|
30
|
+
dmt.call(env)
|
31
|
+
env['HTTP_ACCEPT'].should == '*/*'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/rack/formatters/json'
|
3
|
+
|
4
|
+
describe Goliath::Rack::Formatters::JSON do
|
5
|
+
it 'accepts an app' do
|
6
|
+
lambda { Goliath::Rack::Formatters::JSON.new('my app') }.should_not raise_error Exception
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'with a formatter' do
|
10
|
+
before(:each) do
|
11
|
+
@app = mock('app').as_null_object
|
12
|
+
@js = Goliath::Rack::Formatters::JSON.new(@app)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'checks content type for application/json' do
|
16
|
+
@js.json_response?({'Content-Type' => 'application/json'}).should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns false for non-applicaton/json types' do
|
20
|
+
@js.json_response?({'Content-Type' => 'application/xml'}).should be_false
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'calls the app with the provided environment' do
|
24
|
+
env_mock = mock('env').as_null_object
|
25
|
+
@app.should_receive(:call).with(env_mock).and_return([200, {}, {"a" => 1}])
|
26
|
+
@js.call(env_mock)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'formats the body into json if content-type is json' do
|
30
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/json'}, {:a => 1, :b => 2}])
|
31
|
+
|
32
|
+
status, header, body = @js.call({})
|
33
|
+
lambda { Yajl::Parser.parse(body.first)['a'].should == 1 }.should_not raise_error Exception
|
34
|
+
end
|
35
|
+
|
36
|
+
it "doesn't format to json if the type is not application/json" do
|
37
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/xml'}, {:a => 1, :b => 2}])
|
38
|
+
|
39
|
+
Yajl::Parser.should_not_receive(:encode)
|
40
|
+
status, header, body = @js.call({})
|
41
|
+
body[:a].should == 1
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns the status and headers' do
|
45
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/xml'}, {:a => 1, :b => 2}])
|
46
|
+
|
47
|
+
Yajl::Parser.should_not_receive(:encode)
|
48
|
+
status, header, body = @js.call({})
|
49
|
+
status.should == 200
|
50
|
+
header.should == {'Content-Type' => 'application/xml'}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/rack/formatters/xml'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
describe Goliath::Rack::Formatters::XML do
|
6
|
+
it 'accepts an app' do
|
7
|
+
lambda { Goliath::Rack::Formatters::XML.new('my app') }.should_not raise_error Exception
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'with a formatter' do
|
11
|
+
before(:each) do
|
12
|
+
@app = mock('app').as_null_object
|
13
|
+
@xml = Goliath::Rack::Formatters::XML.new(@app)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'checks content type for application/xml' do
|
17
|
+
@xml.xml_response?({'Content-Type' => 'application/xml'}).should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns false for non-applicaton/xml types' do
|
21
|
+
@xml.xml_response?({'Content-Type' => 'application/json'}).should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'calls the app with the provided environment' do
|
25
|
+
env_mock = mock('env').as_null_object
|
26
|
+
@app.should_receive(:call).with(env_mock).and_return([200, {}, {"a" => 1}])
|
27
|
+
@xml.call(env_mock)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'formats the body into xml if content-type is xml' do
|
31
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/xml'}, {:a => 1, :b => 2}])
|
32
|
+
|
33
|
+
status, header, body = @xml.call({})
|
34
|
+
lambda { Nokogiri.parse(body.first).search('a').inner_text.should == '1' }.should_not raise_error Exception
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'generates arrays correctly' do
|
38
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/xml'}, [1, 2]])
|
39
|
+
|
40
|
+
status, header, body = @xml.call({})
|
41
|
+
lambda {
|
42
|
+
doc = Nokogiri.parse(body.first)
|
43
|
+
doc.search('item').first.inner_text.should == '1'
|
44
|
+
doc.search('item').last.inner_text.should == '2'
|
45
|
+
}.should_not raise_error Exception
|
46
|
+
end
|
47
|
+
|
48
|
+
it "doesn't format to xml if the type is not application/xml" do
|
49
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/json'}, {:a => 1, :b => 2}])
|
50
|
+
|
51
|
+
@xml.should_not_receive(:to_xml)
|
52
|
+
status, header, body = @xml.call({})
|
53
|
+
body[:a].should == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'returns the status and headers' do
|
57
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/json'}, {:a => 1, :b => 2}])
|
58
|
+
|
59
|
+
@xml.should_not_receive(:to_xml)
|
60
|
+
status, header, body = @xml.call({})
|
61
|
+
status.should == 200
|
62
|
+
header.should == {'Content-Type' => 'application/json'}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/rack/heartbeat'
|
3
|
+
require 'goliath/env'
|
4
|
+
|
5
|
+
describe Goliath::Rack::Heartbeat do
|
6
|
+
it 'accepts an app' do
|
7
|
+
lambda { Goliath::Rack::Heartbeat.new('my app') }.should_not raise_error(Exception)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'with the middleware' do
|
11
|
+
before(:each) do
|
12
|
+
@app = mock('app').as_null_object
|
13
|
+
@env = Goliath::Env.new
|
14
|
+
@env['status'] = mock('status').as_null_object
|
15
|
+
@hb = Goliath::Rack::Heartbeat.new(@app)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'allows /status as a path prefix' do
|
19
|
+
@app.should_receive(:call)
|
20
|
+
@env['PATH_INFO'] = '/status_endpoint'
|
21
|
+
@hb.call(@env)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "doesn't call the app when request /status" do
|
25
|
+
@app.should_not_receive(:call)
|
26
|
+
@env['PATH_INFO'] = '/status'
|
27
|
+
@hb.call(@env)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns the status, headers and body from the app on non-/status' do
|
31
|
+
@env['PATH_INFO'] = '/v1'
|
32
|
+
@app.should_receive(:call).and_return([200, {'a' => 'b'}, {'c' => 'd'}])
|
33
|
+
status, headers, body = @hb.call(@env)
|
34
|
+
status.should == 200
|
35
|
+
headers.should == {'a' => 'b'}
|
36
|
+
body.should == {'c' => 'd'}
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns the correct status, headers and body on /status' do
|
40
|
+
@env['PATH_INFO'] = '/status'
|
41
|
+
status, headers, body = @hb.call(@env)
|
42
|
+
status.should == 200
|
43
|
+
headers.should == {}
|
44
|
+
body.should == 'OK'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/rack/params'
|
3
|
+
|
4
|
+
describe Goliath::Rack::Params do
|
5
|
+
it 'accepts an app' do
|
6
|
+
lambda { Goliath::Rack::Params.new('my app') }.should_not raise_error(Exception)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'with middleware' do
|
10
|
+
before(:each) do
|
11
|
+
@app = mock('app').as_null_object
|
12
|
+
@env = {}
|
13
|
+
@params = Goliath::Rack::Params.new(@app)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'parses the query string' do
|
17
|
+
@env['QUERY_STRING'] = 'foo=bar&baz=bonkey'
|
18
|
+
|
19
|
+
ret = @params.retrieve_params(@env)
|
20
|
+
ret['foo'].should == 'bar'
|
21
|
+
ret['baz'].should == 'bonkey'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'parses the post body' do
|
25
|
+
@env['rack.input'] = StringIO.new
|
26
|
+
@env['rack.input'] << "foo=bar&baz=bonkey"
|
27
|
+
@env['rack.input'].rewind
|
28
|
+
|
29
|
+
ret = @params.retrieve_params(@env)
|
30
|
+
ret['foo'].should == 'bar'
|
31
|
+
ret['baz'].should == 'bonkey'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'parses arrays of data' do
|
35
|
+
@env['QUERY_STRING'] = 'foo=bar&foo=baz&foo=foos'
|
36
|
+
|
37
|
+
ret = @params.retrieve_params(@env)
|
38
|
+
ret['foo'].is_a?(Array).should be_true
|
39
|
+
ret['foo'].length.should == 3
|
40
|
+
ret['foo'].should == %w(bar baz foos)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'combines query string and post body params' do
|
44
|
+
@env['QUERY_STRING'] = "baz=bar"
|
45
|
+
|
46
|
+
@env['rack.input'] = StringIO.new
|
47
|
+
@env['rack.input'] << "foos=bonkey"
|
48
|
+
@env['rack.input'].rewind
|
49
|
+
|
50
|
+
ret = @params.retrieve_params(@env)
|
51
|
+
ret['baz'].should == 'bar'
|
52
|
+
ret['foos'].should == 'bonkey'
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'handles empty query and post body' do
|
56
|
+
ret = @params.retrieve_params(@env)
|
57
|
+
ret.is_a?(Hash).should be_true
|
58
|
+
ret.should be_empty
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'prefers post body over query string' do
|
62
|
+
@env['QUERY_STRING'] = "foo=bar1&baz=bar"
|
63
|
+
|
64
|
+
@env['rack.input'] = StringIO.new
|
65
|
+
@env['rack.input'] << "foo=bar2&baz=bonkey"
|
66
|
+
@env['rack.input'].rewind
|
67
|
+
|
68
|
+
ret = @params.retrieve_params(@env)
|
69
|
+
ret['foo'].should == 'bar2'
|
70
|
+
ret['baz'].should == 'bonkey'
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'sets the params into the environment' do
|
74
|
+
@app.should_receive(:call).with do |app_env|
|
75
|
+
app_env.has_key?('params').should be_true
|
76
|
+
app_env['params']['a'].should == 'b'
|
77
|
+
end
|
78
|
+
|
79
|
+
@env['QUERY_STRING'] = "a=b"
|
80
|
+
@params.call(@env)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'returns status, headers and body from the app' do
|
84
|
+
app_headers = {'Content-Type' => 'hash'}
|
85
|
+
app_body = {:a => 1, :b => 2}
|
86
|
+
@app.should_receive(:call).and_return([200, app_headers, app_body])
|
87
|
+
|
88
|
+
status, headers, body = @params.call(@env)
|
89
|
+
status.should == 200
|
90
|
+
headers.should == app_headers
|
91
|
+
body.should == app_body
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/rack/render'
|
3
|
+
require 'goliath/goliath'
|
4
|
+
|
5
|
+
describe Goliath::Rack::Render do
|
6
|
+
let(:env) do
|
7
|
+
env = Goliath::Env.new
|
8
|
+
env['params'] = {}
|
9
|
+
env
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:app) { mock('app').as_null_object }
|
13
|
+
let(:render) { Goliath::Rack::Render.new(app) }
|
14
|
+
|
15
|
+
it 'accepts an app' do
|
16
|
+
lambda { Goliath::Rack::Render.new('my app') }.should_not raise_error(Exception)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns the status, body and app headers' do
|
20
|
+
app_body = {'c' => 'd'}
|
21
|
+
|
22
|
+
app.should_receive(:call).and_return([200, {'a' => 'b'}, app_body])
|
23
|
+
status, headers, body = render.call(env)
|
24
|
+
|
25
|
+
status.should == 200
|
26
|
+
headers['a'].should == 'b'
|
27
|
+
body.should == app_body
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'Vary' do
|
31
|
+
it 'adds Accept to provided Vary header' do
|
32
|
+
app.should_receive(:call).and_return([200, {'Vary' => 'Cookie'}, {}])
|
33
|
+
status, headers, body = render.call(env)
|
34
|
+
headers['Vary'].should == 'Cookie,Accept'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'sets Accept if there is no Vary header' do
|
38
|
+
app.should_receive(:call).and_return([200, {}, {}])
|
39
|
+
status, headers, body = render.call(env)
|
40
|
+
headers['Vary'].should == 'Accept'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'Content-Type' do
|
45
|
+
before(:each) do
|
46
|
+
app.should_receive(:call).and_return([200, {}, {}])
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'from header' do
|
50
|
+
%w(application/json text/html application/rss+xml application/xml).each do |type|
|
51
|
+
it "handles content type for #{type}" do
|
52
|
+
env['HTTP_ACCEPT'] = type
|
53
|
+
status, headers, body = render.call(env)
|
54
|
+
headers['Content-Type'].should =~ /^#{Regexp.escape(type)}/
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'from URL param' do
|
60
|
+
{'rss' => 'application/rss+xml',
|
61
|
+
'xml' => 'application/xml',
|
62
|
+
'html' => 'text/html',
|
63
|
+
'json' => 'application/json'}.each_pair do |format, content_type|
|
64
|
+
it "converts #{format} to #{content_type}" do
|
65
|
+
env['params']['format'] = format
|
66
|
+
status, headers, body = render.call(env)
|
67
|
+
headers['Content-Type'].should =~ /^#{Regexp.escape(content_type)}/
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'prefers URL format over header' do
|
73
|
+
env['HTTP_ACCEPT'] = 'application/xml'
|
74
|
+
env['params']['format'] = 'json'
|
75
|
+
status, headers, body = render.call(env)
|
76
|
+
headers['Content-Type'].should =~ %r{^application/json}
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'charset' do
|
80
|
+
it 'is set if not present' do
|
81
|
+
env['params']['format'] = 'json'
|
82
|
+
status, headers, body = render.call(env)
|
83
|
+
headers['Content-Type'].should =~ /; charset=utf-8$/
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/rack/validation/boolean_value'
|
3
|
+
|
4
|
+
describe Goliath::Rack::Validation::BooleanValue do
|
5
|
+
before(:each) do
|
6
|
+
@app = mock('app').as_null_object
|
7
|
+
@env = {'params' => {}}
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'with middleware' do
|
11
|
+
before(:each) do
|
12
|
+
@bv = Goliath::Rack::Validation::BooleanValue.new(@app, {:key => 'id', :default => true})
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'uses the default if the key is not present' do
|
16
|
+
@bv.call(@env)
|
17
|
+
@env['params']['id'].should == true
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'uses the default if the key is nil' do
|
21
|
+
@env['params']['id'] = nil
|
22
|
+
@bv.call(@env)
|
23
|
+
@env['params']['id'].should == true
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'uses the default if the key is blank' do
|
27
|
+
@env['params']['id'] = ""
|
28
|
+
@bv.call(@env)
|
29
|
+
@env['params']['id'].should == true
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'a random value is false' do
|
33
|
+
@env['params']['id'] = 'blarg'
|
34
|
+
@bv.call(@env)
|
35
|
+
@env['params']['id'].should == false
|
36
|
+
end
|
37
|
+
|
38
|
+
%w(t true TRUE T 1).each do |type|
|
39
|
+
it "considers #{type} true" do
|
40
|
+
@env['params']['id'] = type
|
41
|
+
@bv.call(@env)
|
42
|
+
@env['params']['id'].should == true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
%w(f false FALSE F 0).each do |type|
|
47
|
+
it "considers #{type} false" do
|
48
|
+
@env['params']['id'] = type
|
49
|
+
@bv.call(@env)
|
50
|
+
@env['params']['id'].should == false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/rack/validation/default_params'
|
3
|
+
|
4
|
+
describe Goliath::Rack::Validation::DefaultParams do
|
5
|
+
it 'accepts an app' do
|
6
|
+
opts = {:defaults => ['title'], :key => 'fields'}
|
7
|
+
lambda { Goliath::Rack::Validation::DefaultParams.new('my app', opts) }.should_not raise_error(Exception)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'requires defaults to be set' do
|
11
|
+
lambda { Goliath::Rack::Validation::DefaultParams.new('my app', {:key => 'test'}) }.should raise_error(Exception)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'requires key to be set' do
|
15
|
+
lambda { Goliath::Rack::Validation::DefaultParams.new('my app', {:defaults => 'test'}) }.should raise_error(Exception)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'with middleware' do
|
19
|
+
before(:each) do
|
20
|
+
@app = mock('app').as_null_object
|
21
|
+
@env = {'params' => {}}
|
22
|
+
@rf = Goliath::Rack::Validation::DefaultParams.new(@app, {:key => 'fl', :defaults => ['title', 'link']})
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'passes through provided key if set' do
|
26
|
+
@env['params']['fl'] = ['pubdate', 'content']
|
27
|
+
@rf.call(@env)
|
28
|
+
@env['params']['fl'].should == ['pubdate', 'content']
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'sets defaults if no key set' do
|
32
|
+
@rf.call(@env)
|
33
|
+
@env['params']['fl'].should == ['title', 'link']
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'sets defaults if no key set' do
|
37
|
+
@env['params']['fl'] = nil
|
38
|
+
@rf.call(@env)
|
39
|
+
@env['params']['fl'].should == ['title', 'link']
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'sets defaults if no key is empty' do
|
43
|
+
@env['params']['fl'] = []
|
44
|
+
@rf.call(@env)
|
45
|
+
@env['params']['fl'].should == ['title', 'link']
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'handles a single item' do
|
49
|
+
@env['params']['fl'] = 'title'
|
50
|
+
@rf.call(@env)
|
51
|
+
@env['params']['fl'].should == 'title'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'handles a blank string' do
|
55
|
+
@env['params']['fl'] = ''
|
56
|
+
@rf.call(@env)
|
57
|
+
@env['params']['fl'].should == ['title', 'link']
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'returns the app status, headers and body' do
|
61
|
+
app_headers = {'Content-Type' => 'asdf'}
|
62
|
+
app_body = {'a' => 'b'}
|
63
|
+
@app.should_receive(:call).and_return([200, app_headers, app_body])
|
64
|
+
|
65
|
+
status, headers, body = @rf.call(@env)
|
66
|
+
status.should == 200
|
67
|
+
headers.should == app_headers
|
68
|
+
body.should == app_body
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|