grape 0.2.1.1 → 0.2.2

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.

Potentially problematic release.


This version of grape might be problematic. Click here for more details.

@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Validations::CoerceValidator do
4
+ subject { Class.new(Grape::API) }
5
+ def app; subject end
6
+
7
+ describe 'coerce' do
8
+ it 'error on malformed input' do
9
+ subject.params { requires :int, :type => Integer }
10
+ subject.get '/single' do 'int works'; end
11
+
12
+ get '/single', :int => '43a'
13
+ last_response.status.should == 400
14
+ last_response.body.should == 'invalid parameter: int'
15
+
16
+ get '/single', :int => '43'
17
+ last_response.status.should == 200
18
+ last_response.body.should == 'int works'
19
+ end
20
+
21
+ it 'error on malformed input (Array)' do
22
+ subject.params { requires :ids, :type => Array[Integer] }
23
+ subject.get '/array' do 'array int works'; end
24
+
25
+ get 'array', { :ids => ['1', '2', 'az'] }
26
+ last_response.status.should == 400
27
+ last_response.body.should == 'invalid parameter: ids'
28
+
29
+ get 'array', { :ids => ['1', '2', '890'] }
30
+ last_response.status.should == 200
31
+ last_response.body.should == 'array int works'
32
+ end
33
+
34
+ context 'complex objects' do
35
+ module CoerceValidatorSpec
36
+ class User
37
+ include Virtus
38
+ attribute :id, Integer
39
+ attribute :name, String
40
+ end
41
+ end
42
+
43
+ it 'error on malformed input for complex objects' do
44
+ subject.params { requires :user, :type => CoerceValidatorSpec::User }
45
+ subject.get '/user' do 'complex works'; end
46
+
47
+ get '/user', :user => "32"
48
+ last_response.status.should == 400
49
+ last_response.body.should == 'invalid parameter: user'
50
+
51
+ get '/user', :user => { :id => 32, :name => 'Bob' }
52
+ last_response.status.should == 200
53
+ last_response.body.should == 'complex works'
54
+ end
55
+ end
56
+
57
+ context 'coerces' do
58
+ it 'Integer' do
59
+ subject.params { requires :int, :coerce => Integer }
60
+ subject.get '/int' do params[:int].class; end
61
+
62
+ get '/int', { :int => "45" }
63
+ last_response.status.should == 200
64
+ last_response.body.should == 'Fixnum'
65
+ end
66
+
67
+ it 'Array of Integers' do
68
+ subject.params { requires :arry, :coerce => Array[Integer] }
69
+ subject.get '/array' do params[:arry][0].class; end
70
+
71
+ get '/array', { :arry => [ '1', '2', '3' ] }
72
+ last_response.status.should == 200
73
+ last_response.body.should == 'Fixnum'
74
+ end
75
+
76
+ it 'Array of Bools' do
77
+ subject.params { requires :arry, :coerce => Array[Virtus::Attribute::Boolean] }
78
+ subject.get '/array' do params[:arry][0].class; end
79
+
80
+ get 'array', { :arry => [1, 0] }
81
+ last_response.status.should == 200
82
+ last_response.body.should == 'TrueClass'
83
+ end
84
+
85
+ it 'Bool' do
86
+ subject.params { requires :bool, :coerce => Virtus::Attribute::Boolean }
87
+ subject.get '/bool' do params[:bool].class; end
88
+
89
+ get '/bool', { :bool => 1 }
90
+ last_response.status.should == 200
91
+ last_response.body.should == 'TrueClass'
92
+
93
+ get '/bool', { :bool => 0 }
94
+ last_response.status.should == 200
95
+ last_response.body.should == 'FalseClass'
96
+
97
+ get '/bool', { :bool => 'false' }
98
+ last_response.status.should == 200
99
+ last_response.body.should == 'FalseClass'
100
+
101
+ get '/bool', { :bool => 'true' }
102
+ last_response.status.should == 200
103
+ last_response.body.should == 'TrueClass'
104
+ end
105
+
106
+ it 'file' do
107
+ subject.params { requires :file, :coerce => Rack::Multipart::UploadedFile }
108
+ subject.post '/upload' do params[:file].filename; end
109
+
110
+ post '/upload', { :file => Rack::Test::UploadedFile.new(__FILE__) }
111
+ last_response.status.should == 201
112
+ last_response.body.should == File.basename(__FILE__).to_s
113
+ end
114
+
115
+ it 'Nests integers' do
116
+ subject.params do
117
+ group :integers do
118
+ requires :int, :coerce => Integer
119
+ end
120
+ end
121
+ subject.get '/int' do params[:integers][:int].class; end
122
+
123
+ get '/int', { :integers => { :int => "45" } }
124
+ last_response.status.should == 200
125
+ last_response.body.should == 'Fixnum'
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Validations::PresenceValidator do
4
+
5
+ module ValidationsSpec
6
+ module PresenceValidatorSpec
7
+ class API < Grape::API
8
+ default_format :json
9
+
10
+ resource :bacons do
11
+ get do
12
+ "All the bacon"
13
+ end
14
+ end
15
+
16
+ params do
17
+ requires :id, :regexp => /^[0-9]+$/
18
+ end
19
+ post do
20
+ {:ret => params[:id]}
21
+ end
22
+
23
+ params do
24
+ requires :name, :company
25
+ end
26
+ get do
27
+ "Hello"
28
+ end
29
+
30
+ params do
31
+ group :user do
32
+ requires :first_name, :last_name
33
+ end
34
+ end
35
+ get '/nested' do
36
+ "Nested"
37
+ end
38
+
39
+ params do
40
+ group :admin do
41
+ requires :admin_name
42
+ group :super do
43
+ group :user do
44
+ requires :first_name, :last_name
45
+ end
46
+ end
47
+ end
48
+ end
49
+ get '/nested_triple' do
50
+ "Nested triple"
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ def app
57
+ ValidationsSpec::PresenceValidatorSpec::API
58
+ end
59
+
60
+ it "does not validate for any params" do
61
+ get("/bacons")
62
+ last_response.status.should == 200
63
+ last_response.body.should == "All the bacon"
64
+ end
65
+
66
+ it 'validates id' do
67
+ post('/')
68
+ last_response.status.should == 400
69
+ last_response.body.should == "missing parameter: id"
70
+
71
+ post('/', {}, 'rack.input' => StringIO.new('{"id" : "a56b"}'))
72
+ last_response.body.should == 'invalid parameter: id'
73
+ last_response.status.should == 400
74
+
75
+ post('/', {}, 'rack.input' => StringIO.new('{"id" : 56}'))
76
+ last_response.body.should == '{"ret":56}'
77
+ last_response.status.should == 201
78
+ end
79
+
80
+ it 'validates name, company' do
81
+ get('/')
82
+ last_response.status.should == 400
83
+ last_response.body.should == "missing parameter: name"
84
+
85
+ get('/', :name => "Bob")
86
+ last_response.status.should == 400
87
+ last_response.body.should == "missing parameter: company"
88
+
89
+ get('/', :name => "Bob", :company => "TestCorp")
90
+ last_response.status.should == 200
91
+ last_response.body.should == "Hello"
92
+ end
93
+
94
+ it 'validates nested parameters' do
95
+ get('/nested')
96
+ last_response.status.should == 400
97
+ last_response.body.should == "missing parameter: first_name"
98
+
99
+ get('/nested', :user => {:first_name => "Billy"})
100
+ last_response.status.should == 400
101
+ last_response.body.should == "missing parameter: last_name"
102
+
103
+ get('/nested', :user => {:first_name => "Billy", :last_name => "Bob"})
104
+ last_response.status.should == 200
105
+ last_response.body.should == "Nested"
106
+ end
107
+
108
+ it 'validates triple nested parameters' do
109
+ get('/nested_triple')
110
+ last_response.status.should == 400
111
+ last_response.body.should == "missing parameter: admin_name"
112
+
113
+ get('/nested_triple', :user => {:first_name => "Billy"})
114
+ last_response.status.should == 400
115
+ last_response.body.should == "missing parameter: admin_name"
116
+
117
+ get('/nested_triple', :admin => {:super => {:first_name => "Billy"}})
118
+ last_response.status.should == 400
119
+ last_response.body.should == "missing parameter: admin_name"
120
+
121
+ get('/nested_triple', :super => {:user => {:first_name => "Billy", :last_name => "Bob"}})
122
+ last_response.status.should == 400
123
+ last_response.body.should == "missing parameter: admin_name"
124
+
125
+ get('/nested_triple', :admin => {:super => {:user => {:first_name => "Billy"}}})
126
+ last_response.status.should == 400
127
+ last_response.body.should == "missing parameter: admin_name"
128
+
129
+ get('/nested_triple', :admin => { :admin_name => 'admin', :super => {:user => {:first_name => "Billy"}}})
130
+ last_response.status.should == 400
131
+ last_response.body.should == "missing parameter: last_name"
132
+
133
+ get('/nested_triple', :admin => { :admin_name => 'admin', :super => {:user => {:first_name => "Billy", :last_name => "Bob"}}})
134
+ last_response.status.should == 200
135
+ last_response.body.should == "Nested triple"
136
+ end
137
+
138
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Validations::RegexpValidator do
4
+ module ValidationsSpec
5
+ module RegexpValidatorSpec
6
+ class API < Grape::API
7
+ default_format :json
8
+
9
+ params do
10
+ requires :name, :regexp => /^[a-z]+$/
11
+ end
12
+ get do
13
+
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def app
20
+ ValidationsSpec::RegexpValidatorSpec::API
21
+ end
22
+
23
+ it 'should refuse invalid input' do
24
+ get '/', :name => "invalid name"
25
+ last_response.status.should == 400
26
+ end
27
+
28
+ it 'should accept valid input' do
29
+ get '/', :name => "bob"
30
+ last_response.status.should == 200
31
+ end
32
+
33
+ end
@@ -0,0 +1,185 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Validations do
4
+ subject { Class.new(Grape::API) }
5
+ def app; subject end
6
+
7
+ describe 'params' do
8
+ context 'optional' do
9
+ it 'validates when params is present' do
10
+ subject.params { optional :a_number, :regexp => /^[0-9]+$/ }
11
+ subject.get '/optional' do 'optional works!'; end
12
+
13
+ get '/optional', { :a_number => 'string' }
14
+ last_response.status.should == 400
15
+ last_response.body.should == 'invalid parameter: a_number'
16
+
17
+ get '/optional', { :a_number => 45 }
18
+ last_response.status.should == 200
19
+ last_response.body.should == 'optional works!'
20
+ end
21
+
22
+ it "doesn't validate when param not present" do
23
+ subject.params { optional :a_number, :regexp => /^[0-9]+$/ }
24
+ subject.get '/optional' do 'optional works!'; end
25
+
26
+ get '/optional'
27
+ last_response.status.should == 200
28
+ last_response.body.should == 'optional works!'
29
+ end
30
+
31
+ it 'adds to declared parameters' do
32
+ subject.params { optional :some_param }
33
+ subject.settings[:declared_params].should == [:some_param]
34
+ end
35
+ end
36
+
37
+ context 'required' do
38
+ before do
39
+ subject.params { requires :key }
40
+ subject.get '/required' do 'required works'; end
41
+ end
42
+
43
+ it 'errors when param not present' do
44
+ get '/required'
45
+ last_response.status.should == 400
46
+ last_response.body.should == 'missing parameter: key'
47
+ end
48
+
49
+ it "doesn't throw a missing param when param is present" do
50
+ get '/required', { :key => 'cool' }
51
+ last_response.status.should == 200
52
+ last_response.body.should == 'required works'
53
+ end
54
+
55
+ it 'adds to declared parameters' do
56
+ subject.params { requires :some_param }
57
+ subject.settings[:declared_params].should == [:some_param]
58
+ end
59
+ end
60
+
61
+ context 'custom validation' do
62
+ module CustomValidations
63
+ class Customvalidator < Grape::Validations::Validator
64
+ def validate_param!(attr_name, params)
65
+ unless params[attr_name] == 'im custom'
66
+ throw :error, :status => 400, :message => "#{attr_name}: is not custom!"
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'when using optional with a custom validator' do
73
+ before do
74
+ subject.params { optional :custom, :customvalidator => true }
75
+ subject.get '/optional_custom' do 'optional with custom works!'; end
76
+ end
77
+
78
+ it 'validates when param is present' do
79
+ get '/optional_custom', { :custom => 'im custom' }
80
+ last_response.status.should == 200
81
+ last_response.body.should == 'optional with custom works!'
82
+
83
+ get '/optional_custom', { :custom => 'im wrong' }
84
+ last_response.status.should == 400
85
+ last_response.body.should == 'custom: is not custom!'
86
+ end
87
+
88
+ it "skip validation when parameter isn't present" do
89
+ get '/optional_custom'
90
+ last_response.status.should == 200
91
+ last_response.body.should == 'optional with custom works!'
92
+ end
93
+
94
+ it 'validates with custom validator when param present and incorrect type' do
95
+ subject.params { optional :custom, :type => String, :customvalidator => true }
96
+
97
+ get '/optional_custom', { :custom => 123 }
98
+ last_response.status.should == 400
99
+ last_response.body.should == 'custom: is not custom!'
100
+ end
101
+ end
102
+
103
+ context 'when using requires with a custom validator' do
104
+ before do
105
+ subject.params { requires :custom, :customvalidator => true }
106
+ subject.get '/required_custom' do 'required with custom works!'; end
107
+ end
108
+
109
+ it 'validates when param is present' do
110
+ get '/required_custom', { :custom => 'im wrong, validate me' }
111
+ last_response.status.should == 400
112
+ last_response.body.should == 'custom: is not custom!'
113
+
114
+ get '/required_custom', { :custom => 'im custom' }
115
+ last_response.status.should == 200
116
+ last_response.body.should == 'required with custom works!'
117
+ end
118
+
119
+ it 'validates when param is not present' do
120
+ get '/required_custom'
121
+ last_response.status.should == 400
122
+ last_response.body.should == 'missing parameter: custom'
123
+ end
124
+
125
+ context 'nested namespaces' do
126
+ before do
127
+ subject.params { requires :custom, :customvalidator => true }
128
+ subject.namespace 'nested' do
129
+ get 'one' do 'validation failed' end
130
+ namespace 'nested' do
131
+ get 'two' do 'validation failed' end
132
+ end
133
+ end
134
+ subject.namespace 'peer' do
135
+ get 'one' do 'no validation required' end
136
+ namespace 'nested' do
137
+ get 'two' do 'no validation required' end
138
+ end
139
+ end
140
+
141
+ subject.namespace 'unrelated' do
142
+ params{ requires :name }
143
+ get 'one' do 'validation required'; end
144
+
145
+ namespace 'double' do
146
+ get 'two' do 'no validation required' end
147
+ end
148
+ end
149
+ end
150
+
151
+ specify 'the parent namespace should use the validator' do
152
+ get '/nested/one', { :custom => 'im wrong, validate me'}
153
+ last_response.status.should == 400
154
+ last_response.body.should == 'custom: is not custom!'
155
+ end
156
+
157
+ specify 'the nested namesapce should inherit the custom validator' do
158
+ get '/nested/nested/two', { :custom => 'im wrong, validate me'}
159
+ last_response.status.should == 400
160
+ last_response.body.should == 'custom: is not custom!'
161
+ end
162
+
163
+ specify 'peer namesapces should not have the validator' do
164
+ get '/peer/one', { :custom => 'im not validated' }
165
+ last_response.status.should == 200
166
+ last_response.body.should == 'no validation required'
167
+ end
168
+
169
+ specify 'namespaces nested in peers should also not have the validator' do
170
+ get '/peer/nested/two', { :custom => 'im not validated' }
171
+ last_response.status.should == 200
172
+ last_response.body.should == 'no validation required'
173
+ end
174
+
175
+ specify 'when nested, specifying a route should clear out the validations for deeper nested params' do
176
+ get '/unrelated/one'
177
+ last_response.status.should == 400
178
+ get '/unrelated/double/two'
179
+ last_response.status.should == 200
180
+ end
181
+ end
182
+ end
183
+ end # end custom validation
184
+ end
185
+ end