grape-swagger 0.10.2 → 0.10.4

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.
@@ -9,7 +9,7 @@ module GrapeSwagger
9
9
  ###
10
10
  def initialize(adapter)
11
11
  adapter = adapter.new if adapter.is_a?(Class)
12
- fail(ArgumentError, "The configured markdown adapter should implement the method #{ :markdown }") unless adapter.respond_to? :markdown
12
+ fail(ArgumentError, "The configured markdown adapter should implement the method #{:markdown}") unless adapter.respond_to? :markdown
13
13
  @adapter = adapter
14
14
  end
15
15
 
@@ -1,3 +1,3 @@
1
1
  module GrapeSwagger
2
- VERSION = '0.10.2'
2
+ VERSION = '0.10.4'
3
3
  end
@@ -12,9 +12,10 @@ describe 'API Description' do
12
12
  routes = subject.endpoints.first.routes
13
13
  expect(routes.count).to eq 2
14
14
  expect(routes.first.route_description).to eq 'Swagger compatible API description'
15
- expect(routes.first.route_params).to eq({})
15
+ expect(routes.first.route_params).to eq('locale' => { desc: 'Locale of API documentation', type: 'Symbol', required: false })
16
16
  expect(routes.last.route_description).to eq 'Swagger compatible API description for specific API'
17
- expect(routes.last.route_params).to eq('name' => { desc: 'Resource name of mounted API', type: 'String', required: true })
17
+ expect(routes.last.route_params).to eq('name' => { desc: 'Resource name of mounted API', type: 'String', required: true },
18
+ 'locale' => { desc: 'Locale of API documentation', type: 'Symbol', required: false })
18
19
  end
19
20
  end
20
21
 
@@ -31,10 +32,11 @@ describe 'API Description' do
31
32
  routes = subject.endpoints.first.routes
32
33
  expect(routes.count).to eq 2
33
34
  expect(routes.first.route_description).to eq 'First'
34
- expect(routes.first.route_params).to eq(x: 1)
35
+ expect(routes.first.route_params).to eq(x: 1, 'locale' => { desc: 'Locale of API documentation', type: 'Symbol', required: false })
35
36
  expect(routes.first.route_xx).to eq(11)
36
37
  expect(routes.last.route_description).to eq 'Second'
37
- expect(routes.last.route_params).to eq('name' => { desc: 'Resource name of mounted API', type: 'String', required: true }, y: 42)
38
+ expect(routes.last.route_params).to eq('name' => { desc: 'Resource name of mounted API', type: 'String', required: true }, y: 42,
39
+ 'locale' => { desc: 'Locale of API documentation', type: 'Symbol', required: false })
38
40
  expect(routes.last.route_yy).to eq(4242)
39
41
  end
40
42
  end
@@ -21,7 +21,7 @@ describe 'Array Params' do
21
21
  end
22
22
 
23
23
  params do
24
- optional :raw_array, type: Array[Integer]
24
+ optional :raw_array, type: Array[Integer], documentation: { is_array: true }
25
25
  end
26
26
  get :raw_array_integers do
27
27
  end
@@ -36,8 +36,8 @@ describe 'Array Params' do
36
36
  body = JSON.parse last_response.body
37
37
  parameters = body['apis'].first['operations'].first['parameters']
