angus 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/lib/angus/base.rb +6 -3
- data/lib/angus/base_proxy.rb +20 -0
- data/lib/angus/base_resource.rb +8 -3
- data/lib/angus/generator/templates/definitions/operations.yml.erb +2 -0
- data/lib/angus/generator/templates/resources/resource.rb.erb +2 -2
- data/lib/angus/generator/thor/resource.rb +1 -1
- data/lib/angus/middleware/exception_handler.rb +2 -2
- data/lib/angus/request_handler.rb +7 -7
- data/lib/angus/rspec/support/examples.rb +3 -2
- data/lib/angus/rspec/support/examples/describe_errors.rb +23 -6
- data/lib/angus/utils/exceptions/invalid_parameter_type.rb +18 -0
- data/lib/angus/utils/exceptions/required_parameter_not_fond.rb +19 -0
- data/lib/angus/utils/params_validator.rb +81 -0
- data/spec/angus/middleware/exception_handler_spec.rb +16 -1
- data/spec/angus/rspec/examples/describe_errors_spec.rb +6 -0
- data/spec/functional/basic_spec.rb +2 -2
- data/spec/functional/empty_resource_spec.rb +2 -2
- data/spec/functional/no_resources_spec.rb +2 -2
- data/spec/functional/type_validation/definitions/admins/operations.yml +70 -0
- data/spec/functional/type_validation/definitions/messages.yml +0 -0
- data/spec/functional/type_validation/definitions/representations.yml +9 -0
- data/spec/functional/type_validation/definitions/service.yml +3 -0
- data/spec/functional/type_validation/models/admin.rb +1 -0
- data/spec/functional/type_validation/resources/admins.rb +35 -0
- data/spec/functional/type_validation/services/type_validation.rb +13 -0
- data/spec/functional/type_validation_spec.rb +283 -0
- data/spec/support/matchers/have_error_response_matcher.rb +40 -0
- data/spec/support/matchers/have_in_message_matcher.rb +47 -0
- data/spec/support/matchers/have_success_response_matcher.rb +40 -0
- metadata +95 -93
@@ -0,0 +1,70 @@
|
|
1
|
+
show:
|
2
|
+
name: Get information about a given user.
|
3
|
+
description: >
|
4
|
+
Returns all the information about a given user.
|
5
|
+
|
6
|
+
path: /admins/:id
|
7
|
+
method: get
|
8
|
+
uri:
|
9
|
+
- element: user_id
|
10
|
+
description: User identifier.
|
11
|
+
|
12
|
+
response:
|
13
|
+
- element: profile
|
14
|
+
description: User profile.
|
15
|
+
required: true
|
16
|
+
type: user
|
17
|
+
|
18
|
+
index:
|
19
|
+
name: Gets a list of users.
|
20
|
+
description: >
|
21
|
+
Returns all the information about all users.
|
22
|
+
|
23
|
+
path: /admins
|
24
|
+
method: get
|
25
|
+
request:
|
26
|
+
- element: requester_id
|
27
|
+
type: integer
|
28
|
+
required: true
|
29
|
+
description: User identifier.
|
30
|
+
|
31
|
+
response:
|
32
|
+
- element: users
|
33
|
+
description: Perfil del usuario
|
34
|
+
required: true
|
35
|
+
elements_type: user
|
36
|
+
|
37
|
+
create:
|
38
|
+
name: Create a user with the given parameters.
|
39
|
+
description: >
|
40
|
+
Returns the recently created user.
|
41
|
+
|
42
|
+
path: /admins
|
43
|
+
method: post
|
44
|
+
request:
|
45
|
+
- element: name
|
46
|
+
type: string
|
47
|
+
required: true
|
48
|
+
description: User name.
|
49
|
+
- element: age
|
50
|
+
type: integer
|
51
|
+
required: true
|
52
|
+
description: User age.
|
53
|
+
- element: favorite_decimal
|
54
|
+
type: decimal
|
55
|
+
required: true
|
56
|
+
description: User favorite decimal number.
|
57
|
+
- element: birth_date
|
58
|
+
type: date
|
59
|
+
required: true
|
60
|
+
description: The last time that the user signed in.
|
61
|
+
- element: last_signed_in_at
|
62
|
+
type: datetime
|
63
|
+
required: true
|
64
|
+
description: The last time that the user signed in.
|
65
|
+
|
66
|
+
response:
|
67
|
+
- element: user
|
68
|
+
description: Perfil del usuario
|
69
|
+
required: true
|
70
|
+
elements_type: user
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
Admin = Struct.new(:id, :name, :age)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative '../models/admin'
|
2
|
+
|
3
|
+
|
4
|
+
class Admins < Angus::BaseResource
|
5
|
+
|
6
|
+
ADMINS = [
|
7
|
+
Admin.new(1, 'John Smith', 33),
|
8
|
+
Admin.new(2, 'John Doe', 44)
|
9
|
+
]
|
10
|
+
|
11
|
+
def show
|
12
|
+
user = ADMINS.find { |user| user[:id] == params[:id].to_i }
|
13
|
+
|
14
|
+
{:profile => user}
|
15
|
+
end
|
16
|
+
|
17
|
+
def index
|
18
|
+
{ :users => ADMINS }
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
user = Admin.new(last_id, params[:name], params[:age])
|
23
|
+
|
24
|
+
{ :user => user }
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
# This is not a good practice is only for testing propose. Use an
|
30
|
+
# autogenerated id (using db features).
|
31
|
+
def last_id
|
32
|
+
ADMINS.map {|user| user['id'] }.max + 1
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,283 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'functional/type_validation/services/type_validation'
|
4
|
+
|
5
|
+
working_dir = "#{File.dirname(__FILE__ )}/type_validation"
|
6
|
+
|
7
|
+
describe Spec::Functional::TypeValidation, { :work_dir => working_dir } do
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
subject(:app) { Rack::Lint.new(Spec::Functional::TypeValidation.new) }
|
11
|
+
|
12
|
+
describe 'required fields validation' do
|
13
|
+
it 'responds correctly if all required fields are given' do
|
14
|
+
get '/type_validation/api/0.1/admins?requester_id=1'
|
15
|
+
|
16
|
+
response = JSON(last_response.body)
|
17
|
+
|
18
|
+
expect(response['status']).to eq('success')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'responds with an error when a required field is not present' do
|
22
|
+
get '/type_validation/api/0.1/admins'
|
23
|
+
|
24
|
+
expect(last_response).to have_error_response
|
25
|
+
expect(last_response).to have_in_message({
|
26
|
+
'level' => 'error',
|
27
|
+
'key' => 'TODO define',
|
28
|
+
'dsc' => 'requester_id'
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'type fields validation' do
|
34
|
+
let(:valid_params) {
|
35
|
+
{
|
36
|
+
'name' => 'Britney Watson',
|
37
|
+
'age' => 22,
|
38
|
+
'favorite_decimal' => 21.3,
|
39
|
+
'birth_date' => Date.today.iso8601,
|
40
|
+
'last_signed_in_at' => DateTime.now.iso8601
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
context 'string type' do
|
45
|
+
it 'should be valid if a number is given' do
|
46
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
47
|
+
'name' => 22
|
48
|
+
})
|
49
|
+
|
50
|
+
expect(last_response).to have_success_response
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should be valid if a text is given' do
|
54
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
55
|
+
'name' => 'Example Text'
|
56
|
+
})
|
57
|
+
|
58
|
+
expect(last_response).to have_success_response
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should be valid if a date is given' do
|
62
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
63
|
+
'name' => Date.today
|
64
|
+
})
|
65
|
+
|
66
|
+
expect(last_response).to have_success_response
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'integer type' do
|
71
|
+
it 'should be valid if a number is given' do
|
72
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
73
|
+
'age' => 22
|
74
|
+
})
|
75
|
+
|
76
|
+
expect(last_response).to have_success_response
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should not be valid if a decimal is given' do
|
80
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
81
|
+
'age' => 22.1
|
82
|
+
})
|
83
|
+
|
84
|
+
expect(last_response).to have_error_response
|
85
|
+
expect(last_response).to have_in_message({
|
86
|
+
'level' => 'error',
|
87
|
+
'key' => 'TODO define',
|
88
|
+
'dsc' => 'TODO define'
|
89
|
+
})
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should not be valid if a text is given' do
|
93
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
94
|
+
'age' => 'Example Text'
|
95
|
+
})
|
96
|
+
|
97
|
+
expect(last_response).to have_error_response
|
98
|
+
expect(last_response).to have_in_message({
|
99
|
+
'level' => 'error',
|
100
|
+
'key' => 'TODO define',
|
101
|
+
'dsc' => 'TODO define'
|
102
|
+
})
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should not be valid if a date is given' do
|
106
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
107
|
+
'age' => Date.today
|
108
|
+
})
|
109
|
+
|
110
|
+
expect(last_response).to have_error_response
|
111
|
+
expect(last_response).to have_in_message({
|
112
|
+
'level' => 'error',
|
113
|
+
'key' => 'TODO define',
|
114
|
+
'dsc' => 'TODO define'
|
115
|
+
})
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'decimal type' do
|
120
|
+
it 'should be valid if a number is given' do
|
121
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
122
|
+
'favorite_decimal' => 22
|
123
|
+
})
|
124
|
+
|
125
|
+
expect(last_response).to have_success_response
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should be valid if a decimal is given' do
|
129
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
130
|
+
'favorite_decimal' => 22.1
|
131
|
+
})
|
132
|
+
|
133
|
+
expect(last_response).to have_success_response
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should not be valid if a text is given' do
|
137
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
138
|
+
'favorite_decimal' => 'Example Text'
|
139
|
+
})
|
140
|
+
|
141
|
+
expect(last_response).to have_error_response
|
142
|
+
expect(last_response).to have_in_message({
|
143
|
+
'level' => 'error',
|
144
|
+
'key' => 'TODO define',
|
145
|
+
'dsc' => 'TODO define'
|
146
|
+
})
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should not be valid if a date is given' do
|
150
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
151
|
+
'favorite_decimal' => Date.today
|
152
|
+
})
|
153
|
+
|
154
|
+
expect(last_response).to have_error_response
|
155
|
+
expect(last_response).to have_in_message({
|
156
|
+
'level' => 'error',
|
157
|
+
'key' => 'TODO define',
|
158
|
+
'dsc' => 'TODO define'
|
159
|
+
})
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'date type' do
|
164
|
+
it 'should be valid if a number is given' do
|
165
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
166
|
+
'birth_date' => 22
|
167
|
+
})
|
168
|
+
|
169
|
+
expect(last_response).to have_error_response
|
170
|
+
expect(last_response).to have_in_message({
|
171
|
+
'level' => 'error',
|
172
|
+
'key' => 'TODO define',
|
173
|
+
'dsc' => 'TODO define'
|
174
|
+
})
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should be valid if a decimal is given' do
|
178
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
179
|
+
'birth_date' => 22.1
|
180
|
+
})
|
181
|
+
|
182
|
+
expect(last_response).to have_error_response
|
183
|
+
expect(last_response).to have_in_message({
|
184
|
+
'level' => 'error',
|
185
|
+
'key' => 'TODO define',
|
186
|
+
'dsc' => 'TODO define'
|
187
|
+
})
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should not be valid if a text is given' do
|
191
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
192
|
+
'birth_date' => 'Example Text'
|
193
|
+
})
|
194
|
+
|
195
|
+
expect(last_response).to have_error_response
|
196
|
+
expect(last_response).to have_in_message({
|
197
|
+
'level' => 'error',
|
198
|
+
'key' => 'TODO define',
|
199
|
+
'dsc' => 'TODO define'
|
200
|
+
})
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should be valid if a date is given' do
|
204
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
205
|
+
'birth_date' => Date.today.iso8601
|
206
|
+
})
|
207
|
+
|
208
|
+
expect(last_response).to have_success_response
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'should not be valid if a date is given' do
|
212
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
213
|
+
'birth_date' => DateTime.now.iso8601
|
214
|
+
})
|
215
|
+
|
216
|
+
expect(last_response).to have_success_response
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'datetime type' do
|
221
|
+
it 'should be valid if a number is given' do
|
222
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
223
|
+
'last_signed_in_at' => 22
|
224
|
+
})
|
225
|
+
|
226
|
+
expect(last_response).to have_error_response
|
227
|
+
expect(last_response).to have_in_message({
|
228
|
+
'level' => 'error',
|
229
|
+
'key' => 'TODO define',
|
230
|
+
'dsc' => 'TODO define'
|
231
|
+
})
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should be valid if a decimal is given' do
|
235
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
236
|
+
'last_signed_in_at' => 22.1
|
237
|
+
})
|
238
|
+
|
239
|
+
expect(last_response).to have_error_response
|
240
|
+
expect(last_response).to have_in_message({
|
241
|
+
'level' => 'error',
|
242
|
+
'key' => 'TODO define',
|
243
|
+
'dsc' => 'TODO define'
|
244
|
+
})
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'should not be valid if a text is given' do
|
248
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
249
|
+
'last_signed_in_at' => 'Example Text'
|
250
|
+
})
|
251
|
+
|
252
|
+
expect(last_response).to have_error_response
|
253
|
+
expect(last_response).to have_in_message({
|
254
|
+
'level' => 'error',
|
255
|
+
'key' => 'TODO define',
|
256
|
+
'dsc' => 'TODO define'
|
257
|
+
})
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'should not be valid if a date is given' do
|
261
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
262
|
+
'last_signed_in_at' => Date.today.iso8601
|
263
|
+
})
|
264
|
+
|
265
|
+
expect(last_response).to have_error_response
|
266
|
+
expect(last_response).to have_in_message({
|
267
|
+
'level' => 'error',
|
268
|
+
'key' => 'TODO define',
|
269
|
+
'dsc' => 'TODO define'
|
270
|
+
})
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'should not be valid if a date is given' do
|
274
|
+
post '/type_validation/api/0.1/admins', valid_params.merge({
|
275
|
+
'last_signed_in_at' => DateTime.now.iso8601
|
276
|
+
})
|
277
|
+
|
278
|
+
expect(last_response).to have_success_response
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
RSpec::Matchers.define :have_error_response do
|
2
|
+
|
3
|
+
match do |response|
|
4
|
+
begin
|
5
|
+
@json = JSON(response.body)
|
6
|
+
|
7
|
+
is_valid_response?
|
8
|
+
rescue JSON::ParserError => exception
|
9
|
+
@error = "Error will parsing response: #{exception.message}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
description do
|
14
|
+
'have error response'
|
15
|
+
end
|
16
|
+
|
17
|
+
failure_message_for_should do
|
18
|
+
if @error
|
19
|
+
@error
|
20
|
+
elsif @json && @json['status']
|
21
|
+
"expect #{@json['status']} to be error\n#{@json.inspect}"
|
22
|
+
else
|
23
|
+
"expect #{@json} to include status in it's keys"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
failure_message_for_should_not do
|
28
|
+
if @error
|
29
|
+
@error
|
30
|
+
elsif @json && @json['status']
|
31
|
+
"expect #{@json['status']} to not be error\n#{@json.inspect}"
|
32
|
+
else
|
33
|
+
"expect #{@json} to include status in it's keys"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def is_valid_response?
|
38
|
+
@json && @json['status'] == 'error'
|
39
|
+
end
|
40
|
+
end
|