angus 0.0.9 → 0.0.10

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.
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