38
38
  expect(parameters).to eq [
39
- { 'paramType' => 'form', 'name' => 'a_array[][param_1]', 'description' => nil, 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' },
40
- { 'paramType' => 'form', 'name' => 'a_array[][param_2]', 'description' => nil, 'type' => 'string', 'required' => true, 'allowMultiple' => false }
39
+ { 'paramType' => 'form', 'name' => 'a_array[][param_1]', 'description' => '', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' },
40
+ { 'paramType' => 'form', 'name' => 'a_array[][param_2]', 'description' => '', 'type' => 'string', 'required' => true, 'allowMultiple' => false }
41
41
  ]
42
42
  end
43
43
 
@@ -47,7 +47,7 @@ describe 'Array Params' do
47
47
  body = JSON.parse last_response.body
48
48
  parameters = body['apis'].first['operations'].first['parameters']
49
49
  expect(parameters).to eq [
50
- { 'paramType' => 'query', 'name' => 'raw_array', 'description' => nil, 'type' => 'Array', 'required' => false, 'allowMultiple' => false }
50
+ { 'paramType' => 'query', 'name' => 'raw_array', 'description' => '', 'type' => 'Array', 'required' => false, 'allowMultiple' => false }
51
51
  ]
52
52
  end
53
53
 
@@ -57,7 +57,7 @@ describe 'Array Params' do
57
57
  body = JSON.parse last_response.body
58
58
  parameters = body['apis'].first['operations'].first['parameters']
59
59
  expect(parameters).to eq [
60
- { 'paramType' => 'query', 'name' => 'raw_array', 'description' => nil, 'type' => 'array', 'required' => false, 'allowMultiple' => false, 'items' => { 'type' => 'integer', 'format' => 'int32' } }
60
+ { 'paramType' => 'query', 'name' => 'raw_array', 'description' => '', 'type' => 'array', 'required' => false, 'allowMultiple' => false, 'items' => { 'type' => 'integer', 'format' => 'int32' } }
61
61
  ]
62
62
  end
63
63
  end
@@ -24,7 +24,7 @@ describe 'Boolean Params' do
24
24
 
25
25
  it 'converts boolean types' do
26
26
  expect(subject).to eq [
27
- { 'paramType' => 'form', 'name' => 'a_boolean', 'description' => nil, 'type' => 'boolean', 'required' => true, 'allowMultiple' => false }
27
+ { 'paramType' => 'form', 'name' => 'a_boolean', 'description' => '', 'type' => 'boolean', 'required' => true, 'allowMultiple' => false }
28
28
  ]
29
29
  end
30
30
  end
@@ -39,9 +39,8 @@ describe 'Default API' do
39
39
  end
40
40
  end
41
41
  end
42
-
43
42
  end
44
- context 'with additional option block given to desc', if: GrapeVersion.satisfy?('>= 0.12.0') do
43
+ context 'with additional option block given to desc', if: GrapeVersion.satisfy?('>= 0.12.0') do
45
44
  def app
46
45
  Class.new(Grape::API) do
47
46
  format :json
@@ -24,7 +24,7 @@ describe 'Float Params' do
24
24
 
25
25
  it 'converts float types' do
26
26
  expect(subject).to eq [
27
- { 'paramType' => 'form', 'name' => 'a_float', 'description' => nil, 'type' => 'number', 'format' => 'float', 'required' => true, 'allowMultiple' => false }
27
+ { 'paramType' => 'form', 'name' => 'a_float', 'description' => '', 'type' => 'number', 'format' => 'float', 'required' => true, 'allowMultiple' => false }
28
28
  ]
29
29
  end
30
30
  end
@@ -25,7 +25,7 @@ describe 'Group Params' do
25
25
  body = JSON.parse last_response.body
26
26
  parameters = body['apis'].first['operations'].first['parameters']
27
27
  expect(parameters).to eq [
28
- { 'paramType' => 'form', 'name' => 'required_group[required_param_1]', 'description' => nil, 'type' => 'string', 'required' => true, 'allowMultiple' => false },
29
- { 'paramType' => 'form', 'name' => 'required_group[required_param_2]', 'description' => nil, 'type' => 'string', 'required' => true, 'allowMultiple' => false }]
28
+ { 'paramType' => 'form', 'name' => 'required_group[required_param_1]', 'description' => '', 'type' => 'string', 'required' => true, 'allowMultiple' => false },
29
+ { 'paramType' => 'form', 'name' => 'required_group[required_param_2]', 'description' => '', 'type' => 'string', 'required' => true, 'allowMultiple' => false }]
30
30
  end
31
31
  end
@@ -24,7 +24,7 @@ describe 'Hash Params' do
24
24
 
25
25
  it 'declares hash types as object' do
26
26
  expect(subject).to eq [
27
- { 'paramType' => 'form', 'name' => 'a_hash', 'description' => nil, 'type' => 'object', 'required' => true, 'allowMultiple' => false }
27
+ { 'paramType' => 'form', 'name' => 'a_hash', 'description' => '', 'type' => 'object', 'required' => true, 'allowMultiple' => false }
28
28
  ]
29
29
  end
30
30
  end
data/spec/i18n_spec.rb ADDED
@@ -0,0 +1,364 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'I18n Default Translation' do
4
+ module Entities
5
+ class User < Grape::Entity
6
+ expose :id, documentation: { type: String }
7
+ expose :name, documentation: { type: String }
8
+ expose :email, documentation: { type: String }
9
+ expose :sign_up_at, documentation: { type: String }
10
+ end
11
+
12
+ class AdminUser < User
13
+ expose :level, documentation: { type: Integer }
14
+ end
15
+
16
+ class PasswordStrength < Grape::Entity
17
+ expose :level, documentation: { type: Integer }
18
+ expose :crack_time, documentation: { type: Float }
19
+ end
20
+ end
21
+
22
+ def app
23
+ Class.new(Grape::API) do
24
+ format :json
25
+
26
+ params do
27
+ optional :locale, type: Symbol
28
+ end
29
+ namespace :users do
30
+ desc nil do
31
+ success Entities::User
32
+ end
33
+ params do
34
+ optional :sort, type: String
35
+ end
36
+ get do
37
+ []
38
+ end
39
+
40
+ params do
41
+ requires :id, type: String
42
+ end
43
+ route_param :id do
44
+ desc '' do
45
+ success Entities::AdminUser
46
+ end
47
+ get do
48
+ {}
49
+ end
50
+
51
+ params do
52
+ requires :email, type: String
53
+ end
54
+ put :email do
55
+ end
56
+
57
+ desc nil do
58
+ success Entities::PasswordStrength
59
+ end
60
+ get :'password/strength' do
61
+ {}
62
+ end
63
+ end
64
+ end
65
+
66
+ add_swagger_documentation
67
+ end
68
+ end
69
+
70
+ def api_translations
71
+ yaml_en = <<-EOS.strip_heredoc
72
+ info:
73
+ title: My Awesome API
74
+ desc: Some detail information about this API.
75
+ entities:
76
+ default:
77
+ id: Resource identifier
78
+ user:
79
+ name: User's real name
80
+ email: User's login email address
81
+ sign_up_at: When the user signed up
82
+ admin_user:
83
+ level: Which level the admin is
84
+ password_strength:
85
+ level: A 0~4 integer indicates `very_weak` to `strong`
86
+ crack_time: An estimated time for force cracking the password, in seconds
87
+ params:
88
+ locale: Used to change locale of endpoint's responding message
89
+ sort: To specify the order of result list
90
+ users:
91
+ desc: Operations about not-disabled users
92
+ get:
93
+ desc: Gets a list of users
94
+ detail: You can control how to sort the results.
95
+ ':id':
96
+ params:
97
+ id: User id
98
+ get:
99
+ desc: Finds user by id
100
+ email:
101
+ put:
102
+ desc: Changes a user's email
103
+ params:
104
+ email: A new email
105
+ password:
106
+ strength:
107
+ get:
108
+ desc: Gets the strength estimation of a user's password
109
+ detail: The estimation is done by a well-known algorithm when he changed his password
110
+ swagger_doc:
111
+ desc: Endpoints for API documents
112
+ get:
113
+ desc: Gets root API document
114
+ ':name':
115
+ get:
116
+ desc: Gets specific resource API document
117
+ params:
118
+ name: Resource name
119
+ EOS
120
+
121
+ YAML.load(yaml_en)
122
+ end
123
+
124
+ context 'swagger_doc' do
125
+ subject do
126
+ with_translations :en, api: api_translations do
127
+ get '/swagger_doc'
128
+ JSON.parse(last_response.body).deep_symbolize_keys
129
+ end
130
+ end
131
+
132
+ it 'translates api info' do
133
+ expect(subject[:info]).to eq(
134
+ title: 'My Awesome API',
135
+ description: 'Some detail information about this API.'
136
+ )
137
+ end
138
+
139
+ it 'translates root namespace description (including swagger_doc)' do
140
+ expect(subject[:apis]).to eq [
141
+ { path: '/users.{format}', description: 'Operations about not-disabled users' },
142
+ { path: '/swagger_doc.{format}', description: 'Endpoints for API documents' }
143
+ ]
144
+ end
145
+ end
146
+
147
+ it 'translates endpoint description, notes and params' do
148
+ result = with_translations :en, api: api_translations do
149
+ get '/swagger_doc/users'
150
+ JSON.parse(last_response.body).deep_symbolize_keys
151
+ end
152
+
153
+ api_index = 0
154
+ expect(result[:apis][api_index][:operations][0]).to include(
155
+ summary: 'Gets a list of users', notes: 'You can control how to sort the results.'
156
+ )
157
+ expect(result[:apis][api_index][:operations][0][:parameters]).to eq [
158
+ { paramType: 'query', name: 'locale', description: "Used to change locale of endpoint's responding message", type: 'string', required: false, allowMultiple: false },
159
+ { paramType: 'query', name: 'sort', description: 'To specify the order of result list', type: 'string', required: false, allowMultiple: false }
160
+ ]
161
+
162
+ api_index += 1
163
+ expect(result[:apis][api_index][:operations][0]).to include(
164
+ summary: 'Finds user by id', notes: ''
165
+ )
166
+ expect(result[:apis][api_index][:operations][0][:parameters]).to eq [
167
+ { paramType: 'path', name: 'id', description: 'User id', type: 'string', required: true, allowMultiple: false },
168
+ { paramType: 'query', name: 'locale', description: "Used to change locale of endpoint's responding message", type: 'string', required: false, allowMultiple: false }
169
+ ]
170
+
171
+ api_index += 1
172
+ expect(result[:apis][api_index][:operations][0]).to include(
173
+ summary: "Changes a user's email", notes: ''
174
+ )
175
+ expect(result[:apis][api_index][:operations][0][:parameters]).to eq [
176
+ { paramType: 'path', name: 'id', description: 'User id', type: 'string', required: true, allowMultiple: false },
177
+ { paramType: 'form', name: 'locale', description: "Used to change locale of endpoint's responding message", type: 'string', required: false, allowMultiple: false },
178
+ { paramType: 'form', name: 'email', description: 'A new email', type: 'string', required: true, allowMultiple: false }
179
+ ]
180
+
181
+ api_index += 1
182
+ expect(result[:apis][api_index][:operations][0]).to include(
183
+ summary: "Gets the strength estimation of a user's password", notes: 'The estimation is done by a well-known algorithm when he changed his password'
184
+ )
185
+ expect(result[:apis][api_index][:operations][0][:parameters]).to eq [
186
+ { paramType: 'path', name: 'id', description: 'User id', type: 'string', required: true, allowMultiple: false },
187
+ { paramType: 'query', name: 'locale', description: "Used to change locale of endpoint's responding message", type: 'string', required: false, allowMultiple: false }
188
+ ]
189
+ end
190
+
191
+ it 'translates swagger doc endpoints description, notes and params' do
192
+ result = with_translations :en, api: api_translations do
193
+ get '/swagger_doc/swagger_doc'
194
+ JSON.parse(last_response.body).deep_symbolize_keys
195
+ end
196
+
197
+ api_index = 0
198
+ expect(result[:apis][api_index][:operations][0]).to include(
199
+ summary: 'Gets root API document'
200
+ )
201
+ expect(result[:apis][api_index][:operations][0][:parameters]).to eq [
202
+ { paramType: 'query', name: 'locale', description: "Used to change locale of endpoint's responding message", type: 'string', required: false, allowMultiple: false }
203
+ ]
204
+
205
+ api_index += 1
206
+ expect(result[:apis][api_index][:operations][0]).to include(
207
+ summary: 'Gets specific resource API document'
208
+ )
209
+ expect(result[:apis][api_index][:operations][0][:parameters]).to eq [
210
+ { paramType: 'path', name: 'name', description: 'Resource name', type: 'string', required: true, allowMultiple: false },
211
+ { paramType: 'query', name: 'locale', description: "Used to change locale of endpoint's responding message", type: 'string', required: false, allowMultiple: false }
212
+ ]
213
+ end
214
+ end
215
+
216
+ describe 'I18n Customized Translation' do
217
+ def api_translations
218
+ yaml_en = <<-EOS.strip_heredoc
219
+ info:
220
+ title: My Awesome I18n API
221
+ desc: Some details in English
222
+ custom:
223
+ api_info: My Custom Awesome API
224
+ interpolation: My %{keyword} API
225
+ EOS
226
+
227
+ YAML.load(yaml_en)
228
+ end
229
+
230
+ def extra_translations
231
+ yaml_en = <<-EOS.strip_heredoc
232
+ info:
233
+ title: My Awesome I18n API in Extra Scope
234
+ desc: Some details in English in Extra Scope
235
+ custom:
236
+ api_info: My Custom Awesome API in Extra Scope
237
+ interpolation: This API supports %{count} languages, and by default it is in %{language}.
238
+ EOS
239
+
240
+ YAML.load(yaml_en)
241
+ end
242
+
243
+ subject do
244
+ with_translations :en, api: api_translations, extra: extra_translations do
245
+ get '/swagger_doc'
246
+ JSON.parse(last_response.body).deep_symbolize_keys
247
+ end
248
+ end
249
+
250
+ context 'a string' do
251
+ def app
252
+ Class.new(Grape::API) do
253
+ format :json
254
+ add_swagger_documentation info: {
255
+ title: 'My Plain API', description: 'Boring description', license: 'MIT License'
256
+ }
257
+ end
258
+ end
259
+
260
+ it 'became default message when translation missing' do
261
+ expect(subject[:info]).to eq(
262
+ title: 'My Awesome I18n API',
263
+ description: 'Some details in English',
264
+ license: 'MIT License'
265
+ )
266
+ end
267
+ end
268
+
269
+ context 'a symbol' do
270
+ def app
271
+ Class.new(Grape::API) do
272
+ format :json
273
+ add_swagger_documentation info: { title: :'custom.api_info', description: :missing }
274
+ end
275
+ end
276
+
277
+ it 'acts as custom lookup key' do
278
+ expect(subject[:info][:title]).to eq 'My Custom Awesome API'
279
+ end
280
+
281
+ it 'can fallback to default key' do
282
+ expect(subject[:info][:description]).to eq 'Some details in English'
283
+ end
284
+ end
285
+
286
+ context 'a hash' do
287
+ context 'using :key and :default' do
288
+ def app
289
+ Class.new(Grape::API) do
290
+ format :json
291
+ add_swagger_documentation info: {
292
+ title: { key: :'custom.api_info', default: 'A Demo API' },
293
+ description: { key: :missing, default: 'No need to say anything more' },
294
+ license: { key: :license, default: 'MIT License' }
295
+ }
296
+ end
297
+ end
298
+
299
+ it 'to define custom lookup key and default message together' do
300
+ expect(subject[:info]).to eq(
301
+ title: 'My Custom Awesome API',
302
+ description: 'Some details in English',
303
+ license: 'MIT License'
304
+ )
305
+ end
306
+ end
307
+
308
+ context 'using :translate with "false"' do
309
+ def app
310
+ Class.new(Grape::API) do
311
+ format :json
312
+ add_swagger_documentation info: {
313
+ title: { default: 'A Demo API', translate: false },
314
+ description: { translate: false }
315
+ }
316
+ end
317
+ end
318
+
319
+ it 'to skip translation' do
320
+ expect(subject[:info]).to eq(
321
+ title: 'A Demo API'
322
+ )
323
+ end
324
+ end
325
+
326
+ context 'using :scope' do
327
+ def app
328
+ Class.new(Grape::API) do
329
+ format :json
330
+ add_swagger_documentation info: {
331
+ title: { key: :'custom.api_info', scope: :extra },
332
+ description: { scope: 'extra' }
333
+ }
334
+ end
335
+ end
336
+
337
+ it 'to look up in custom scope' do
338
+ expect(subject[:info]).to eq(
339
+ title: 'My Custom Awesome API in Extra Scope',
340
+ description: 'Some details in English in Extra Scope'
341
+ )
342
+ end
343
+ end
344
+
345
+ context 'all other params' do
346
+ def app
347
+ Class.new(Grape::API) do
348
+ format :json
349
+ add_swagger_documentation info: {
350
+ title: { key: :interpolation, keyword: 'Best' },
351
+ description: { key: :interpolation, scope: :extra, count: 2, language: 'English' }
352
+ }
353
+ end
354
+ end
355
+
356
+ it 'can be interpolated into the translation' do
357
+ expect(subject[:info]).to eq(
358
+ title: 'My Best API',
359
+ description: 'This API supports 2 languages, and by default it is in English.'
360
+ )
361
+ end
362
+ end
363
+ end
364
+ end