grape-swagger 1.1.0 → 1.4.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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +14 -0
- data/.github/workflows/rubocop.yml +26 -0
- data/.github/workflows/ruby.yml +30 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/.rubocop.yml +65 -2
- data/.rubocop_todo.yml +1 -1
- data/CHANGELOG.md +66 -0
- data/Gemfile +9 -4
- data/README.md +213 -13
- data/UPGRADING.md +38 -0
- data/grape-swagger.gemspec +4 -4
- data/lib/grape-swagger/doc_methods/build_model_definition.rb +53 -2
- data/lib/grape-swagger/doc_methods/data_type.rb +4 -4
- data/lib/grape-swagger/doc_methods/format_data.rb +4 -2
- data/lib/grape-swagger/doc_methods/move_params.rb +6 -7
- data/lib/grape-swagger/doc_methods/operation_id.rb +2 -2
- data/lib/grape-swagger/doc_methods/parse_params.rb +51 -9
- data/lib/grape-swagger/doc_methods.rb +65 -62
- data/lib/grape-swagger/endpoint.rb +83 -32
- data/lib/grape-swagger/errors.rb +2 -0
- data/lib/grape-swagger/model_parsers.rb +2 -2
- data/lib/grape-swagger/rake/oapi_tasks.rb +3 -1
- data/lib/grape-swagger/version.rb +1 -1
- data/lib/grape-swagger.rb +7 -4
- data/spec/issues/427_entity_as_string_spec.rb +1 -1
- data/spec/issues/430_entity_definitions_spec.rb +7 -5
- data/spec/issues/537_enum_values_spec.rb +1 -0
- data/spec/issues/776_multiple_presents_spec.rb +59 -0
- data/spec/issues/809_utf8_routes_spec.rb +55 -0
- data/spec/issues/832_array_hash_float_decimal_spec.rb +111 -0
- data/spec/lib/data_type_spec.rb +12 -0
- data/spec/lib/format_data_spec.rb +24 -0
- data/spec/lib/move_params_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -1
- data/spec/support/empty_model_parser.rb +3 -2
- data/spec/support/mock_parser.rb +1 -2
- data/spec/support/model_parsers/entity_parser.rb +8 -8
- data/spec/support/model_parsers/mock_parser.rb +24 -8
- data/spec/support/model_parsers/representable_parser.rb +8 -8
- data/spec/support/namespace_tags.rb +3 -0
- data/spec/support/the_paths_definitions.rb +4 -4
- data/spec/swagger_v2/api_swagger_v2_additional_properties_spec.rb +83 -0
- data/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb +1 -1
- data/spec/swagger_v2/api_swagger_v2_mounted_spec.rb +1 -0
- data/spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb +73 -1
- data/spec/swagger_v2/api_swagger_v2_param_type_body_spec.rb +2 -2
- data/spec/swagger_v2/api_swagger_v2_response_with_headers_spec.rb +4 -2
- data/spec/swagger_v2/api_swagger_v2_response_with_models_spec.rb +53 -0
- data/spec/swagger_v2/api_swagger_v2_spec.rb +1 -0
- data/spec/swagger_v2/boolean_params_spec.rb +4 -1
- data/spec/swagger_v2/float_api_spec.rb +1 -0
- data/spec/swagger_v2/inheritance_and_discriminator_spec.rb +57 -0
- data/spec/swagger_v2/namespace_tags_prefix_spec.rb +1 -0
- data/spec/swagger_v2/param_multi_type_spec.rb +2 -0
- data/spec/swagger_v2/param_type_spec.rb +3 -0
- data/spec/swagger_v2/param_values_spec.rb +6 -0
- data/spec/swagger_v2/{params_array_collection_fromat_spec.rb → params_array_collection_format_spec.rb} +0 -0
- data/spec/swagger_v2/params_example_spec.rb +40 -0
- data/spec/swagger_v2/reference_entity_spec.rb +74 -29
- data/spec/swagger_v2/security_requirement_spec.rb +2 -2
- data/spec/swagger_v2/simple_mounted_api_spec.rb +3 -0
- metadata +31 -13
- data/.travis.yml +0 -35
@@ -218,22 +218,22 @@ RSpec.shared_context 'representable swagger example' do
|
|
218
218
|
|
219
219
|
let(:swagger_nested_type) do
|
220
220
|
{
|
221
|
-
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => '
|
222
|
-
'UseItemResponseAsType' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, 'responses' => { 'description' => '', 'type' => 'ResponseItem' } }, 'description' => '
|
221
|
+
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' },
|
222
|
+
'UseItemResponseAsType' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, 'responses' => { 'description' => '', 'type' => 'ResponseItem' } }, 'description' => 'UseItemResponseAsType model' }
|
223
223
|
}
|
224
224
|
end
|
225
225
|
|
226
226
|
let(:swagger_entity_as_response_object) do
|
227
227
|
{
|
228
|
-
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => '
|
228
|
+
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' },
|
229
229
|
'ResponseItem' => { 'type' => 'object', 'properties' => { 'id' => { 'description' => '', 'type' => 'integer', 'format' => 'int32' }, 'name' => { 'description' => '', 'type' => 'string' } } },
|
230
|
-
'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' }, 'description' => '' } }, 'description' => '
|
230
|
+
'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' }, 'description' => '' } }, 'description' => 'UseResponse model' }
|
231
231
|
}
|
232
232
|
end
|
233
233
|
|
234
234
|
let(:swagger_params_as_response_object) do
|
235
235
|
{
|
236
|
-
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => '
|
236
|
+
'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' }
|
237
237
|
}
|
238
238
|
end
|
239
239
|
|
@@ -372,7 +372,7 @@ RSpec.shared_context 'representable swagger example' do
|
|
372
372
|
'type' => 'object',
|
373
373
|
'required' => ['elements'],
|
374
374
|
'properties' => { 'elements' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/QueryInputElement' }, 'description' => 'Set of configuration' } },
|
375
|
-
'description' => '
|
375
|
+
'description' => 'QueryInput model'
|
376
376
|
},
|
377
377
|
'QueryInputElement' => {
|
378
378
|
'type' => 'object',
|
@@ -382,7 +382,7 @@ RSpec.shared_context 'representable swagger example' do
|
|
382
382
|
'ApiError' => {
|
383
383
|
'type' => 'object',
|
384
384
|
'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } },
|
385
|
-
'description' => '
|
385
|
+
'description' => 'ApiError model'
|
386
386
|
},
|
387
387
|
'Something' => {
|
388
388
|
'type' => 'object',
|
@@ -392,7 +392,7 @@ RSpec.shared_context 'representable swagger example' do
|
|
392
392
|
'links' => { 'type' => 'array', 'items' => { 'description' => '', 'type' => 'link' } },
|
393
393
|
'others' => { 'description' => '', 'type' => 'text' }
|
394
394
|
},
|
395
|
-
'description' => '
|
395
|
+
'description' => 'Something model'
|
396
396
|
}
|
397
397
|
}
|
398
398
|
}
|
@@ -3,12 +3,15 @@
|
|
3
3
|
RSpec.shared_context 'namespace example' do
|
4
4
|
before :all do
|
5
5
|
module TheApi
|
6
|
+
# rubocop:disable Lint/EmptyClass
|
6
7
|
class CustomType; end
|
8
|
+
# rubocop:enable Lint/EmptyClass
|
7
9
|
|
8
10
|
class NamespaceApi < Grape::API
|
9
11
|
namespace :hudson do
|
10
12
|
desc 'Document root'
|
11
13
|
get '/' do
|
14
|
+
{ message: 'hi' }
|
12
15
|
end
|
13
16
|
end
|
14
17
|
|
@@ -8,7 +8,7 @@ RSpec.shared_context 'the api paths/defs' do
|
|
8
8
|
produces: ['application/json'],
|
9
9
|
consumes: ['application/json'],
|
10
10
|
parameters: [
|
11
|
-
{ in: 'body', name: 'in_body_1', description: 'in_body_1', type: 'integer', format: 'int32', required: true },
|
11
|
+
{ in: 'body', name: 'in_body_1', description: 'in_body_1', type: 'integer', format: 'int32', required: true, example: 23 },
|
12
12
|
{ in: 'body', name: 'in_body_2', description: 'in_body_2', type: 'string', required: false },
|
13
13
|
{ in: 'body', name: 'in_body_3', description: 'in_body_3', type: 'string', required: false }
|
14
14
|
],
|
@@ -31,7 +31,7 @@ RSpec.shared_context 'the api paths/defs' do
|
|
31
31
|
{ in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
|
32
32
|
{ in: 'body', name: 'in_body_1', description: 'in_body_1', type: 'integer', format: 'int32', required: true },
|
33
33
|
{ in: 'body', name: 'in_body_2', description: 'in_body_2', type: 'string', required: false },
|
34
|
-
{ in: 'body', name: 'in_body_3', description: 'in_body_3', type: 'string', required: false }
|
34
|
+
{ in: 'body', name: 'in_body_3', description: 'in_body_3', type: 'string', required: false, example: 'my example string' }
|
35
35
|
],
|
36
36
|
responses: { 200 => { description: 'put in body /wo entity', schema: { '$ref' => '#/definitions/InBody' } } },
|
37
37
|
tags: ['in_body'],
|
@@ -85,7 +85,7 @@ RSpec.shared_context 'the api paths/defs' do
|
|
85
85
|
{
|
86
86
|
type: 'object',
|
87
87
|
properties: {
|
88
|
-
in_body_1: { type: 'integer', format: 'int32', description: 'in_body_1' },
|
88
|
+
in_body_1: { type: 'integer', format: 'int32', description: 'in_body_1', example: 23 },
|
89
89
|
in_body_2: { type: 'string', description: 'in_body_2' },
|
90
90
|
in_body_3: { type: 'string', description: 'in_body_3' }
|
91
91
|
},
|
@@ -99,7 +99,7 @@ RSpec.shared_context 'the api paths/defs' do
|
|
99
99
|
properties: {
|
100
100
|
in_body_1: { type: 'integer', format: 'int32', description: 'in_body_1' },
|
101
101
|
in_body_2: { type: 'string', description: 'in_body_2' },
|
102
|
-
in_body_3: { type: 'string', description: 'in_body_3' }
|
102
|
+
in_body_3: { type: 'string', description: 'in_body_3', example: 'my example string' }
|
103
103
|
},
|
104
104
|
required: [:in_body_1]
|
105
105
|
}
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'parsing additional_parameters' do
|
6
|
+
let(:app) do
|
7
|
+
Class.new(Grape::API) do
|
8
|
+
namespace :things do
|
9
|
+
class Element < Grape::Entity
|
10
|
+
expose :id
|
11
|
+
end
|
12
|
+
|
13
|
+
params do
|
14
|
+
optional :closed, type: Hash, documentation: { additional_properties: false, in: 'body' } do
|
15
|
+
requires :only
|
16
|
+
end
|
17
|
+
optional :open, type: Hash, documentation: { additional_properties: true }
|
18
|
+
optional :type_limited, type: Hash, documentation: { additional_properties: String }
|
19
|
+
optional :ref_limited, type: Hash, documentation: { additional_properties: Element }
|
20
|
+
optional :fallback, type: Hash, documentation: { additional_properties: { type: 'integer' } }
|
21
|
+
end
|
22
|
+
post do
|
23
|
+
present params
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
add_swagger_documentation format: :json, models: [Element]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
subject do
|
32
|
+
get '/swagger_doc/things'
|
33
|
+
JSON.parse(last_response.body)
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'POST' do
|
37
|
+
specify do
|
38
|
+
expect(subject.dig('paths', '/things', 'post', 'parameters')).to eql(
|
39
|
+
[
|
40
|
+
{ 'name' => 'Things', 'in' => 'body', 'required' => true, 'schema' => { '$ref' => '#/definitions/postThings' } }
|
41
|
+
]
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
specify do
|
46
|
+
expect(subject.dig('definitions', 'postThings')).to eql(
|
47
|
+
'type' => 'object',
|
48
|
+
'properties' => {
|
49
|
+
'closed' => {
|
50
|
+
'type' => 'object',
|
51
|
+
'additionalProperties' => false,
|
52
|
+
'properties' => {
|
53
|
+
'only' => { 'type' => 'string' }
|
54
|
+
},
|
55
|
+
'required' => ['only']
|
56
|
+
},
|
57
|
+
'open' => {
|
58
|
+
'type' => 'object',
|
59
|
+
'additionalProperties' => true
|
60
|
+
},
|
61
|
+
'type_limited' => {
|
62
|
+
'type' => 'object',
|
63
|
+
'additionalProperties' => {
|
64
|
+
'type' => 'string'
|
65
|
+
}
|
66
|
+
},
|
67
|
+
'ref_limited' => {
|
68
|
+
'type' => 'object',
|
69
|
+
'additionalProperties' => {
|
70
|
+
'$ref' => '#/definitions/Element'
|
71
|
+
}
|
72
|
+
},
|
73
|
+
'fallback' => {
|
74
|
+
'type' => 'object',
|
75
|
+
'additionalProperties' => {
|
76
|
+
'type' => 'integer'
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -19,7 +19,7 @@ describe 'hidden flag enables a single endpoint parameter to be excluded from th
|
|
19
19
|
requires :name, type: String, documentation: { desc: 'name' }
|
20
20
|
optional :favourite_color, type: String, documentation: { desc: 'I should not be anywhere', hidden: true }
|
21
21
|
optional :proc_param, type: String, documentation: { desc: 'I should not be anywhere', hidden: proc { true } }
|
22
|
-
optional :proc_with_token, type: String, documentation: { desc: 'I may be somewhere', hidden: proc {
|
22
|
+
optional :proc_with_token, type: String, documentation: { desc: 'I may be somewhere', hidden: proc { false } }
|
23
23
|
end
|
24
24
|
|
25
25
|
post do
|
@@ -13,7 +13,7 @@ describe 'moving body/formData Params to definitions' do
|
|
13
13
|
detail: 'more details description',
|
14
14
|
success: Entities::UseNestedWithAddress
|
15
15
|
params do
|
16
|
-
optional :contact, type: Hash do
|
16
|
+
optional :contact, type: Hash, documentation: { additional_properties: true } do
|
17
17
|
requires :name, type: String, documentation: { desc: 'name', in: 'body' }
|
18
18
|
optional :addresses, type: Array do
|
19
19
|
requires :street, type: String, documentation: { desc: 'street', in: 'body' }
|
@@ -96,6 +96,27 @@ describe 'moving body/formData Params to definitions' do
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
+
namespace :nested_params_array do
|
100
|
+
desc 'post in body with array of nested parameters',
|
101
|
+
detail: 'more details description',
|
102
|
+
success: Entities::UseNestedWithAddress
|
103
|
+
params do
|
104
|
+
optional :contacts, type: Array, documentation: { additional_properties: false } do
|
105
|
+
requires :name, type: String, documentation: { desc: 'name', in: 'body' }
|
106
|
+
optional :addresses, type: Array do
|
107
|
+
requires :street, type: String, documentation: { desc: 'street', in: 'body' }
|
108
|
+
requires :postcode, type: String, documentation: { desc: 'postcode', in: 'body' }
|
109
|
+
requires :city, type: String, documentation: { desc: 'city', in: 'body' }
|
110
|
+
optional :country, type: String, documentation: { desc: 'country', in: 'body' }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
post '/in_body' do
|
116
|
+
{ 'declared_params' => declared(params) }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
99
120
|
add_swagger_documentation
|
100
121
|
end
|
101
122
|
end
|
@@ -126,6 +147,7 @@ describe 'moving body/formData Params to definitions' do
|
|
126
147
|
'properties' => {
|
127
148
|
'contact' => {
|
128
149
|
'type' => 'object',
|
150
|
+
'additionalProperties' => true,
|
129
151
|
'properties' => {
|
130
152
|
'name' => { 'type' => 'string', 'description' => 'name' },
|
131
153
|
'addresses' => {
|
@@ -280,4 +302,54 @@ describe 'moving body/formData Params to definitions' do
|
|
280
302
|
end
|
281
303
|
end
|
282
304
|
end
|
305
|
+
|
306
|
+
describe 'array of nested body parameters given' do
|
307
|
+
subject do
|
308
|
+
get '/swagger_doc/nested_params_array'
|
309
|
+
JSON.parse(last_response.body)
|
310
|
+
end
|
311
|
+
|
312
|
+
describe 'POST' do
|
313
|
+
specify do
|
314
|
+
expect(subject['paths']['/nested_params_array/in_body']['post']['parameters']).to eql(
|
315
|
+
[
|
316
|
+
{ 'name' => 'NestedParamsArrayInBody', 'in' => 'body', 'required' => true, 'schema' => { '$ref' => '#/definitions/postNestedParamsArrayInBody' } }
|
317
|
+
]
|
318
|
+
)
|
319
|
+
end
|
320
|
+
|
321
|
+
specify do
|
322
|
+
expect(subject['definitions']['postNestedParamsArrayInBody']).to eql(
|
323
|
+
'type' => 'object',
|
324
|
+
'properties' => {
|
325
|
+
'contacts' => {
|
326
|
+
'type' => 'array',
|
327
|
+
'items' => {
|
328
|
+
'type' => 'object',
|
329
|
+
'additionalProperties' => false,
|
330
|
+
'properties' => {
|
331
|
+
'name' => { 'type' => 'string', 'description' => 'name' },
|
332
|
+
'addresses' => {
|
333
|
+
'type' => 'array',
|
334
|
+
'items' => {
|
335
|
+
'type' => 'object',
|
336
|
+
'properties' => {
|
337
|
+
'street' => { 'type' => 'string', 'description' => 'street' },
|
338
|
+
'postcode' => { 'type' => 'string', 'description' => 'postcode' },
|
339
|
+
'city' => { 'type' => 'string', 'description' => 'city' },
|
340
|
+
'country' => { 'type' => 'string', 'description' => 'country' }
|
341
|
+
},
|
342
|
+
'required' => %w[street postcode city]
|
343
|
+
}
|
344
|
+
}
|
345
|
+
},
|
346
|
+
'required' => %w[name]
|
347
|
+
}
|
348
|
+
}
|
349
|
+
},
|
350
|
+
'description' => 'post in body with array of nested parameters'
|
351
|
+
)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
283
355
|
end
|
@@ -189,7 +189,7 @@ describe 'setting of param type, such as `query`, `path`, `formData`, `body`, `h
|
|
189
189
|
'type' => 'object',
|
190
190
|
'properties' => {
|
191
191
|
'data' => {
|
192
|
-
'$ref' => '#/definitions/
|
192
|
+
'$ref' => '#/definitions/NestedModule_ApiResponse',
|
193
193
|
'description' => 'request data'
|
194
194
|
}
|
195
195
|
},
|
@@ -207,7 +207,7 @@ describe 'setting of param type, such as `query`, `path`, `formData`, `body`, `h
|
|
207
207
|
end
|
208
208
|
|
209
209
|
specify do
|
210
|
-
expect(subject['definitions']['
|
210
|
+
expect(subject['definitions']['NestedModule_ApiResponse']).not_to be_nil
|
211
211
|
end
|
212
212
|
|
213
213
|
specify do
|
@@ -19,7 +19,8 @@ describe 'response with headers' do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
desc 'A 204 can have headers too' do
|
22
|
-
|
22
|
+
foo = { status: 204, message: 'No content', headers: { 'Location' => { description: 'Location of resource', type: 'string' } } }
|
23
|
+
success foo
|
23
24
|
failure [[400, 'Bad Request', Entities::ApiError, { 'application/json' => { code: 400, message: 'Bad request' } }, { 'Date' => { description: 'Date of failure', type: 'string' } }]]
|
24
25
|
end
|
25
26
|
delete '/no_content_response_headers' do
|
@@ -27,7 +28,8 @@ describe 'response with headers' do
|
|
27
28
|
end
|
28
29
|
|
29
30
|
desc 'A file can have headers too' do
|
30
|
-
|
31
|
+
foo = { status: 200, model: 'File', headers: { 'Cache-Control': { description: 'Directive for caching', type: 'string' } } }
|
32
|
+
success foo
|
31
33
|
failure [[404, 'NotFound', Entities::ApiError, { 'application/json' => { code: 404, message: 'Not found' } }, { 'Date' => { description: 'Date of failure', type: 'string' } }]]
|
32
34
|
end
|
33
35
|
get '/file_response_headers' do
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'response' do
|
6
|
+
include_context "#{MODEL_PARSER} swagger example"
|
7
|
+
|
8
|
+
before :all do
|
9
|
+
module TheApi
|
10
|
+
class ResponseApiModels < Grape::API
|
11
|
+
format :json
|
12
|
+
|
13
|
+
desc 'This returns something',
|
14
|
+
success: [{ code: 200 }],
|
15
|
+
failure: [
|
16
|
+
{ code: 400, message: 'NotFound', model: '' },
|
17
|
+
{ code: 404, message: 'BadRequest', model: Entities::ApiError }
|
18
|
+
]
|
19
|
+
get '/use-response' do
|
20
|
+
{ 'declared_params' => declared(params) }
|
21
|
+
end
|
22
|
+
|
23
|
+
add_swagger_documentation(models: [Entities::UseResponse])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def app
|
29
|
+
TheApi::ResponseApiModels
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'uses entity as response object implicitly with route name' do
|
33
|
+
subject do
|
34
|
+
get '/swagger_doc/use-response'
|
35
|
+
JSON.parse(last_response.body)
|
36
|
+
end
|
37
|
+
|
38
|
+
specify do
|
39
|
+
expect(subject['paths']['/use-response']['get']).to eql(
|
40
|
+
'description' => 'This returns something',
|
41
|
+
'produces' => ['application/json'],
|
42
|
+
'responses' => {
|
43
|
+
'200' => { 'description' => 'This returns something', 'schema' => { '$ref' => '#/definitions/UseResponse' } },
|
44
|
+
'400' => { 'description' => 'NotFound' },
|
45
|
+
'404' => { 'description' => 'BadRequest', 'schema' => { '$ref' => '#/definitions/ApiError' } }
|
46
|
+
},
|
47
|
+
'tags' => ['use-response'],
|
48
|
+
'operationId' => 'getUseResponse'
|
49
|
+
)
|
50
|
+
expect(subject['definitions']).to eql(swagger_entity_as_response_object)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -9,8 +9,10 @@ describe 'Boolean Params' do
|
|
9
9
|
|
10
10
|
params do
|
11
11
|
requires :a_boolean, type: Grape::API::Boolean
|
12
|
+
optional :another_boolean, type: Grape::API::Boolean, default: false
|
12
13
|
end
|
13
14
|
post :splines do
|
15
|
+
{ message: 'hi' }
|
14
16
|
end
|
15
17
|
|
16
18
|
add_swagger_documentation
|
@@ -26,7 +28,8 @@ describe 'Boolean Params' do
|
|
26
28
|
|
27
29
|
it 'converts boolean types' do
|
28
30
|
expect(subject).to eq [
|
29
|
-
{ 'in' => 'formData', 'name' => 'a_boolean', 'type' => 'boolean', 'required' => true }
|
31
|
+
{ 'in' => 'formData', 'name' => 'a_boolean', 'type' => 'boolean', 'required' => true },
|
32
|
+
{ 'in' => 'formData', 'name' => 'another_boolean', 'type' => 'boolean', 'required' => false, 'default' => false }
|
30
33
|
]
|
31
34
|
end
|
32
35
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'Inheritance and Discriminator' do
|
6
|
+
before :all do
|
7
|
+
module InheritanceTest
|
8
|
+
module Entities
|
9
|
+
# example from https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#models-with-polymorphism-supports
|
10
|
+
class Pet < Grape::Entity
|
11
|
+
expose :type, documentation: {
|
12
|
+
type: 'string',
|
13
|
+
is_discriminator: true,
|
14
|
+
required: true
|
15
|
+
}
|
16
|
+
expose :name, documentation: {
|
17
|
+
type: 'string',
|
18
|
+
required: true
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
class Cat < Pet
|
23
|
+
expose :huntingSkill, documentation: {
|
24
|
+
type: 'string',
|
25
|
+
description: 'The measured skill for hunting',
|
26
|
+
default: 'lazy',
|
27
|
+
values: %w[
|
28
|
+
clueless
|
29
|
+
lazy
|
30
|
+
adventurous
|
31
|
+
aggressive
|
32
|
+
]
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class NameApi < Grape::API
|
38
|
+
add_swagger_documentation models: [Entities::Pet, Entities::Cat]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'Parent model' do
|
44
|
+
let(:app) { InheritanceTest::NameApi }
|
45
|
+
|
46
|
+
subject do
|
47
|
+
get '/swagger_doc'
|
48
|
+
JSON.parse(last_response.body)['definitions']
|
49
|
+
end
|
50
|
+
|
51
|
+
specify do
|
52
|
+
subject['InheritanceTest_Entities_Pet'].key?('discriminator')
|
53
|
+
subject['InheritanceTest_Entities_Pet']['discriminator'] = 'type'
|
54
|
+
subject['InheritanceTest_Entities_Cat'].key?('allOf')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -16,6 +16,7 @@ describe 'Params Multi Types' do
|
|
16
16
|
requires :another_input, type: [String, Integer]
|
17
17
|
end
|
18
18
|
post :action do
|
19
|
+
{ message: 'hi' }
|
19
20
|
end
|
20
21
|
|
21
22
|
add_swagger_documentation
|
@@ -61,6 +62,7 @@ describe 'Params Multi Types' do
|
|
61
62
|
requires :another_input, type: [String, Integer]
|
62
63
|
end
|
63
64
|
post :action do
|
65
|
+
{ message: 'hi' }
|
64
66
|
end
|
65
67
|
|
66
68
|
add_swagger_documentation
|
@@ -11,12 +11,14 @@ describe 'Params Types' do
|
|
11
11
|
requires :input, type: String
|
12
12
|
end
|
13
13
|
post :action do
|
14
|
+
{ message: 'hi' }
|
14
15
|
end
|
15
16
|
|
16
17
|
params do
|
17
18
|
requires :input, type: String, default: '14', documentation: { type: 'email', default: '42' }
|
18
19
|
end
|
19
20
|
post :action_with_doc do
|
21
|
+
{ message: 'hi' }
|
20
22
|
end
|
21
23
|
|
22
24
|
add_swagger_documentation
|
@@ -49,6 +51,7 @@ describe 'Params Types' do
|
|
49
51
|
requires :input, type: String
|
50
52
|
end
|
51
53
|
post :action do
|
54
|
+
{ message: 'hi' }
|
52
55
|
end
|
53
56
|
|
54
57
|
add_swagger_documentation
|
@@ -12,24 +12,28 @@ describe 'Convert values to enum or Range' do
|
|
12
12
|
requires :letter, type: String, values: %w[a b c]
|
13
13
|
end
|
14
14
|
post :plain_array do
|
15
|
+
{ message: 'hi' }
|
15
16
|
end
|
16
17
|
|
17
18
|
params do
|
18
19
|
requires :letter, type: String, values: proc { %w[d e f] }
|
19
20
|
end
|
20
21
|
post :array_in_proc do
|
22
|
+
{ message: 'hi' }
|
21
23
|
end
|
22
24
|
|
23
25
|
params do
|
24
26
|
requires :letter, type: String, values: 'a'..'z'
|
25
27
|
end
|
26
28
|
post :range_letter do
|
29
|
+
{ message: 'hi' }
|
27
30
|
end
|
28
31
|
|
29
32
|
params do
|
30
33
|
requires :integer, type: Integer, values: -5..5
|
31
34
|
end
|
32
35
|
post :range_integer do
|
36
|
+
{ message: 'hi' }
|
33
37
|
end
|
34
38
|
|
35
39
|
add_swagger_documentation
|
@@ -107,12 +111,14 @@ describe 'Convert values to enum for float range and not arrays inside a proc',
|
|
107
111
|
requires :letter, type: String, values: proc { 'string' }
|
108
112
|
end
|
109
113
|
post :non_array_in_proc do
|
114
|
+
{ message: 'hi' }
|
110
115
|
end
|
111
116
|
|
112
117
|
params do
|
113
118
|
requires :float, type: Float, values: -5.0..5.0
|
114
119
|
end
|
115
120
|
post :range_float do
|
121
|
+
{ message: 'hi' }
|
116
122
|
end
|
117
123
|
|
118
124
|
add_swagger_documentation
|
File without changes
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'Param example' do
|
6
|
+
def app
|
7
|
+
Class.new(Grape::API) do
|
8
|
+
format :json
|
9
|
+
|
10
|
+
params do
|
11
|
+
requires :id, type: Integer, documentation: { example: 123 }
|
12
|
+
optional :name, type: String, documentation: { example: 'Person' }
|
13
|
+
optional :obj, type: 'Object', documentation: { example: { 'foo' => 'bar' } }
|
14
|
+
end
|
15
|
+
|
16
|
+
get '/endpoint_with_examples' do
|
17
|
+
{ 'declared_params' => declared(params) }
|
18
|
+
end
|
19
|
+
|
20
|
+
add_swagger_documentation
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'documentation with parameter examples' do
|
25
|
+
subject do
|
26
|
+
get '/swagger_doc/endpoint_with_examples'
|
27
|
+
JSON.parse(last_response.body)
|
28
|
+
end
|
29
|
+
|
30
|
+
specify do
|
31
|
+
expect(subject['paths']['/endpoint_with_examples']['get']['parameters']).to eql(
|
32
|
+
[
|
33
|
+
{ 'in' => 'query', 'name' => 'id', 'type' => 'integer', 'example' => 123, 'format' => 'int32', 'required' => true },
|
34
|
+
{ 'in' => 'query', 'name' => 'name', 'type' => 'string', 'example' => 'Person', 'required' => false },
|
35
|
+
{ 'in' => 'query', 'name' => 'obj', 'type' => 'Object', 'example' => { 'foo' => 'bar' }, 'required' => false }
|
36
|
+
]
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|