grape-swagger 0.10.0 → 0.10.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.
@@ -43,13 +43,13 @@ describe 'Global Models' do
43
43
  get '/swagger_doc/thing.json'
44
44
  json = JSON.parse(last_response.body)
45
45
  expect(json['models']).to eq(
46
- 'Some::Thing' => {
47
- 'id' => 'Some::Thing',
48
- 'properties' => {
49
- 'text' => { 'type' => 'string', 'description' => 'Content of something.' },
50
- 'name' => { 'type' => 'string', 'description' => 'Name of something.' }
51
- }
52
- })
46
+ 'Some::Thing' => {
47
+ 'id' => 'Some::Thing',
48
+ 'properties' => {
49
+ 'text' => { 'type' => 'string', 'description' => 'Content of something.' },
50
+ 'name' => { 'type' => 'string', 'description' => 'Name of something.' }
51
+ }
52
+ })
53
53
  end
54
54
 
55
55
  it 'uses global models and route endpoint specific entities together' do
@@ -57,21 +57,21 @@ describe 'Global Models' do
57
57
  json = JSON.parse(last_response.body)
58
58
 
59
59
  expect(json['models']).to include(
60
- 'Some::Thing' => {
61
- 'id' => 'Some::Thing',
62
- 'properties' => {
63
- 'text' => { 'type' => 'string', 'description' => 'Content of something.' },
64
- 'name' => { 'type' => 'string', 'description' => 'Name of something.' }
65
- }
66
- })
60
+ 'Some::Thing' => {
61
+ 'id' => 'Some::Thing',
62
+ 'properties' => {
63
+ 'text' => { 'type' => 'string', 'description' => 'Content of something.' },
64
+ 'name' => { 'type' => 'string', 'description' => 'Name of something.' }
65
+ }
66
+ })
67
67
 
68
68
  expect(json['models']).to include(
69
- 'Some::CombinedThing' => {
70
- 'id' => 'Some::CombinedThing',
71
- 'properties' => {
72
- 'text' => { 'type' => 'string', 'description' => 'Content of something.' },
73
- 'created_at' => { 'type' => 'dateTime', 'description' => 'Creation of something.' }
74
- }
75
- })
69
+ 'Some::CombinedThing' => {
70
+ 'id' => 'Some::CombinedThing',
71
+ 'properties' => {
72
+ 'text' => { 'type' => 'string', 'description' => 'Content of something.' },
73
+ 'created_at' => { 'type' => 'string', 'format' => 'date-time', 'description' => 'Creation of something.' }
74
+ }
75
+ })
76
76
  end
77
77
  end
@@ -94,6 +94,13 @@ describe 'API Models' do
94
94
  end
95
95
  end
96
96
 
97
+ module Entities
98
+ class ThingWithRoot < Grape::Entity
99
+ root 'things', 'thing'
100
+ expose :text, documentation: { type: 'string', desc: 'Content of something.' }
101
+ end
102
+ end
103
+
97
104
  def app
98
105
  Class.new(Grape::API) do
99
106
  format :json
@@ -149,6 +156,12 @@ describe 'API Models' do
149
156
  present result, with: Entities::QueryResult
150
157
  end
151
158
 
159
+ desc 'This gets thing_with_root.', entity: Entities::ThingWithRoot
160
+ get '/thing_with_root' do
161
+ thing = OpenStruct.new text: 'thing'
162
+ present thing, with: Entities::ThingWithRoot
163
+ end
164
+
152
165
  add_swagger_documentation
153
166
  end
154
167
  end
@@ -177,6 +190,7 @@ describe 'API Models' do
177
190
  { 'path' => '/aliasedthing.{format}', 'description' => 'Operations about aliasedthings' },
178
191
  { 'path' => '/nesting.{format}', 'description' => 'Operations about nestings' },
179
192
  { 'path' => '/multiple_entities.{format}', 'description' => 'Operations about multiple_entities' },
193
+ { 'path' => '/thing_with_root.{format}', 'description' => 'Operations about thing_with_roots' },
180
194
  { 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
181
195
  ]
182
196
  end
@@ -213,68 +227,68 @@ describe 'API Models' do
213
227
  },
214
228
  'required' => ['parts']
215
229
 
216
- )
230
+ )
217
231
 
218
232
  expect(result['models']['ComposedOf']).to include(
219
- 'id' => 'ComposedOf',
220
- 'properties' => {
221
- 'part_text' => {
222
- 'type' => 'string',
223
- 'description' => 'Content of composedof.'
224
- }
225
- }
226
- )
233
+ 'id' => 'ComposedOf',
234
+ 'properties' => {
235
+ 'part_text' => {
236
+ 'type' => 'string',
237
+ 'description' => 'Content of composedof.'
238
+ }
239
+ }
240
+ )
227
241
 
