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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +14 -0
  3. data/.github/workflows/rubocop.yml +26 -0
  4. data/.github/workflows/ruby.yml +30 -0
  5. data/.gitignore +1 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +65 -2
  8. data/.rubocop_todo.yml +1 -1
  9. data/CHANGELOG.md +66 -0
  10. data/Gemfile +9 -4
  11. data/README.md +213 -13
  12. data/UPGRADING.md +38 -0
  13. data/grape-swagger.gemspec +4 -4
  14. data/lib/grape-swagger/doc_methods/build_model_definition.rb +53 -2
  15. data/lib/grape-swagger/doc_methods/data_type.rb +4 -4
  16. data/lib/grape-swagger/doc_methods/format_data.rb +4 -2
  17. data/lib/grape-swagger/doc_methods/move_params.rb +6 -7
  18. data/lib/grape-swagger/doc_methods/operation_id.rb +2 -2
  19. data/lib/grape-swagger/doc_methods/parse_params.rb +51 -9
  20. data/lib/grape-swagger/doc_methods.rb +65 -62
  21. data/lib/grape-swagger/endpoint.rb +83 -32
  22. data/lib/grape-swagger/errors.rb +2 -0
  23. data/lib/grape-swagger/model_parsers.rb +2 -2
  24. data/lib/grape-swagger/rake/oapi_tasks.rb +3 -1
  25. data/lib/grape-swagger/version.rb +1 -1
  26. data/lib/grape-swagger.rb +7 -4
  27. data/spec/issues/427_entity_as_string_spec.rb +1 -1
  28. data/spec/issues/430_entity_definitions_spec.rb +7 -5
  29. data/spec/issues/537_enum_values_spec.rb +1 -0
  30. data/spec/issues/776_multiple_presents_spec.rb +59 -0
  31. data/spec/issues/809_utf8_routes_spec.rb +55 -0
  32. data/spec/issues/832_array_hash_float_decimal_spec.rb +111 -0
  33. data/spec/lib/data_type_spec.rb +12 -0
  34. data/spec/lib/format_data_spec.rb +24 -0
  35. data/spec/lib/move_params_spec.rb +2 -2
  36. data/spec/spec_helper.rb +1 -1
  37. data/spec/support/empty_model_parser.rb +3 -2
  38. data/spec/support/mock_parser.rb +1 -2
  39. data/spec/support/model_parsers/entity_parser.rb +8 -8
  40. data/spec/support/model_parsers/mock_parser.rb +24 -8
  41. data/spec/support/model_parsers/representable_parser.rb +8 -8
  42. data/spec/support/namespace_tags.rb +3 -0
  43. data/spec/support/the_paths_definitions.rb +4 -4
  44. data/spec/swagger_v2/api_swagger_v2_additional_properties_spec.rb +83 -0
  45. data/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb +1 -1
  46. data/spec/swagger_v2/api_swagger_v2_mounted_spec.rb +1 -0
  47. data/spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb +73 -1
  48. data/spec/swagger_v2/api_swagger_v2_param_type_body_spec.rb +2 -2
  49. data/spec/swagger_v2/api_swagger_v2_response_with_headers_spec.rb +4 -2
  50. data/spec/swagger_v2/api_swagger_v2_response_with_models_spec.rb +53 -0
  51. data/spec/swagger_v2/api_swagger_v2_spec.rb +1 -0
  52. data/spec/swagger_v2/boolean_params_spec.rb +4 -1
  53. data/spec/swagger_v2/float_api_spec.rb +1 -0
  54. data/spec/swagger_v2/inheritance_and_discriminator_spec.rb +57 -0
  55. data/spec/swagger_v2/namespace_tags_prefix_spec.rb +1 -0
  56. data/spec/swagger_v2/param_multi_type_spec.rb +2 -0
  57. data/spec/swagger_v2/param_type_spec.rb +3 -0
  58. data/spec/swagger_v2/param_values_spec.rb +6 -0
  59. data/spec/swagger_v2/{params_array_collection_fromat_spec.rb → params_array_collection_format_spec.rb} +0 -0
  60. data/spec/swagger_v2/params_example_spec.rb +40 -0
  61. data/spec/swagger_v2/reference_entity_spec.rb +74 -29
  62. data/spec/swagger_v2/security_requirement_spec.rb +2 -2
  63. data/spec/swagger_v2/simple_mounted_api_spec.rb +3 -0
  64. metadata +31 -13
  65. 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' => 'This returns something' },
222
- 'UseItemResponseAsType' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, 'responses' => { 'description' => '', 'type' => 'ResponseItem' } }, 'description' => 'This returns something' }
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' => 'This returns something' },
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' => 'This returns something' }
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' => 'This returns something' }
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' => 'nested route inside namespace'
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' => 'This gets Things.'
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' => 'This gets Things.'
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 { |token_owner = nil| token_owner.nil? } }
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
@@ -81,6 +81,7 @@ describe 'swagger spec v2.0' do
81
81
  requires :id, type: Integer
82
82
  end
83
83
  delete '/dummy/:id' do
84
+ {}
84
85
  end
85
86
 
86
87
  namespace :other_thing 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/NestedModule::ApiResponse',
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']['NestedModule::ApiResponse']).not_to be_nil
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
- success Hash[status: 204, message: 'No content', headers: { 'Location' => { description: 'Location of resource', type: 'string' } }]
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
- success Hash[status: 200, model: 'File', headers: { 'Cache-Control' => { description: 'Directive for caching', type: 'string' } }]
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
@@ -80,6 +80,7 @@ describe 'swagger spec v2.0' do
80
80
  requires :id, type: Integer
81
81
  end
82
82
  delete '/dummy/:id' do
83
+ {}
83
84
  end
84
85
 
85
86
  namespace :other_thing do
@@ -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
@@ -11,6 +11,7 @@ describe 'Float Params' do
11
11
  requires :a_float, type: Float
12
12
  end
13
13
  post :splines do
14
+ { message: 'hi' }
14
15
  end
15
16
 
16
17
  add_swagger_documentation
@@ -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
@@ -17,6 +17,7 @@ describe 'namespace tags check while using prefix and version' do
17
17
  namespace :hudson do
18
18
  desc 'Document root'
19
19
  get '/' do
20
+ { message: 'hi' }
20
21
  end
21
22
  end
22
23
 
@@ -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
@@ -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