grape-swagger 0.8.0 → 0.9.0
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/.rubocop.yml +2 -33
- data/.rubocop_todo.yml +55 -0
- data/.travis.yml +12 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile +8 -1
- data/README.md +10 -8
- data/{test → example}/api.rb +4 -0
- data/{test → example}/config.ru +0 -0
- data/{test → example}/splines.png +0 -0
- data/grape-swagger.gemspec +2 -2
- data/lib/grape-swagger.rb +211 -193
- data/lib/grape-swagger/version.rb +1 -1
- data/spec/api_global_models_spec.rb +10 -7
- data/spec/api_models_spec.rb +45 -17
- data/spec/api_paths_spec.rb +67 -0
- data/spec/api_root_spec.rb +31 -0
- data/spec/boolean_params_spec.rb +30 -0
- data/spec/form_params_spec.rb +7 -43
- data/spec/grape-swagger_helper_spec.rb +1 -23
- data/spec/group_params_spec.rb +31 -0
- data/spec/hash_params_spec.rb +30 -0
- data/spec/hide_api_spec.rb +3 -3
- data/spec/non_default_api_spec.rb +25 -22
- data/spec/response_model_spec.rb +42 -11
- data/spec/simple_mounted_api_spec.rb +3 -3
- data/spec/spec_helper.rb +1 -0
- metadata +20 -12
@@ -7,10 +7,12 @@ describe 'Global Models' do
|
|
7
7
|
module Some
|
8
8
|
class Thing < Grape::Entity
|
9
9
|
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
|
10
|
+
expose :name, documentation: { type: String, desc: 'Name of something.' }
|
10
11
|
end
|
11
12
|
|
12
13
|
class CombinedThing < Grape::Entity
|
13
14
|
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
|
15
|
+
expose :created_at, documentation: { type: DateTime, desc: 'Creation of something.' }
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
@@ -18,15 +20,13 @@ describe 'Global Models' do
|
|
18
20
|
|
19
21
|
subject do
|
20
22
|
Class.new(Grape::API) do
|
21
|
-
desc 'This gets thing.'
|
23
|
+
desc 'This gets thing.'
|
22
24
|
get '/thing' do
|
23
25
|
thing = OpenStruct.new text: 'thing'
|
24
26
|
present thing, with: Entities::Some::Thing
|
25
27
|
end
|
26
28
|
|
27
|
-
desc 'This gets combined thing.',
|
28
|
-
params: Entities::Some::CombinedThing.documentation,
|
29
|
-
entity: Entities::Some::CombinedThing
|
29
|
+
desc 'This gets combined thing.', entity: Entities::Some::CombinedThing
|
30
30
|
get '/combined_thing' do
|
31
31
|
thing = OpenStruct.new text: 'thing'
|
32
32
|
present thing, with: Entities::Some::CombinedThing
|
@@ -47,7 +47,8 @@ describe 'Global Models' do
|
|
47
47
|
'Some::Thing' => {
|
48
48
|
'id' => 'Some::Thing',
|
49
49
|
'properties' => {
|
50
|
-
'text' => { 'type' => 'string', 'description' => 'Content of something.' }
|
50
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' },
|
51
|
+
'name' => { 'type' => 'string', 'description' => 'Name of something.' }
|
51
52
|
}
|
52
53
|
})
|
53
54
|
end
|
@@ -60,7 +61,8 @@ describe 'Global Models' do
|
|
60
61
|
'Some::Thing' => {
|
61
62
|
'id' => 'Some::Thing',
|
62
63
|
'properties' => {
|
63
|
-
'text' => { 'type' => 'string', 'description' => 'Content of something.' }
|
64
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' },
|
65
|
+
'name' => { 'type' => 'string', 'description' => 'Name of something.' }
|
64
66
|
}
|
65
67
|
})
|
66
68
|
|
@@ -68,7 +70,8 @@ describe 'Global Models' do
|
|
68
70
|
'Some::CombinedThing' => {
|
69
71
|
'id' => 'Some::CombinedThing',
|
70
72
|
'properties' => {
|
71
|
-
'text' => { 'type' => 'string', 'description' => 'Content of something.' }
|
73
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' },
|
74
|
+
'created_at' => { 'type' => 'dateTime', 'description' => 'Creation of something.' }
|
72
75
|
}
|
73
76
|
})
|
74
77
|
|
data/spec/api_models_spec.rb
CHANGED
@@ -6,6 +6,7 @@ describe 'API Models' do
|
|
6
6
|
module Entities
|
7
7
|
class Something < Grape::Entity
|
8
8
|
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
|
9
|
+
expose :links, documentation: { type: 'link', is_array: true }
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -51,6 +52,24 @@ describe 'API Models' do
|
|
51
52
|
expose :something, as: :post, using: Entities::Something, documentation: { type: 'Something', desc: 'Reference to something.' }
|
52
53
|
end
|
53
54
|
end
|
55
|
+
|
56
|
+
module Entities
|
57
|
+
class FourthLevel < Grape::Entity
|
58
|
+
expose :text, documentation: { type: 'string' }
|
59
|
+
end
|
60
|
+
|
61
|
+
class ThirdLevel < Grape::Entity
|
62
|
+
expose :parts, using: Entities::FourthLevel, documentation: { type: 'FourthLevel' }
|
63
|
+
end
|
64
|
+
|
65
|
+
class SecondLevel < Grape::Entity
|
66
|
+
expose :parts, using: Entities::ThirdLevel, documentation: { type: 'ThirdLevel' }
|
67
|
+
end
|
68
|
+
|
69
|
+
class FirstLevel < Grape::Entity
|
70
|
+
expose :parts, using: Entities::SecondLevel, documentation: { type: 'SecondLevel' }
|
71
|
+
end
|
72
|
+
end
|
54
73
|
end
|
55
74
|
|
56
75
|
def app
|
@@ -91,6 +110,16 @@ describe 'API Models' do
|
|
91
110
|
present something, with: Entities::AliasedThing
|
92
111
|
end
|
93
112
|
|
113
|
+
desc 'This gets all nested entities.', entity: Entities::FirstLevel
|
114
|
+
get '/nesting' do
|
115
|
+
fourth_level = OpenStruct.new text: 'something'
|
116
|
+
third_level = OpenStruct.new parts: [fourth_level]
|
117
|
+
second_level = OpenStruct.new parts: [third_level]
|
118
|
+
first_level = OpenStruct.new parts: [second_level]
|
119
|
+
|
120
|
+
present first_level, with: Entities::FirstLevel
|
121
|
+
end
|
122
|
+
|
94
123
|
add_swagger_documentation
|
95
124
|
end
|
96
125
|
end
|
@@ -117,37 +146,28 @@ describe 'API Models' do
|
|
117
146
|
{ 'path' => '/somethingelse.{format}', 'description' => 'Operations about somethingelses' },
|
118
147
|
{ 'path' => '/enum_description_in_entity.{format}', 'description' => 'Operations about enum_description_in_entities' },
|
119
148
|
{ 'path' => '/aliasedthing.{format}', 'description' => 'Operations about aliasedthings' },
|
149
|
+
{ 'path' => '/nesting.{format}', 'description' => 'Operations about nestings' },
|
120
150
|
{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
|
121
151
|
]
|
122
152
|
end
|
123
153
|
end
|
124
154
|
|
125
155
|
it 'returns type' do
|
126
|
-
get '/swagger_doc/something
|
156
|
+
get '/swagger_doc/something'
|
127
157
|
result = JSON.parse(last_response.body)
|
128
158
|
expect(result['apis'].first['operations'].first['type']).to eq 'Something'
|
129
159
|
end
|
130
160
|
|
131
161
|
it 'includes nested type' do
|
132
|
-
get '/swagger_doc/thing
|
162
|
+
get '/swagger_doc/thing'
|
133
163
|
result = JSON.parse(last_response.body)
|
134
164
|
expect(result['apis'].first['operations'].first['type']).to eq 'Some::Thing'
|
135
165
|
end
|
136
166
|
|
137
167
|
it 'includes entities which are only used as composition' do
|
138
|
-
get '/swagger_doc/somethingelse
|
168
|
+
get '/swagger_doc/somethingelse'
|
139
169
|
result = JSON.parse(last_response.body)
|
140
|
-
expect(result['apis']).to
|
141
|
-
'path' => '/somethingelse.{format}',
|
142
|
-
'operations' => [{
|
143
|
-
'notes' => '',
|
144
|
-
'type' => 'SomeThingElse',
|
145
|
-
'summary' => 'This gets somthing else.',
|
146
|
-
'nickname' => 'GET-somethingelse---format-',
|
147
|
-
'method' => 'GET',
|
148
|
-
'parameters' => []
|
149
|
-
}]
|
150
|
-
}])
|
170
|
+
expect(result['apis'][0]['path']).to start_with '/somethingelse'
|
151
171
|
|
152
172
|
expect(result['models']['SomeThingElse']).to include('id' => 'SomeThingElse',
|
153
173
|
'properties' => {
|
@@ -188,7 +208,7 @@ describe 'API Models' do
|
|
188
208
|
end
|
189
209
|
|
190
210
|
it 'includes enum values in params and documentation.' do
|
191
|
-
get '/swagger_doc/enum_description_in_entity
|
211
|
+
get '/swagger_doc/enum_description_in_entity'
|
192
212
|
result = JSON.parse(last_response.body)
|
193
213
|
expect(result['models']['EnumValues']).to eq(
|
194
214
|
'id' => 'EnumValues',
|
@@ -210,7 +230,7 @@ describe 'API Models' do
|
|
210
230
|
end
|
211
231
|
|
212
232
|
it 'includes referenced models in those with aliased references.' do
|
213
|
-
get '/swagger_doc/aliasedthing
|
233
|
+
get '/swagger_doc/aliasedthing'
|
214
234
|
result = JSON.parse(last_response.body)
|
215
235
|
expect(result['models']['AliasedThing']).to eq(
|
216
236
|
'id' => 'AliasedThing',
|
@@ -222,8 +242,16 @@ describe 'API Models' do
|
|
222
242
|
expect(result['models']['Something']).to eq(
|
223
243
|
'id' => 'Something',
|
224
244
|
'properties' => {
|
225
|
-
'text' => { 'type' => 'string', 'description' => 'Content of something.' }
|
245
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' },
|
246
|
+
'links' => { 'type' => 'array', 'items' => { '$ref' => 'link' } }
|
226
247
|
}
|
227
248
|
)
|
228
249
|
end
|
250
|
+
|
251
|
+
it 'includes all entities with four levels of nesting' do
|
252
|
+
get '/swagger_doc/nesting'
|
253
|
+
result = JSON.parse(last_response.body)
|
254
|
+
|
255
|
+
expect(result['models']).to include('FirstLevel', 'SecondLevel', 'ThirdLevel', 'FourthLevel')
|
256
|
+
end
|
229
257
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'simple api with prefix' do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
class ApiWithPrefix < Grape::API
|
7
|
+
prefix :api
|
8
|
+
|
9
|
+
desc 'This gets apitest'
|
10
|
+
get '/apitest' do
|
11
|
+
{ test: 'something' }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class SimpleApiWithPrefix < Grape::API
|
16
|
+
mount ApiWithPrefix
|
17
|
+
add_swagger_documentation
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def app
|
23
|
+
SimpleApiWithPrefix
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should not raise TypeError exception' do
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'retrieves swagger-documentation on /swagger_doc that contains apitest' do
|
30
|
+
get '/swagger_doc.json'
|
31
|
+
expect(JSON.parse(last_response.body)).to eq(
|
32
|
+
'apiVersion' => '0.1',
|
33
|
+
'swaggerVersion' => '1.2',
|
34
|
+
'info' => {},
|
35
|
+
'produces' => Grape::ContentTypes::CONTENT_TYPES.values.uniq,
|
36
|
+
'apis' => [
|
37
|
+
{ 'path' => '/apitest.{format}', 'description' => 'Operations about apitests' },
|
38
|
+
{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
|
39
|
+
]
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'retrieves the documentation for apitest that' do
|
44
|
+
it 'contains returns something in URL' do
|
45
|
+
get '/swagger_doc/apitest.json'
|
46
|
+
expect(JSON.parse(last_response.body)).to eq(
|
47
|
+
'apiVersion' => '0.1',
|
48
|
+
'swaggerVersion' => '1.2',
|
49
|
+
'basePath' => 'http://example.org',
|
50
|
+
'resourcePath' => '/apitest',
|
51
|
+
'produces' => Grape::ContentTypes::CONTENT_TYPES.values.uniq,
|
52
|
+
'apis' => [{
|
53
|
+
'path' => '/api/apitest.{format}',
|
54
|
+
'operations' => [{
|
55
|
+
'notes' => '',
|
56
|
+
'summary' => 'This gets apitest',
|
57
|
+
'nickname' => 'GET-api-apitest---format-',
|
58
|
+
'method' => 'GET',
|
59
|
+
'parameters' => [],
|
60
|
+
'type' => 'void'
|
61
|
+
}]
|
62
|
+
}]
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'simple root api' do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
class ApiRoot < Grape::API
|
7
|
+
format :json
|
8
|
+
prefix 'api'
|
9
|
+
version 'v2', using: :header, vendor: 'artsy', strict: false
|
10
|
+
get do
|
11
|
+
{}
|
12
|
+
end
|
13
|
+
add_swagger_documentation
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def app
|
18
|
+
ApiRoot
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'retrieves swagger-documentation on /swagger_doc' do
|
22
|
+
get '/api/swagger_doc'
|
23
|
+
expect(JSON.parse(last_response.body)).to eq(
|
24
|
+
'apiVersion' => '0.1',
|
25
|
+
'swaggerVersion' => '1.2',
|
26
|
+
'info' => {},
|
27
|
+
'produces' => ['application/json'],
|
28
|
+
'apis' => [{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }]
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Boolean Params' do
|
4
|
+
def app
|
5
|
+
Class.new(Grape::API) do
|
6
|
+
format :json
|
7
|
+
|
8
|
+
params do
|
9
|
+
requires :a_boolean, type: Virtus::Attribute::Boolean
|
10
|
+
end
|
11
|
+
post :splines do
|
12
|
+
end
|
13
|
+
|
14
|
+
add_swagger_documentation
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
subject do
|
19
|
+
get '/swagger_doc/splines'
|
20
|
+
expect(last_response.status).to eq 200
|
21
|
+
body = JSON.parse last_response.body
|
22
|
+
body['apis'].first['operations'].first['parameters']
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'converts boolean types' do
|
26
|
+
expect(subject).to eq [
|
27
|
+
{ 'paramType' => 'form', 'name' => 'a_boolean', 'description' => nil, 'type' => 'boolean', 'required' => true, 'allowMultiple' => false }
|
28
|
+
]
|
29
|
+
end
|
30
|
+
end
|
data/spec/form_params_spec.rb
CHANGED
@@ -35,52 +35,16 @@ describe 'Form Params' do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
subject do
|
38
|
-
get '/swagger_doc/items
|
38
|
+
get '/swagger_doc/items'
|
39
39
|
JSON.parse(last_response.body)
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'retrieves the documentation form params' do
|
43
|
-
expect(subject['apis']).to eq
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
'summary' => '',
|
50
|
-
'nickname' => 'POST-items---format-',
|
51
|
-
'method' => 'POST',
|
52
|
-
'parameters' => [{ 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false }],
|
53
|
-
'type' => 'void'
|
54
|
-
}
|
55
|
-
]
|
56
|
-
}, {
|
57
|
-
'path' => '/items/{id}.{format}',
|
58
|
-
'operations' => [
|
59
|
-
{
|
60
|
-
'notes' => '',
|
61
|
-
'summary' => '',
|
62
|
-
'nickname' => 'PUT-items--id---format-',
|
63
|
-
'method' => 'PUT',
|
64
|
-
'parameters' => [
|
65
|
-
{ 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' },
|
66
|
-
{ 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false },
|
67
|
-
{ 'paramType' => 'form', 'name' => 'conditions', 'description' => 'conditions of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32', 'enum' => [1, 2, 3] }
|
68
|
-
],
|
69
|
-
'type' => 'void'
|
70
|
-
},
|
71
|
-
{
|
72
|
-
'notes' => '',
|
73
|
-
'summary' => '',
|
74
|
-
'nickname' => 'PATCH-items--id---format-',
|
75
|
-
'method' => 'PATCH',
|
76
|
-
'parameters' => [
|
77
|
-
{ 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' },
|
78
|
-
{ 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false },
|
79
|
-
{ 'paramType' => 'form', 'name' => 'conditions', 'description' => 'conditions of item', 'type' => 'string', 'required' => false, 'allowMultiple' => false, 'enum' => %w(1 2) }
|
80
|
-
],
|
81
|
-
'type' => 'void'
|
82
|
-
}
|
83
|
-
]
|
84
|
-
}])
|
43
|
+
expect(subject['apis'].count).to eq 2
|
44
|
+
expect(subject['apis'][0]['path']).to start_with '/items'
|
45
|
+
expect(subject['apis'][0]['operations'][0]['method']).to eq 'POST'
|
46
|
+
expect(subject['apis'][1]['path']).to start_with '/items/{id}'
|
47
|
+
expect(subject['apis'][1]['operations'][0]['method']).to eq 'PUT'
|
48
|
+
expect(subject['apis'][1]['operations'][1]['method']).to eq 'PATCH'
|
85
49
|
end
|
86
50
|
end
|
@@ -4,19 +4,11 @@ describe 'helpers' do
|
|
4
4
|
|
5
5
|
before :all do
|
6
6
|
class HelperTestAPI < Grape::API
|
7
|
-
add_swagger_documentation
|
8
7
|
end
|
9
8
|
end
|
10
9
|
|
11
10
|
subject do
|
12
|
-
|
13
|
-
|
14
|
-
# after injecting grape-swagger into the Test API we get the helper methods
|
15
|
-
# back from the first endpoint's class (the API mounted by grape-swagger
|
16
|
-
# to serve the swagger_doc
|
17
|
-
|
18
|
-
api.extend HelperTestAPI.endpoints.first.options[:app].helpers
|
19
|
-
api
|
11
|
+
HelperTestAPI.add_swagger_documentation
|
20
12
|
end
|
21
13
|
|
22
14
|
context 'parsing parameters' do
|
@@ -53,12 +45,6 @@ describe 'helpers' do
|
|
53
45
|
desc: 'rack file',
|
54
46
|
datafile: 'content',
|
55
47
|
required: true
|
56
|
-
},
|
57
|
-
rails: {
|
58
|
-
type: 'Hash',
|
59
|
-
desc: 'rails file',
|
60
|
-
datafile: 'content',
|
61
|
-
required: true
|
62
48
|
}
|
63
49
|
}
|
64
50
|
path = '/coolness'
|
@@ -71,14 +57,6 @@ describe 'helpers' do
|
|
71
57
|
type: 'File',
|
72
58
|
required: true,
|
73
59
|
allowMultiple: false
|
74
|
-
},
|
75
|
-
{
|
76
|
-
paramType: 'body',
|
77
|
-
name: :rails,
|
78
|
-
description: 'rails file',
|
79
|
-
type: 'File',
|
80
|
-
required: true,
|
81
|
-
allowMultiple: false
|
82
60
|
}
|
83
61
|
]
|
84
62
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Group Params' do
|
4
|
+
def app
|
5
|
+
Class.new(Grape::API) do
|
6
|
+
format :json
|
7
|
+
|
8
|
+
params do
|
9
|
+
requires :required_group, type: Hash do
|
10
|
+
requires :required_param_1
|
11
|
+
requires :required_param_2
|
12
|
+
end
|
13
|
+
end
|
14
|
+
post '/groups' do
|
15
|
+
{}
|
16
|
+
end
|
17
|
+
|
18
|
+
add_swagger_documentation
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'retrieves the documentation for group parameters' do
|
23
|
+
get '/swagger_doc/groups'
|
24
|
+
|
25
|
+
body = JSON.parse last_response.body
|
26
|
+
parameters = body['apis'].first['operations'].first['parameters']
|
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 }]
|
30
|
+
end
|
31
|
+
end
|