228
242
  expect(result['models']['composed']).to include(
229
- 'id' => 'composed',
230
- 'properties' => {
231
- 'part_text' => {
232
- 'type' => 'string',
233
- 'description' => 'Content of composedof else.'
234
- }
235
-
236
- }
237
- )
243
+ 'id' => 'composed',
244
+ 'properties' => {
245
+ 'part_text' => {
246
+ 'type' => 'string',
247
+ 'description' => 'Content of composedof else.'
248
+ }
249
+
250
+ }
251
+ )
238
252
  end
239
253
 
240
254
  it 'includes enum values in params and documentation.' do
241
255
  get '/swagger_doc/enum_description_in_entity'
242
256
  result = JSON.parse(last_response.body)
243
257
  expect(result['models']['EnumValues']).to eq(
244
- 'id' => 'EnumValues',
245
- 'properties' => {
246
- 'gender' => { 'type' => 'string', 'description' => 'Content of something.', 'enum' => %w(Male Female) },
247
- 'number' => { 'type' => 'integer', 'description' => 'Content of something.', 'enum' => [1, 2] }
248
- }
249
- )
258
+ 'id' => 'EnumValues',
259
+ 'properties' => {
260
+ 'gender' => { 'type' => 'string', 'description' => 'Content of something.', 'enum' => %w(Male Female) },
261
+ 'number' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'Content of something.', 'enum' => [1, 2] }
262
+ }
263
+ )
250
264
 
251
265
  expect(result['apis'][0]['operations'][0]).to include(
252
- 'parameters' =>
253
- [
254
- { 'paramType' => 'query', 'name' => 'gender', 'description' => 'Content of something.', 'type' => 'string', 'required' => false, 'allowMultiple' => false, 'enum' => %w(Male Female) },
255
- { 'paramType' => 'query', 'name' => 'number', 'description' => 'Content of something.', 'type' => 'integer', 'required' => false, 'allowMultiple' => false, 'format' => 'int32', 'enum' => [1, 2] }
256
- ],
257
- 'type' => 'EnumValues'
258
- )
266
+ 'parameters' =>
267
+ [
268
+ { 'paramType' => 'query', 'name' => 'gender', 'description' => 'Content of something.', 'type' => 'string', 'required' => false, 'allowMultiple' => false, 'enum' => %w(Male Female) },
269
+ { 'paramType' => 'query', 'name' => 'number', 'description' => 'Content of something.', 'type' => 'integer', 'required' => false, 'allowMultiple' => false, 'format' => 'int32', 'enum' => [1, 2] }
270
+ ],
271
+ 'type' => 'EnumValues'
272
+ )
259
273
  end
260
274
 
261
275
  it 'includes referenced models in those with aliased references.' do
262
276
  get '/swagger_doc/aliasedthing'
263
277
  result = JSON.parse(last_response.body)
264
278
  expect(result['models']['AliasedThing']).to eq(
265
- 'id' => 'AliasedThing',
266
- 'properties' => {
267
- 'post' => { '$ref' => 'Something', 'description' => 'Reference to something.' }
268
- }
269
- )
279
+ 'id' => 'AliasedThing',
280
+ 'properties' => {
281
+ 'post' => { '$ref' => 'Something', 'description' => 'Reference to something.' }
282
+ }
283
+ )
270
284
 
271
285
  expect(result['models']['Something']).to eq(
272
- 'id' => 'Something',
273
- 'properties' => {
274
- 'text' => { 'type' => 'string', 'description' => 'Content of something.' },
275
- 'links' => { 'type' => 'array', 'items' => { '$ref' => 'link' } }
276
- }
277
- )
286
+ 'id' => 'Something',
287
+ 'properties' => {
288
+ 'text' => { 'type' => 'string', 'description' => 'Content of something.' },
289
+ 'links' => { 'type' => 'array', 'items' => { '$ref' => 'link' } }
290
+ }
291
+ )
278
292
  end
279
293
 
280
294
  it 'includes all entities with four levels of nesting' do
@@ -290,4 +304,10 @@ describe 'API Models' do
290
304
 
291
305
  expect(result['models']).to include('QueryInput', 'QueryInputElement', 'QueryResult')
292
306
  end
307
+
308
+ it 'includes an id equal to the model name' do
309
+ get '/swagger_doc/thing_with_root'
310
+ result = JSON.parse(last_response.body)
311
+ expect(result['models']['thing']['id']).to eq('thing')
312
+ end
293
313
  end
