goliath 0.9.1 → 0.9.2
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 +1 -0
- data/HISTORY +50 -0
- data/README.md +2 -0
- data/examples/activerecord/srv.rb +1 -3
- data/examples/async_aroundware_demo.rb +81 -0
- data/examples/async_upload.rb +1 -2
- data/examples/auth_and_rate_limit.rb +143 -0
- data/examples/chunked_streaming.rb +37 -0
- data/examples/conf_test.rb +1 -3
- data/examples/config/auth_and_rate_limit.rb +30 -0
- data/examples/config/template.rb +8 -0
- data/examples/content_stream.rb +1 -3
- data/examples/echo.rb +8 -6
- data/examples/env_use_statements.rb +17 -0
- data/examples/gziped.rb +1 -3
- data/examples/public/stylesheets/style.css +296 -0
- data/examples/rack_routes.rb +65 -3
- data/examples/rasterize/rasterize.js +15 -0
- data/examples/rasterize/rasterize.rb +36 -0
- data/examples/rasterize/rasterize_and_shorten.rb +37 -0
- data/examples/stream.rb +2 -2
- data/examples/template.rb +48 -0
- data/examples/test_rig.rb +125 -0
- data/examples/valid.rb +4 -2
- data/examples/views/debug.haml +4 -0
- data/examples/views/joke.markdown +13 -0
- data/examples/views/layout.erb +12 -0
- data/examples/views/layout.haml +39 -0
- data/examples/views/root.haml +28 -0
- data/goliath.gemspec +10 -3
- data/lib/goliath.rb +0 -36
- data/lib/goliath/api.rb +137 -26
- data/lib/goliath/application.rb +71 -21
- data/lib/goliath/connection.rb +4 -2
- data/lib/goliath/constants.rb +1 -0
- data/lib/goliath/env.rb +40 -1
- data/lib/goliath/goliath.rb +30 -15
- data/lib/goliath/headers.rb +2 -2
- data/lib/goliath/plugins/latency.rb +8 -2
- data/lib/goliath/rack.rb +18 -0
- data/lib/goliath/rack/async_aroundware.rb +56 -0
- data/lib/goliath/rack/async_middleware.rb +93 -0
- data/lib/goliath/rack/builder.rb +42 -0
- data/lib/goliath/rack/default_response_format.rb +3 -15
- data/lib/goliath/rack/formatters.rb +11 -0
- data/lib/goliath/rack/formatters/html.rb +2 -18
- data/lib/goliath/rack/formatters/json.rb +2 -17
- data/lib/goliath/rack/formatters/plist.rb +32 -0
- data/lib/goliath/rack/formatters/xml.rb +23 -31
- data/lib/goliath/rack/formatters/yaml.rb +27 -0
- data/lib/goliath/rack/jsonp.rb +1 -13
- data/lib/goliath/rack/params.rb +55 -27
- data/lib/goliath/rack/render.rb +13 -22
- data/lib/goliath/rack/templates.rb +357 -0
- data/lib/goliath/rack/tracer.rb +11 -12
- data/lib/goliath/rack/validation.rb +12 -0
- data/lib/goliath/rack/validation/default_params.rb +0 -2
- data/lib/goliath/rack/validation/numeric_range.rb +11 -2
- data/lib/goliath/rack/validation/request_method.rb +3 -2
- data/lib/goliath/rack/validation/required_param.rb +13 -11
- data/lib/goliath/rack/validation/required_value.rb +11 -15
- data/lib/goliath/rack/validator.rb +51 -0
- data/lib/goliath/request.rb +34 -20
- data/lib/goliath/response.rb +3 -2
- data/lib/goliath/runner.rb +5 -11
- data/lib/goliath/server.rb +2 -1
- data/lib/goliath/synchrony/mongo_receiver.rb +64 -0
- data/lib/goliath/synchrony/response_receiver.rb +64 -0
- data/lib/goliath/test_helper.rb +39 -21
- data/lib/goliath/validation.rb +2 -0
- data/lib/goliath/{rack/validation_error.rb → validation/error.rb} +0 -16
- data/lib/goliath/validation/standard_http_errors.rb +31 -0
- data/lib/goliath/version.rb +1 -1
- data/spec/integration/http_log_spec.rb +16 -16
- data/spec/integration/rack_routes_spec.rb +144 -0
- data/spec/integration/reloader_spec.rb +4 -4
- data/spec/integration/template_spec.rb +54 -0
- data/spec/integration/trace_spec.rb +23 -0
- data/spec/integration/valid_spec.rb +21 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/unit/api_spec.rb +30 -0
- data/spec/unit/rack/builder_spec.rb +40 -0
- data/spec/unit/rack/formatters/plist_spec.rb +51 -0
- data/spec/unit/rack/formatters/yaml_spec.rb +53 -0
- data/spec/unit/rack/params_spec.rb +22 -0
- data/spec/unit/rack/render_spec.rb +10 -5
- data/spec/unit/rack/validation/numeric_range_spec.rb +8 -1
- data/spec/unit/rack/validation/request_method_spec.rb +8 -8
- data/spec/unit/rack/validation/required_param_spec.rb +19 -15
- data/spec/unit/rack/validation/required_value_spec.rb +10 -13
- data/spec/unit/server_spec.rb +4 -4
- data/spec/unit/validation/standard_http_errors_spec.rb +21 -0
- metadata +177 -35
- data/spec/unit/rack/validation_error_spec.rb +0 -40
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require File.join(File.dirname(__FILE__), '../../', 'examples/echo')
|
3
|
+
|
4
|
+
|
5
|
+
describe Goliath::Rack::Tracer do
|
6
|
+
let(:err) { Proc.new { fail "API request failed" } }
|
7
|
+
|
8
|
+
it 'injects a trace param on a 200 (via async callback)' do
|
9
|
+
with_api(Echo) do
|
10
|
+
get_request({:query => {:echo => 'test'}}, err) do |c|
|
11
|
+
c.response_header['X_POSTRANK'].should =~ /trace\.start: [\d\.]+, total: [\d\.]+/
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'injects a trace param on a 400 (direct callback)' do
|
17
|
+
with_api(Echo) do
|
18
|
+
get_request({}, err) do |c|
|
19
|
+
c.response_header['X_POSTRANK'].should =~ /trace\.start: [\d\.]+, total: [\d\.]+/
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'json'
|
2
3
|
require File.join(File.dirname(__FILE__), '../../', 'examples/valid')
|
3
4
|
|
4
5
|
describe Valid do
|
@@ -20,3 +21,23 @@ describe Valid do
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
24
|
+
|
25
|
+
class ValidationErrorInEndpoint < Goliath::API
|
26
|
+
def response(env)
|
27
|
+
raise Goliath::Validation::Error.new(420, 'You Must Chill')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe ValidationErrorInEndpoint do
|
32
|
+
let(:err) { Proc.new { fail "API request failed" } }
|
33
|
+
|
34
|
+
it 'handles Goliath::Validation::Error correctly' do
|
35
|
+
with_api(ValidationErrorInEndpoint) do
|
36
|
+
get_request({}, err) do |c|
|
37
|
+
c.response.should == '[:error, "You Must Chill"]'
|
38
|
+
c.response_header.status.should == 420
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/api'
|
3
|
+
|
4
|
+
describe Goliath::API do
|
5
|
+
|
6
|
+
DummyApi = Class.new(Goliath::API)
|
7
|
+
|
8
|
+
describe 'middlewares' do
|
9
|
+
it "doesn't change after multi calls" do
|
10
|
+
2.times { Goliath::API.should have(2).middlewares }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ".maps?" do
|
15
|
+
context "when not using maps" do
|
16
|
+
it "returns false" do
|
17
|
+
DummyApi.maps?.should be_false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when using maps" do
|
22
|
+
it "returns true" do
|
23
|
+
DummyApi.map "/foo"
|
24
|
+
DummyApi.maps?.should be_true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Goliath::Rack::Builder do
|
5
|
+
|
6
|
+
SimpleMiddleware = Class.new
|
7
|
+
NestedMiddleware = Class.new
|
8
|
+
|
9
|
+
class NestedClassApi < Goliath::API
|
10
|
+
use NestedMiddleware, 'class'
|
11
|
+
end
|
12
|
+
|
13
|
+
class NestedBlockApi < Goliath::API
|
14
|
+
use NestedMiddleware, 'block'
|
15
|
+
end
|
16
|
+
|
17
|
+
class SimpleRouter < Goliath::API
|
18
|
+
use SimpleMiddleware
|
19
|
+
map "/class", NestedClassApi
|
20
|
+
map "/block" do
|
21
|
+
run NestedBlockApi.new
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:router) { SimpleRouter.new }
|
26
|
+
|
27
|
+
describe '.build' do
|
28
|
+
|
29
|
+
it "builds rack app for api" do
|
30
|
+
Rack::Builder.should_receive(:app)
|
31
|
+
Goliath::Rack::Builder.build(router.class, router)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "loads rack/goliath middlewares" do
|
35
|
+
SimpleMiddleware.should_receive(:new)
|
36
|
+
Goliath::Rack::Builder.build(router.class, router)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/rack/formatters/plist'
|
3
|
+
|
4
|
+
describe Goliath::Rack::Formatters::PLIST do
|
5
|
+
# this sucks, but I had install problems with nokogiri-plist
|
6
|
+
# and I would rather not use an alternative library that requires libxml or rexml
|
7
|
+
before(:all) do
|
8
|
+
class Object
|
9
|
+
def to_plist(*args) "plist: #{to_s}" end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:all) do
|
14
|
+
class Object
|
15
|
+
undef to_plist
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'accepts an app' do
|
20
|
+
lambda { Goliath::Rack::Formatters::PLIST.new('my app') }.should_not raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'with a formatter' do
|
24
|
+
before(:each) do
|
25
|
+
@app = mock('app').as_null_object
|
26
|
+
@m = Goliath::Rack::Formatters::PLIST.new(@app)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'formats the body into plist if content-type is plist' do
|
30
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/x-plist'}, {:a => 1, :b => 2}])
|
31
|
+
|
32
|
+
status, header, body = @m.call({})
|
33
|
+
body.should == ["plist: {:a=>1, :b=>2}"]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "doesn't format to plist if the type is not plist" do
|
37
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/xml'}, {:a => 1, :b => 2}])
|
38
|
+
status, header, body = @m.call({})
|
39
|
+
status.should == 200
|
40
|
+
header.should == {'Content-Type' => 'application/xml'}
|
41
|
+
|
42
|
+
body[:a].should == 1
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns the status and headers' do
|
46
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/xml'}, {:a => 1, :b => 2}])
|
47
|
+
|
48
|
+
status, header, body = @m.call({})
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'goliath/rack/formatters/yaml'
|
3
|
+
|
4
|
+
describe Goliath::Rack::Formatters::YAML do
|
5
|
+
it 'accepts an app' do
|
6
|
+
lambda { Goliath::Rack::Formatters::YAML.new('my app') }.should_not raise_error
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'with a formatter' do
|
10
|
+
before(:each) do
|
11
|
+
@app = mock('app').as_null_object
|
12
|
+
@ym = Goliath::Rack::Formatters::YAML.new(@app)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'checks content type for text/yaml' do
|
16
|
+
@ym.yaml_response?({'Content-Type' => 'text/yaml'}).should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns false for non-applicaton/yaml types' do
|
20
|
+
@ym.yaml_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
|
+
@ym.call(env_mock)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'formats the body into yaml if content-type is yaml' do
|
30
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'text/yaml'}, {:a => 1, :b => 2}])
|
31
|
+
|
32
|
+
status, header, body = @ym.call({})
|
33
|
+
lambda { YAML.load(body.first)[:a].should == 1 }.should_not raise_error
|
34
|
+
end
|
35
|
+
|
36
|
+
it "doesn't format to yaml if the type is not text/yaml" do
|
37
|
+
@app.should_receive(:call).and_return([200, {'Content-Type' => 'application/xml'}, {:a => 1, :b => 2}])
|
38
|
+
|
39
|
+
YAML.should_not_receive(:encode)
|
40
|
+
status, header, body = @ym.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
|
+
YAML.should_not_receive(:encode)
|
48
|
+
status, header, body = @ym.call({})
|
49
|
+
status.should == 200
|
50
|
+
header.should == {'Content-Type' => 'application/xml'}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -19,6 +19,7 @@ describe Goliath::Rack::Params do
|
|
19
19
|
|
20
20
|
ret = @params.retrieve_params(@env)
|
21
21
|
ret['foo'].should == 'bar'
|
22
|
+
ret[:foo].should == 'bar'
|
22
23
|
ret['baz'].should == 'bonkey'
|
23
24
|
end
|
24
25
|
|
@@ -38,6 +39,8 @@ describe Goliath::Rack::Params do
|
|
38
39
|
ret['foo'].should == 'bar'
|
39
40
|
ret['baz'].should == 'bonkey'
|
40
41
|
ret['zonk'].should == {'donk' => 'monk'}
|
42
|
+
ret[:zonk].should == {'donk' => 'monk'}
|
43
|
+
ret[:zonk][:donk].should == 'monk'
|
41
44
|
end
|
42
45
|
|
43
46
|
it 'parses arrays of data' do
|
@@ -47,6 +50,7 @@ describe Goliath::Rack::Params do
|
|
47
50
|
ret['foo'].is_a?(Array).should be_true
|
48
51
|
ret['foo'].length.should == 3
|
49
52
|
ret['foo'].should == %w(bar baz foos)
|
53
|
+
ret[:foo].should == %w(bar baz foos)
|
50
54
|
end
|
51
55
|
|
52
56
|
it 'parses multipart data' do
|
@@ -67,6 +71,7 @@ Berry\r
|
|
67
71
|
|
68
72
|
ret = @params.retrieve_params(@env)
|
69
73
|
ret['submit-name'].should == 'Larry'
|
74
|
+
ret[:"submit-name"].should == 'Larry'
|
70
75
|
ret['submit-name-with-content'].should == 'Berry'
|
71
76
|
end
|
72
77
|
|
@@ -140,8 +145,25 @@ Berry\r
|
|
140
145
|
|
141
146
|
ret = @params.retrieve_params(@env)
|
142
147
|
ret['foo'].should == 'bar'
|
148
|
+
ret[:foo].should == 'bar'
|
149
|
+
end
|
150
|
+
|
151
|
+
it "handles empty input gracefully on JSON" do
|
152
|
+
@env['CONTENT_TYPE'] = 'application/json'
|
153
|
+
@env['rack.input'] = StringIO.new
|
154
|
+
|
155
|
+
ret = @params.retrieve_params(@env)
|
156
|
+
ret.should be_empty
|
143
157
|
end
|
144
158
|
|
159
|
+
it "raises a BadRequestError on invalid JSON" do
|
160
|
+
@env['CONTENT_TYPE'] = 'application/json'
|
161
|
+
@env['rack.input'] = StringIO.new
|
162
|
+
@env['rack.input'] << %|{"foo":"bar" BORKEN}|
|
163
|
+
@env['rack.input'].rewind
|
164
|
+
|
165
|
+
lambda{ @params.retrieve_params(@env) }.should raise_error(Goliath::Validation::BadRequestError)
|
166
|
+
end
|
145
167
|
|
146
168
|
it "doesn't parse unknown content types" do
|
147
169
|
@env['CONTENT_TYPE'] = 'fake/form -- type'
|
@@ -41,13 +41,21 @@ describe Goliath::Rack::Render do
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
CONTENT_TYPES = {
|
45
|
+
'rss' => 'application/rss+xml',
|
46
|
+
'xml' => 'application/xml',
|
47
|
+
'html' => 'text/html',
|
48
|
+
'json' => 'application/json',
|
49
|
+
'yaml' => 'text/yaml',
|
50
|
+
}
|
51
|
+
|
44
52
|
describe 'Content-Type' do
|
45
53
|
before(:each) do
|
46
54
|
app.should_receive(:call).and_return([200, {}, {}])
|
47
55
|
end
|
48
56
|
|
49
57
|
describe 'from header' do
|
50
|
-
|
58
|
+
CONTENT_TYPES.values.each do |type|
|
51
59
|
it "handles content type for #{type}" do
|
52
60
|
env['HTTP_ACCEPT'] = type
|
53
61
|
status, headers, body = render.call(env)
|
@@ -57,10 +65,7 @@ describe Goliath::Rack::Render do
|
|
57
65
|
end
|
58
66
|
|
59
67
|
describe 'from URL param' do
|
60
|
-
|
61
|
-
'xml' => 'application/xml',
|
62
|
-
'html' => 'text/html',
|
63
|
-
'json' => 'application/json'}.each_pair do |format, content_type|
|
68
|
+
CONTENT_TYPES.each_pair do |format, content_type|
|
64
69
|
it "converts #{format} to #{content_type}" do
|
65
70
|
env['params']['format'] = format
|
66
71
|
status, headers, body = render.call(env)
|
@@ -30,7 +30,7 @@ describe Goliath::Rack::Validation::NumericRange do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'uses the first value, if the value is an array' do
|
33
|
-
@env['params']['id'] = [10,11,12]
|
33
|
+
@env['params']['id'] = [10, 11, 12]
|
34
34
|
@nr.call(@env)
|
35
35
|
@env['params']['id'].should == 10
|
36
36
|
end
|
@@ -58,6 +58,13 @@ describe Goliath::Rack::Validation::NumericRange do
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
it 'converts to a float with :as => Float' do
|
62
|
+
nr = Goliath::Rack::Validation::NumericRange.new(@app, {:key => 'id', :min => 1.1, :as => Float})
|
63
|
+
@env['params']['id'] = 1.5
|
64
|
+
nr.call(@env)
|
65
|
+
@env['params']['id'].should == 1.5
|
66
|
+
end
|
67
|
+
|
61
68
|
it 'raises error if key is not set' do
|
62
69
|
lambda { Goliath::Rack::Validation::NumericRange.new('app', {:min => 5}) }.should raise_error
|
63
70
|
end
|
@@ -3,7 +3,11 @@ require 'goliath/rack/validation/request_method'
|
|
3
3
|
|
4
4
|
describe Goliath::Rack::Validation::RequestMethod do
|
5
5
|
before(:each) do
|
6
|
+
@app_headers = {'Content-Type' => 'asdf'}
|
7
|
+
@app_body = {'a' => 'b'}
|
8
|
+
|
6
9
|
@app = mock('app').as_null_object
|
10
|
+
@app.stub!(:call).and_return([200, @app_headers, @app_body])
|
7
11
|
end
|
8
12
|
|
9
13
|
it 'accepts an app' do
|
@@ -18,25 +22,21 @@ describe Goliath::Rack::Validation::RequestMethod do
|
|
18
22
|
|
19
23
|
it 'raises error if method is invalid' do
|
20
24
|
@env['REQUEST_METHOD'] = 'fubar'
|
21
|
-
|
25
|
+
@rm.call(@env).should == [405, {'Allow' => 'GET, POST'}, {:error => "Invalid request method"}]
|
22
26
|
end
|
23
27
|
|
24
28
|
it 'allows valid methods through' do
|
25
29
|
@env['REQUEST_METHOD'] = 'GET'
|
26
|
-
|
30
|
+
@rm.call(@env).should == [200, @app_headers, @app_body]
|
27
31
|
end
|
28
32
|
|
29
33
|
it 'returns app status, headers and body' do
|
30
|
-
app_headers = {'Content-Type' => 'asdf'}
|
31
|
-
app_body = {'a' => 'b'}
|
32
|
-
@app.should_receive(:call).and_return([200, app_headers, app_body])
|
33
|
-
|
34
34
|
@env['REQUEST_METHOD'] = 'POST'
|
35
35
|
|
36
36
|
status, headers, body = @rm.call(@env)
|
37
37
|
status.should == 200
|
38
|
-
headers.should == app_headers
|
39
|
-
body.should == app_body
|
38
|
+
headers.should == @app_headers
|
39
|
+
body.should == @app_body
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -7,24 +7,26 @@ describe Goliath::Rack::Validation::RequiredParam do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'accepts options on create' do
|
10
|
-
opts = { :type => 1, :key => 2 }
|
10
|
+
opts = { :type => 1, :key => 2, :message => 'is required' }
|
11
11
|
lambda { Goliath::Rack::Validation::RequiredParam.new('my app', opts) }.should_not raise_error
|
12
12
|
end
|
13
13
|
|
14
|
-
it 'defaults type and
|
14
|
+
it 'defaults type, key and message' do
|
15
15
|
@rp = Goliath::Rack::Validation::RequiredParam.new('app')
|
16
16
|
@rp.key.should_not be_nil
|
17
17
|
@rp.key.should_not =~ /^\s*$/
|
18
18
|
|
19
19
|
@rp.type.should_not be_nil
|
20
20
|
@rp.type.should_not =~ /^\s*$/
|
21
|
+
|
22
|
+
@rp.message.should == 'identifier missing'
|
21
23
|
end
|
22
24
|
|
23
25
|
describe 'with middleware' do
|
24
26
|
before(:each) do
|
25
27
|
@app = mock('app').as_null_object
|
26
28
|
@env = {'params' => {}}
|
27
|
-
@rp = Goliath::Rack::Validation::RequiredParam.new(@app, {:type => 'Monkey', :key => 'mk'})
|
29
|
+
@rp = Goliath::Rack::Validation::RequiredParam.new(@app, {:type => 'Monkey', :key => 'mk', :message => 'is required'})
|
28
30
|
end
|
29
31
|
|
30
32
|
it 'stores type and key options' do
|
@@ -32,6 +34,11 @@ describe Goliath::Rack::Validation::RequiredParam do
|
|
32
34
|
@rp.key.should == 'mk'
|
33
35
|
end
|
34
36
|
|
37
|
+
it 'calls validation_error with a custom message' do
|
38
|
+
@rp.should_receive(:validation_error).with(anything, 'Monkey is required')
|
39
|
+
@rp.call(@env)
|
40
|
+
end
|
41
|
+
|
35
42
|
it 'returns the app status, headers and body' do
|
36
43
|
app_headers = {'Content-Type' => 'app'}
|
37
44
|
app_body = {'b' => 'c'}
|
@@ -45,47 +52,44 @@ describe Goliath::Rack::Validation::RequiredParam do
|
|
45
52
|
body.should == app_body
|
46
53
|
end
|
47
54
|
|
48
|
-
describe 'key_valid
|
55
|
+
describe 'key_valid?' do
|
49
56
|
it 'raises exception if the key is not provided' do
|
50
|
-
|
57
|
+
@rp.key_valid?(@env['params']).should be_false
|
51
58
|
end
|
52
59
|
|
53
60
|
it 'raises exception if the key is blank' do
|
54
61
|
@env['params']['mk'] = ''
|
55
|
-
|
56
|
-
lambda { @rp.key_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
|
62
|
+
@rp.key_valid?(@env['params']).should be_false
|
57
63
|
end
|
58
64
|
|
59
65
|
it 'raises exception if the key is nil' do
|
60
66
|
@env['params']['mk'] = nil
|
61
|
-
|
62
|
-
lambda { @rp.key_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
|
67
|
+
@rp.key_valid?(@env['params']).should be_false
|
63
68
|
end
|
64
69
|
|
65
70
|
it 'handles an empty array' do
|
66
71
|
@env['params']['mk'] = []
|
67
|
-
|
72
|
+
@rp.key_valid?(@env['params']).should be_false
|
68
73
|
end
|
69
74
|
|
70
75
|
it 'handles an array of nils' do
|
71
76
|
@env['params']['mk'] = [nil, nil, nil]
|
72
|
-
|
77
|
+
@rp.key_valid?(@env['params']).should be_false
|
73
78
|
end
|
74
79
|
|
75
80
|
it 'handles an array of blanks' do
|
76
81
|
@env['params']['mk'] = ['', '', '']
|
77
|
-
|
82
|
+
@rp.key_valid?(@env['params']).should be_false
|
78
83
|
end
|
79
84
|
|
80
85
|
it "doesn't raise if the key provided" do
|
81
86
|
@env['params']['mk'] = 'my value'
|
82
|
-
|
83
|
-
lambda { @rp.key_valid!(@env['params']) }.should_not raise_error(Goliath::Validation::Error)
|
87
|
+
@rp.key_valid?(@env['params']).should be_true
|
84
88
|
end
|
85
89
|
|
86
90
|
it "doesn't raise if the array contains valid data" do
|
87
91
|
@env['params']['mk'] = [1, 2, 3, 4]
|
88
|
-
|
92
|
+
@rp.key_valid?(@env['params']).should be_true
|
89
93
|
end
|
90
94
|
end
|
91
95
|
end
|