grape-swagger 1.0.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +94 -1
- data/.rubocop_todo.yml +1 -1
- data/.travis.yml +14 -8
- data/CHANGELOG.md +56 -6
- data/Gemfile +9 -4
- data/README.md +191 -12
- data/UPGRADING.md +34 -0
- data/grape-swagger.gemspec +1 -1
- data/lib/grape-swagger.rb +7 -4
- data/lib/grape-swagger/doc_methods.rb +65 -62
- data/lib/grape-swagger/doc_methods/build_model_definition.rb +53 -2
- data/lib/grape-swagger/doc_methods/data_type.rb +5 -5
- data/lib/grape-swagger/doc_methods/format_data.rb +2 -2
- data/lib/grape-swagger/doc_methods/operation_id.rb +2 -2
- data/lib/grape-swagger/doc_methods/parse_params.rb +19 -4
- data/lib/grape-swagger/endpoint.rb +73 -31
- data/lib/grape-swagger/rake/oapi_tasks.rb +12 -2
- data/lib/grape-swagger/version.rb +1 -1
- 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 +56 -0
- data/spec/issues/784_extensions_on_params_spec.rb +38 -0
- data/spec/issues/809_utf8_routes_spec.rb +55 -0
- data/spec/lib/data_type_spec.rb +12 -0
- data/spec/lib/move_params_spec.rb +2 -2
- data/spec/lib/oapi_tasks_spec.rb +15 -5
- data/spec/support/empty_model_parser.rb +1 -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 +8 -8
- data/spec/support/model_parsers/representable_parser.rb +8 -8
- data/spec/support/namespace_tags.rb +1 -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_spec.rb +2 -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 +1 -0
- data/spec/swagger_v2/float_api_spec.rb +1 -0
- data/spec/swagger_v2/inheritance_and_discriminator_spec.rb +56 -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/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 +1 -0
- metadata +19 -9
@@ -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
|
}
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -0,0 +1,56 @@
|
|
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
|
+
class NameApi < Grape::API
|
37
|
+
add_swagger_documentation models: [Entities::Pet, Entities::Cat]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'Parent model' do
|
43
|
+
let(:app) { InheritanceTest::NameApi }
|
44
|
+
|
45
|
+
subject do
|
46
|
+
get '/swagger_doc'
|
47
|
+
JSON.parse(last_response.body)['definitions']
|
48
|
+
end
|
49
|
+
|
50
|
+
specify do
|
51
|
+
subject['InheritanceTest_Entities_Pet'].key?('discriminator')
|
52
|
+
subject['InheritanceTest_Entities_Pet']['discriminator'] = 'type'
|
53
|
+
subject['InheritanceTest_Entities_Cat'].key?('allOf')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
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
|
@@ -22,6 +22,20 @@ describe 'referenceEntity' do
|
|
22
22
|
expose :title, documentation: { type: 'string', desc: 'Title of the kind.' }
|
23
23
|
expose :something, documentation: { type: Something, desc: 'Something interesting.' }
|
24
24
|
end
|
25
|
+
|
26
|
+
class Base < Grape::Entity
|
27
|
+
def self.entity_name
|
28
|
+
parts = to_s.split('::')
|
29
|
+
|
30
|
+
"MyAPI::#{parts.last}"
|
31
|
+
end
|
32
|
+
|
33
|
+
expose :title, documentation: { type: 'string', desc: 'Title of the parent.' }
|
34
|
+
end
|
35
|
+
|
36
|
+
class Child < Base
|
37
|
+
expose :child, documentation: { type: 'string', desc: 'Child property.' }
|
38
|
+
end
|
25
39
|
end
|
26
40
|
|
27
41
|
class ResponseModelApi < Grape::API
|
@@ -40,6 +54,16 @@ describe 'referenceEntity' do
|
|
40
54
|
present kind, with: Entities::Kind
|
41
55
|
end
|
42
56
|
|
57
|
+
desc 'This returns a child entity',
|
58
|
+
entity: Entities::Child,
|
59
|
+
http_codes: [
|
60
|
+
{ code: 200, message: 'OK', model: Entities::Child }
|
61
|
+
]
|
62
|
+
get '/child' do
|
63
|
+
child = OpenStruct.new text: 'child'
|
64
|
+
present child, with: Entities::Child
|
65
|
+
end
|
66
|
+
|
43
67
|
add_swagger_documentation # models: [MyAPI::Entities::Something, MyAPI::Entities::Kind]
|
44
68
|
end
|
45
69
|
end
|
@@ -49,36 +73,57 @@ describe 'referenceEntity' do
|
|
49
73
|
MyAPI::ResponseModelApi
|
50
74
|
end
|
51
75
|
|
52
|
-
|
53
|
-
|
54
|
-
|
76
|
+
describe 'kind' do
|
77
|
+
subject do
|
78
|
+
get '/swagger_doc/kind'
|
79
|
+
JSON.parse(last_response.body)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should document specified models' do
|
83
|
+
expect(subject['paths']['/kind']['get']['parameters']).to eq [{
|
84
|
+
'in' => 'query',
|
85
|
+
'name' => 'something',
|
86
|
+
'description' => 'Something interesting.',
|
87
|
+
'type' => 'SomethingCustom',
|
88
|
+
'required' => false
|
89
|
+
}]
|
90
|
+
|
91
|
+
expect(subject['definitions'].keys).to include 'SomethingCustom'
|
92
|
+
expect(subject['definitions']['SomethingCustom']).to eq(
|
93
|
+
'type' => 'object', 'properties' => { 'text' => { 'type' => 'string', 'description' => 'Content of something.' } }
|
94
|
+
)
|
95
|
+
|
96
|
+
expect(subject['definitions'].keys).to include 'KindCustom'
|
97
|
+
expect(subject['definitions']['KindCustom']).to eq(
|
98
|
+
'type' => 'object',
|
99
|
+
'properties' => {
|
100
|
+
'title' => { 'type' => 'string', 'description' => 'Title of the kind.' },
|
101
|
+
'something' => {
|
102
|
+
'$ref' => '#/definitions/SomethingCustom',
|
103
|
+
'description' => 'Something interesting.'
|
104
|
+
}
|
105
|
+
},
|
106
|
+
'description' => 'KindCustom model'
|
107
|
+
)
|
108
|
+
end
|
55
109
|
end
|
56
110
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
'properties' => {
|
75
|
-
'title' => { 'type' => 'string', 'description' => 'Title of the kind.' },
|
76
|
-
'something' => {
|
77
|
-
'$ref' => '#/definitions/SomethingCustom',
|
78
|
-
'description' => 'Something interesting.'
|
79
|
-
}
|
80
|
-
},
|
81
|
-
'description' => 'This returns kind and something or an error'
|
82
|
-
)
|
111
|
+
describe 'child' do
|
112
|
+
subject do
|
113
|
+
get '/swagger_doc/child'
|
114
|
+
JSON.parse(last_response.body)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should document specified models' do
|
118
|
+
expect(subject['definitions'].keys).to include 'MyAPI::Child'
|
119
|
+
expect(subject['definitions']['MyAPI::Child']).to eq(
|
120
|
+
'type' => 'object',
|
121
|
+
'properties' => {
|
122
|
+
'title' => { 'type' => 'string', 'description' => 'Title of the parent.' },
|
123
|
+
'child' => { 'type' => 'string', 'description' => 'Child property.' }
|
124
|
+
},
|
125
|
+
'description' => 'MyAPI::Child model'
|
126
|
+
)
|
127
|
+
end
|
83
128
|
end
|
84
129
|
end
|