@@ -62,3 +62,67 @@ describe 'simple api with prefix' do
62
62
  end
63
63
  end
64
64
  end
65
+
66
+ describe 'simple api with partially same path as docs mount and hidden doc path' do
67
+ before :all do
68
+ class SamePathApi < Grape::API
69
+ desc 'This gets the documents'
70
+ get '/documents' do
71
+ { test: 'something' }
72
+ end
73
+
74
+ desc 'This gets the doc types'
75
+ get '/doc-types' do
76
+ { test: 'something' }
77
+ end
78
+ end
79
+
80
+ class SimpleSamePathApi < Grape::API
81
+ mount SamePathApi
82
+ add_swagger_documentation(
83
+ mount_path: '/doc',
84
+ hide_documentation_path: true
85
+ )
86
+ end
87
+ end
88
+
89
+ def app
90
+ SimpleSamePathApi
91
+ end
92
+
93
+ it 'retrieves swagger-documentation on /doc that contains documents' do
94
+ get '/doc.json'
95
+ expect(JSON.parse(last_response.body)).to eq(
96
+ 'apiVersion' => '0.1',
97
+ 'swaggerVersion' => '1.2',
98
+ 'info' => {},
99
+ 'produces' => Grape::ContentTypes::CONTENT_TYPES.values.uniq,
100
+ 'apis' => [
101
+ { 'path' => '/documents.{format}', 'description' => 'Operations about documents' },
102
+ { 'path' => '/doc-types.{format}', 'description' => 'Operations about doc-types' }
103
+ ]
104
+ )
105
+ end
106
+
107
+ it 'retrieves the documentation for apis' do
108
+ get '/doc/documents.json'
109
+ expect(JSON.parse(last_response.body)).to eq(
110
+ 'apiVersion' => '0.1',
111
+ 'swaggerVersion' => '1.2',
112
+ 'basePath' => 'http://example.org',
113
+ 'resourcePath' => '/documents',
114
+ 'produces' => Grape::ContentTypes::CONTENT_TYPES.values.uniq,
115
+ 'apis' => [{
116
+ 'path' => '/documents.{format}',
117
+ 'operations' => [{
118
+ 'notes' => '',
119
+ 'summary' => 'This gets the documents',
120
+ 'nickname' => 'GET-documents---format-',
121
+ 'method' => 'GET',
122
+ 'parameters' => [],
123
+ 'type' => 'void'
124
+ }]
125
+ }]
126
+ )
127
+ end
128
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'API with minimally documented models' do
4
+ def app
5
+ entity_klass = Class.new do
6
+ def self.exposures
7
+ {}
8
+ end
9
+
10
+ def self.documentation
11
+ {
12
+ bar: { type: String },
13
+ foo: {}
14
+ }
15
+ end
16
+
17
+ def self.entity_name
18
+ 'Foo'
19
+ end
20
+ end
21
+
22
+ Class.new(Grape::API) do
23
+ format :json
24
+
25
+ get :foo do
26
+ end
27
+
28
+ add_swagger_documentation \
29
+ format: :json,
30
+ models: [Class.new(entity_klass)]
31
+ end
32
+ end
33
+
34
+ subject do
35
+ get '/swagger_doc/foo'
36
+ JSON.parse(last_response.body)['models']
37
+ end
38
+
39
+ it 'returns model' do
40
+ expect(subject).to eq(
41
+ 'Foo' => {
42
+ 'id' => 'Foo',
43
+ 'properties' => {
44
+ 'bar' => { 'type' => 'string' },
45
+ 'foo' => { '$ref' => nil }
46
+ }
47
+ }
48
+ )
49
+ end
50
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'API with Prefix and Namespace' do
4
+ def app
5
+ Class.new(Grape::API) do
6
+ format :json
7
+ prefix 'api'
8
+
9
+ namespace :status do
10
+ desc 'Retrieve status.'
11
+ get do
12
+ end
13
+ end
14
+
15
+ add_swagger_documentation
16
+ end
17
+ end
18
+
19
+ subject do
20
+ get '/api/swagger_doc'
21
+ expect(last_response.status).to eq 200
22
+ body = JSON.parse last_response.body
23
+ body['apis']
24
+ end
25
+
26
+ it 'gets array types' do
27
+ expect(subject).to eq([
28
+ { 'path' => '/status.{format}', 'description' => 'Operations about statuses' },
29
+ { 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
30
+ ])
31
+ end
32
+ end
@@ -47,14 +47,14 @@ describe 'Standalone namespace API' do
47
47
 
48
48
  it 'that contains all api paths' do
49
49
  expect(json_body['apis']).to eq(
50
- [
51
- { 'path' => '/store.{format}', 'description' => 'Operations about stores' },
52
- { 'path' => '/store_orders.{format}', 'description' => 'Operations about store/orders' },
53
- { 'path' => '/store_orders_actions2.{format}', 'description' => 'Operations about store/orders/actions2s' },
54
- { 'path' => '/specific-store-orders.{format}', 'description' => 'Operations about store/:store_id/orders' },
55
- { 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
56
- ]
57
- )
50
+ [
51
+ { 'path' => '/store.{format}', 'description' => 'Operations about stores' },
52
+ { 'path' => '/store_orders.{format}', 'description' => 'Operations about store/orders' },
53
+ { 'path' => '/store_orders_actions2.{format}', 'description' => 'Operations about store/orders/actions2s' },
54
+ { 'path' => '/specific-store-orders.{format}', 'description' => 'Operations about store/:store_id/orders' },
55
+ { 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
56
+ ]
57
+ )
58
58
  end
59
59
  end
60
60
 
@@ -152,14 +152,14 @@ describe 'Standalone namespace API' do
152
152
 
153
153
  it 'that contains all api paths' do
154
154
  expect(json_body['apis']).to eq(
155
- [
156
- { 'path' => '/store.{format}', 'description' => 'Operations about stores' },
157
- { 'path' => '/store_orders.{format}', 'description' => 'Operations about store/orders' },
158
- { 'path' => '/store_orders_actions2.{format}', 'description' => 'Operations about store/orders/actions2s' },
159
- { 'path' => '/specific-store-orders.{format}', 'description' => 'Operations about store/:store_id/orders' },
160
- { 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
161
- ]
162
- )
155
+ [
156
+ { 'path' => '/store.{format}', 'description' => 'Operations about stores' },
157
+ { 'path' => '/store_orders.{format}', 'description' => 'Operations about store/orders' },
158
+ { 'path' => '/store_orders_actions2.{format}', 'description' => 'Operations about store/orders/actions2s' },
159
+ { 'path' => '/specific-store-orders.{format}', 'description' => 'Operations about store/:store_id/orders' },
160
+ { 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
161
+ ]
162
+ )
163
163
  end
164
164
  end
165
165
 
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Array Entity' do
4
+ before :all do
5
+ class Something < Grape::Entity
6
+ expose :text, documentation: { type: 'string', desc: 'Content of something.' }
7
+ end
8
+ end
9
+
10
+ def app
11
+ Class.new(Grape::API) do
12
+ format :json
13
+
14
+ desc 'This returns something or an error',
15
+ is_array: true,
16
+ entity: Something
17
+ post :action do
18
+ end
19
+
20
+ add_swagger_documentation
21
+ end
22
+ end
23
+
24
+ subject do
25
+ get '/swagger_doc/action'
26
+ JSON.parse(last_response.body)
27
+ end
28
+
29
+ it 'reads param type correctly' do
30
+ expect(subject['models'].keys).to include 'Something'
31
+ expect(subject['apis'][0]['operations'][0]['type']).to eq('array')
32
+ expect(subject['apis'][0]['operations'][0]['items']).to eq('$ref' => 'Something')
33
+ end
34
+ end
@@ -14,21 +14,50 @@ describe 'Array Params' do
14
14
  post :splines do
15
15
  end
16
16
 
17
+ params do
18
+ optional :raw_array, type: Array
19
+ end
20
+ get :raw_array_splines do
21
+ end
22
+
23
+ params do
24
+ optional :raw_array, type: Array[Integer]
25
+ end
26
+ get :raw_array_integers do
27
+ end
28
+
17
29
  add_swagger_documentation
18
30
  end
19
31
  end
20
32
 
21
- subject do
33
+ it 'gets array types' do
22
34
  get '/swagger_doc/splines'
23
35
  expect(last_response.status).to eq 200
24
36
  body = JSON.parse last_response.body
25
- body['apis'].first['operations'].first['parameters']
26
- end
27
-
28
- it 'gets array types' do
29
- expect(subject).to eq [
37
+ parameters = body['apis'].first['operations'].first['parameters']
38
+ expect(parameters).to eq [
30
39
  { 'paramType' => 'form', 'name' => 'a_array[][param_1]', 'description' => nil, 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' },
31
40
  { 'paramType' => 'form', 'name' => 'a_array[][param_2]', 'description' => nil, 'type' => 'string', 'required' => true, 'allowMultiple' => false }
32
41
  ]
33
42
  end
43
+
44
+ it 'get raw array type' do
45
+ get '/swagger_doc/raw_array_splines'
46
+ expect(last_response.status).to eq 200
47
+ body = JSON.parse last_response.body
48
+ parameters = body['apis'].first['operations'].first['parameters']
49
+ expect(parameters).to eq [
50
+ { 'paramType' => 'query', 'name' => 'raw_array', 'description' => nil, 'type' => 'Array', 'required' => false, 'allowMultiple' => false }
51
+ ]
52
+ end
53
+
54
+ it 'get raw array integer' do
55
+ get '/swagger_doc/raw_array_integers'
56
+ expect(last_response.status).to eq 200
57
+ body = JSON.parse last_response.body
58
+ parameters = body['apis'].first['operations'].first['parameters']
59
+ expect(parameters).to eq [
60
+ { 'paramType' => 'query', 'name' => 'raw_array', 'description' => nil, 'type' => 'array', 'required' => false, 'allowMultiple' => false, 'items' => { 'type' => 'integer', 'format' => 'int32' } }
61
+ ]
62
+ end
34
63
  end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'grape_version'
2
3
 
3
4
  describe 'Default API' do
4
5
  context 'with no additional options' do
@@ -38,6 +39,47 @@ describe 'Default API' do
38
39
  end
39
40
  end
40
41
  end
42
+
43
+ end
44
+ context 'with additional option block given to desc', if: GrapeVersion.satisfy?('>= 0.12.0') do
45
+ def app
46
+ Class.new(Grape::API) do
47
+ format :json
48
+ desc 'This gets something.' do
49
+ detail 'more details about the endpoint'
50
+ end
51
+ get '/something' do
52
+ { bla: 'something' }
53
+ end
54
+ add_swagger_documentation
55
+ end
56
+ end
57
+
58
+ subject do
59
+ get '/swagger_doc/something'
60
+ JSON.parse(last_response.body)
61
+ end
62
+
63
+ it 'documents endpoint' do
64
+ expect(subject).to eq(
65
+ 'apiVersion' => '0.1',
66
+ 'swaggerVersion' => '1.2',
67
+ 'basePath' => 'http://example.org',
68
+ 'produces' => ['application/json'],
69
+ 'resourcePath' => '/something',
70
+ 'apis' => [{
71
+ 'path' => '/something.{format}',
72
+ 'operations' => [{
73
+ 'notes' => 'more details about the endpoint',
74
+ 'summary' => 'This gets something.',
75
+ 'nickname' => 'GET-something--json-',
76
+ 'method' => 'GET',
77
+ 'parameters' => [],
78
+ 'type' => 'void'
79
+ }]
80
+ }]
81
+ )
82
+ end
41
83
  end
42
84
 
43
85
  context 'with additional info' do
@@ -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' => 'float', 'required' => true, 'allowMultiple' => false }
27
+ { 'paramType' => 'form', 'name' => 'a_float', 'description' => nil, 'type' => 'number', 'format' => 'float', 'required' => true, 'allowMultiple' => false }
28
28
  ]
29
29
  end
30
30
  end
@@ -24,6 +24,19 @@ describe 'helpers' do
24
24
  ]
25
25
  end
26
26
 
27
+ it 'parses params as query strings for a GET with an example' do
28
+ params = {
29
+ name: { type: 'String', desc: 'A name', required: true, default: 'default api value', documentation: { example: 'default swagger value' } },
30
+ level: 'max'
31
+ }
32
+ path = '/coolness'
33
+ method = 'GET'
34
+ expect(subject.parse_params(params, path, method)).to eq [
35
+ { paramType: 'query', name: :name, description: 'A name', type: 'string', required: true, allowMultiple: false, defaultValue: 'default swagger value' },
36
+ { paramType: 'query', name: :level, description: '', type: 'string', required: false, allowMultiple: false }
37
+ ]
38
+ end
39
+
27
40
  it 'parses params as form for a POST' do
28
41
  params = {
29
42
  name: { type: 'String', desc: 'A name', required: true },
@@ -132,7 +145,7 @@ describe 'helpers' do
132
145
  'XAuthToken' => { description: 'A required header.', required: true, default: 'default' }
133
146
  }
134
147
  expect(subject.parse_header_params(params)).to eq [
135
- { paramType: 'header', name: 'XAuthToken', description: 'A required header.', type: 'String', required: true, defaultValue: 'default' }
148
+ { paramType: 'header', name: 'XAuthToken', description: 'A required header.', type: 'string', required: true, defaultValue: 'default' }
136
149
  ]
137
150
  end
138
151
  end