angus 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +15 -0
  2. data/lib/angus/base.rb +6 -3
  3. data/lib/angus/base_proxy.rb +20 -0
  4. data/lib/angus/base_resource.rb +8 -3
  5. data/lib/angus/generator/templates/definitions/operations.yml.erb +2 -0
  6. data/lib/angus/generator/templates/resources/resource.rb.erb +2 -2
  7. data/lib/angus/generator/thor/resource.rb +1 -1
  8. data/lib/angus/middleware/exception_handler.rb +2 -2
  9. data/lib/angus/request_handler.rb +7 -7
  10. data/lib/angus/rspec/support/examples.rb +3 -2
  11. data/lib/angus/rspec/support/examples/describe_errors.rb +23 -6
  12. data/lib/angus/utils/exceptions/invalid_parameter_type.rb +18 -0
  13. data/lib/angus/utils/exceptions/required_parameter_not_fond.rb +19 -0
  14. data/lib/angus/utils/params_validator.rb +81 -0
  15. data/spec/angus/middleware/exception_handler_spec.rb +16 -1
  16. data/spec/angus/rspec/examples/describe_errors_spec.rb +6 -0
  17. data/spec/functional/basic_spec.rb +2 -2
  18. data/spec/functional/empty_resource_spec.rb +2 -2
  19. data/spec/functional/no_resources_spec.rb +2 -2
  20. data/spec/functional/type_validation/definitions/admins/operations.yml +70 -0
  21. data/spec/functional/type_validation/definitions/messages.yml +0 -0
  22. data/spec/functional/type_validation/definitions/representations.yml +9 -0
  23. data/spec/functional/type_validation/definitions/service.yml +3 -0
  24. data/spec/functional/type_validation/models/admin.rb +1 -0
  25. data/spec/functional/type_validation/resources/admins.rb +35 -0
  26. data/spec/functional/type_validation/services/type_validation.rb +13 -0
  27. data/spec/functional/type_validation_spec.rb +283 -0
  28. data/spec/support/matchers/have_error_response_matcher.rb +40 -0
  29. data/spec/support/matchers/have_in_message_matcher.rb +47 -0
  30. data/spec/support/matchers/have_success_response_matcher.rb +40 -0
  31. 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
@@ -0,0 +1,9 @@
1
+ user:
2
+ - field: id
3
+ description: User identifier
4
+ required: true
5
+ type: integer
6
+ - field: name
7
+ description: User name
8
+ required: true
9
+ type: string
@@ -0,0 +1,3 @@
1
+ service: 'Type Validation'
2
+ code_name: 'type_validation'
3
+ version: '0.1'
@@ -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,13 @@
1
+ require 'angus'
2
+
3
+ module Spec
4
+ module Functional
5
+
6
+ class TypeValidation < Angus::Base
7
+ def configure
8
+ register :admins
9
+ end
10
+ end
11
+
12
+ end
13
+ 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