gitlab-grape-swagger 1.5.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.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.github/dependabot.yml +20 -0
  4. data/.github/workflows/ci.yml +45 -0
  5. data/.gitignore +44 -0
  6. data/.gitlab-ci.yml +19 -0
  7. data/.rspec +3 -0
  8. data/.rubocop.yml +136 -0
  9. data/.rubocop_todo.yml +60 -0
  10. data/.ruby-gemset +1 -0
  11. data/CHANGELOG.md +671 -0
  12. data/CONTRIBUTING.md +126 -0
  13. data/Dangerfile +3 -0
  14. data/Gemfile +45 -0
  15. data/Gemfile.lock +249 -0
  16. data/LICENSE.txt +20 -0
  17. data/README.md +1772 -0
  18. data/RELEASING.md +82 -0
  19. data/Rakefile +20 -0
  20. data/UPGRADING.md +201 -0
  21. data/example/api/endpoints.rb +131 -0
  22. data/example/api/entities.rb +18 -0
  23. data/example/config.ru +42 -0
  24. data/example/example_requests.postman_collection +146 -0
  25. data/example/splines.png +0 -0
  26. data/example/swagger-example.png +0 -0
  27. data/grape-swagger.gemspec +23 -0
  28. data/lib/grape-swagger/doc_methods/build_model_definition.rb +68 -0
  29. data/lib/grape-swagger/doc_methods/data_type.rb +110 -0
  30. data/lib/grape-swagger/doc_methods/extensions.rb +101 -0
  31. data/lib/grape-swagger/doc_methods/file_params.rb +17 -0
  32. data/lib/grape-swagger/doc_methods/format_data.rb +53 -0
  33. data/lib/grape-swagger/doc_methods/headers.rb +20 -0
  34. data/lib/grape-swagger/doc_methods/move_params.rb +209 -0
  35. data/lib/grape-swagger/doc_methods/operation_id.rb +32 -0
  36. data/lib/grape-swagger/doc_methods/optional_object.rb +30 -0
  37. data/lib/grape-swagger/doc_methods/parse_params.rb +190 -0
  38. data/lib/grape-swagger/doc_methods/path_string.rb +52 -0
  39. data/lib/grape-swagger/doc_methods/produces_consumes.rb +15 -0
  40. data/lib/grape-swagger/doc_methods/status_codes.rb +21 -0
  41. data/lib/grape-swagger/doc_methods/tag_name_description.rb +34 -0
  42. data/lib/grape-swagger/doc_methods/version.rb +20 -0
  43. data/lib/grape-swagger/doc_methods.rb +142 -0
  44. data/lib/grape-swagger/endpoint/params_parser.rb +76 -0
  45. data/lib/grape-swagger/endpoint.rb +476 -0
  46. data/lib/grape-swagger/errors.rb +17 -0
  47. data/lib/grape-swagger/instance.rb +7 -0
  48. data/lib/grape-swagger/model_parsers.rb +42 -0
  49. data/lib/grape-swagger/rake/oapi_tasks.rb +135 -0
  50. data/lib/grape-swagger/version.rb +5 -0
  51. data/lib/grape-swagger.rb +174 -0
  52. data/spec/issues/267_nested_namespaces.rb +55 -0
  53. data/spec/issues/403_versions_spec.rb +124 -0
  54. data/spec/issues/427_entity_as_string_spec.rb +39 -0
  55. data/spec/issues/430_entity_definitions_spec.rb +94 -0
  56. data/spec/issues/532_allow_custom_format_spec.rb +42 -0
  57. data/spec/issues/533_specify_status_code_spec.rb +78 -0
  58. data/spec/issues/537_enum_values_spec.rb +50 -0
  59. data/spec/issues/539_array_post_body_spec.rb +65 -0
  60. data/spec/issues/542_array_of_type_in_post_body_spec.rb +46 -0
  61. data/spec/issues/553_align_array_put_post_params_spec.rb +152 -0
  62. data/spec/issues/572_array_post_body_spec.rb +51 -0
  63. data/spec/issues/579_align_put_post_parameters_spec.rb +185 -0
  64. data/spec/issues/582_file_response_spec.rb +55 -0
  65. data/spec/issues/587_range_parameter_delimited_by_dash_spec.rb +26 -0
  66. data/spec/issues/605_root_route_documentation_spec.rb +23 -0
  67. data/spec/issues/650_params_array_spec.rb +65 -0
  68. data/spec/issues/677_consumes_produces_add_swagger_documentation_options_spec.rb +100 -0
  69. data/spec/issues/680_keep_204_error_schemas_spec.rb +55 -0
  70. data/spec/issues/721_set_default_parameter_location_based_on_consumes_spec.rb +62 -0
  71. data/spec/issues/751_deeply_nested_objects_spec.rb +190 -0
  72. data/spec/issues/776_multiple_presents_spec.rb +59 -0
  73. data/spec/issues/784_extensions_on_params_spec.rb +42 -0
  74. data/spec/issues/809_utf8_routes_spec.rb +55 -0
  75. data/spec/issues/832_array_hash_float_decimal_spec.rb +114 -0
  76. data/spec/issues/847_route_param_options_spec.rb +37 -0
  77. data/spec/issues/873_wildcard_segments_path_parameters_spec.rb +28 -0
  78. data/spec/issues/878_optional_path_segments_spec.rb +29 -0
  79. data/spec/issues/881_handle_file_params_spec.rb +38 -0
  80. data/spec/issues/883_query_array_parameter_spec.rb +46 -0
  81. data/spec/issues/884_dont_document_non_schema_examples_spec.rb +49 -0
  82. data/spec/issues/887_prevent_duplicate_operation_ids_spec.rb +35 -0
  83. data/spec/lib/data_type_spec.rb +111 -0
  84. data/spec/lib/endpoint/params_parser_spec.rb +124 -0
  85. data/spec/lib/endpoint_spec.rb +153 -0
  86. data/spec/lib/extensions_spec.rb +185 -0
  87. data/spec/lib/format_data_spec.rb +115 -0
  88. data/spec/lib/model_parsers_spec.rb +104 -0
  89. data/spec/lib/move_params_spec.rb +444 -0
  90. data/spec/lib/oapi_tasks_spec.rb +163 -0
  91. data/spec/lib/operation_id_spec.rb +55 -0
  92. data/spec/lib/optional_object_spec.rb +47 -0
  93. data/spec/lib/parse_params_spec.rb +68 -0
  94. data/spec/lib/path_string_spec.rb +101 -0
  95. data/spec/lib/produces_consumes_spec.rb +116 -0
  96. data/spec/lib/tag_name_description_spec.rb +80 -0
  97. data/spec/lib/version_spec.rb +28 -0
  98. data/spec/spec_helper.rb +39 -0
  99. data/spec/support/empty_model_parser.rb +23 -0
  100. data/spec/support/grape_version.rb +13 -0
  101. data/spec/support/mock_parser.rb +23 -0
  102. data/spec/support/model_parsers/entity_parser.rb +334 -0
  103. data/spec/support/model_parsers/mock_parser.rb +346 -0
  104. data/spec/support/model_parsers/representable_parser.rb +406 -0
  105. data/spec/support/namespace_tags.rb +93 -0
  106. data/spec/support/the_paths_definitions.rb +109 -0
  107. data/spec/swagger_v2/api_documentation_spec.rb +42 -0
  108. data/spec/swagger_v2/api_swagger_v2_additional_properties_spec.rb +83 -0
  109. data/spec/swagger_v2/api_swagger_v2_body_definitions_spec.rb +48 -0
  110. data/spec/swagger_v2/api_swagger_v2_definitions-models_spec.rb +36 -0
  111. data/spec/swagger_v2/api_swagger_v2_detail_spec.rb +79 -0
  112. data/spec/swagger_v2/api_swagger_v2_extensions_spec.rb +145 -0
  113. data/spec/swagger_v2/api_swagger_v2_format-content_type_spec.rb +137 -0
  114. data/spec/swagger_v2/api_swagger_v2_global_configuration_spec.rb +56 -0
  115. data/spec/swagger_v2/api_swagger_v2_hash_and_array_spec.rb +64 -0
  116. data/spec/swagger_v2/api_swagger_v2_headers_spec.rb +58 -0
  117. data/spec/swagger_v2/api_swagger_v2_hide_documentation_path_spec.rb +57 -0
  118. data/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb +109 -0
  119. data/spec/swagger_v2/api_swagger_v2_ignore_defaults_spec.rb +48 -0
  120. data/spec/swagger_v2/api_swagger_v2_mounted_spec.rb +153 -0
  121. data/spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb +355 -0
  122. data/spec/swagger_v2/api_swagger_v2_param_type_body_spec.rb +217 -0
  123. data/spec/swagger_v2/api_swagger_v2_param_type_spec.rb +247 -0
  124. data/spec/swagger_v2/api_swagger_v2_request_params_fix_spec.rb +80 -0
  125. data/spec/swagger_v2/api_swagger_v2_response_spec.rb +147 -0
  126. data/spec/swagger_v2/api_swagger_v2_response_with_examples_spec.rb +135 -0
  127. data/spec/swagger_v2/api_swagger_v2_response_with_headers_spec.rb +216 -0
  128. data/spec/swagger_v2/api_swagger_v2_response_with_models_spec.rb +53 -0
  129. data/spec/swagger_v2/api_swagger_v2_response_with_root_spec.rb +153 -0
  130. data/spec/swagger_v2/api_swagger_v2_spec.rb +245 -0
  131. data/spec/swagger_v2/api_swagger_v2_status_codes_spec.rb +93 -0
  132. data/spec/swagger_v2/api_swagger_v2_type-format_spec.rb +90 -0
  133. data/spec/swagger_v2/boolean_params_spec.rb +38 -0
  134. data/spec/swagger_v2/default_api_spec.rb +175 -0
  135. data/spec/swagger_v2/deprecated_field_spec.rb +25 -0
  136. data/spec/swagger_v2/description_not_initialized_spec.rb +39 -0
  137. data/spec/swagger_v2/endpoint_versioned_path_spec.rb +130 -0
  138. data/spec/swagger_v2/errors_spec.rb +77 -0
  139. data/spec/swagger_v2/float_api_spec.rb +36 -0
  140. data/spec/swagger_v2/form_params_spec.rb +76 -0
  141. data/spec/swagger_v2/grape-swagger_spec.rb +17 -0
  142. data/spec/swagger_v2/guarded_endpoint_spec.rb +162 -0
  143. data/spec/swagger_v2/hide_api_spec.rb +147 -0
  144. data/spec/swagger_v2/host_spec.rb +43 -0
  145. data/spec/swagger_v2/inheritance_and_discriminator_spec.rb +57 -0
  146. data/spec/swagger_v2/mount_override_api_spec.rb +58 -0
  147. data/spec/swagger_v2/mounted_target_class_spec.rb +76 -0
  148. data/spec/swagger_v2/namespace_tags_prefix_spec.rb +122 -0
  149. data/spec/swagger_v2/namespace_tags_spec.rb +78 -0
  150. data/spec/swagger_v2/namespaced_api_spec.rb +121 -0
  151. data/spec/swagger_v2/nicknamed_api_spec.rb +25 -0
  152. data/spec/swagger_v2/operation_id_api_spec.rb +27 -0
  153. data/spec/swagger_v2/param_multi_type_spec.rb +82 -0
  154. data/spec/swagger_v2/param_type_spec.rb +95 -0
  155. data/spec/swagger_v2/param_values_spec.rb +180 -0
  156. data/spec/swagger_v2/params_array_collection_format_spec.rb +105 -0
  157. data/spec/swagger_v2/params_array_spec.rb +225 -0
  158. data/spec/swagger_v2/params_example_spec.rb +38 -0
  159. data/spec/swagger_v2/params_hash_spec.rb +77 -0
  160. data/spec/swagger_v2/params_nested_spec.rb +92 -0
  161. data/spec/swagger_v2/parent_less_namespace_spec.rb +32 -0
  162. data/spec/swagger_v2/reference_entity_spec.rb +129 -0
  163. data/spec/swagger_v2/security_requirement_spec.rb +46 -0
  164. data/spec/swagger_v2/simple_mounted_api_spec.rb +332 -0
  165. data/spec/version_spec.rb +10 -0
  166. metadata +225 -0
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'nested group params' do
6
+ [true, false].each do |array_use_braces|
7
+ context "when array_use_braces option is set to #{array_use_braces}" do
8
+ let(:braces) { array_use_braces ? '[]' : '' }
9
+ let(:app) do
10
+ Class.new(Grape::API) do
11
+ format :json
12
+
13
+ desc 'nested array' do
14
+ consumes ['application/x-www-form-urlencoded']
15
+ end
16
+ params do
17
+ requires :a_array, type: Array do
18
+ requires :param_1, type: Integer
19
+ requires :b_array, type: Array do
20
+ requires :param_2, type: String
21
+ end
22
+ requires :c_hash, type: Hash do
23
+ requires :param_3, type: String
24
+ end
25
+ end
26
+ requires :a_array_foo, type: String
27
+ end
28
+ post '/nested_array' do
29
+ { 'declared_params' => declared(params) }
30
+ end
31
+
32
+ desc 'nested hash' do
33
+ consumes ['application/x-www-form-urlencoded']
34
+ end
35
+ params do
36
+ requires :a_hash, type: Hash do
37
+ requires :param_1, type: Integer
38
+ requires :b_hash, type: Hash do
39
+ requires :param_2, type: String
40
+ end
41
+ requires :c_array, type: Array do
42
+ requires :param_3, type: String
43
+ end
44
+ end
45
+ requires :a_hash_foo, type: String
46
+ end
47
+ post '/nested_hash' do
48
+ { 'declared_params' => declared(params) }
49
+ end
50
+
51
+ add_swagger_documentation array_use_braces: array_use_braces
52
+ end
53
+ end
54
+
55
+ describe 'retrieves the documentation for nested array parameters' do
56
+ subject do
57
+ get '/swagger_doc/nested_array'
58
+ JSON.parse(last_response.body)
59
+ end
60
+
61
+ specify do
62
+ expect(subject['paths']['/nested_array']['post']['parameters']).to eql(
63
+ [
64
+ { 'in' => 'formData', 'name' => "a_array#{braces}[param_1]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'integer', 'format' => 'int32' } },
65
+ { 'in' => 'formData', 'name' => "a_array#{braces}[b_array]#{braces}[param_2]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } },
66
+ { 'in' => 'formData', 'name' => "a_array#{braces}[c_hash][param_3]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } },
67
+ { 'in' => 'formData', 'name' => 'a_array_foo', 'required' => true, 'type' => 'string' }
68
+ ]
69
+ )
70
+ end
71
+ end
72
+
73
+ describe 'retrieves the documentation for nested hash parameters' do
74
+ subject do
75
+ get '/swagger_doc/nested_hash'
76
+ JSON.parse(last_response.body)
77
+ end
78
+
79
+ specify do
80
+ expect(subject['paths']['/nested_hash']['post']['parameters']).to eql(
81
+ [
82
+ { 'in' => 'formData', 'name' => 'a_hash[param_1]', 'required' => true, 'type' => 'integer', 'format' => 'int32' },
83
+ { 'in' => 'formData', 'name' => 'a_hash[b_hash][param_2]', 'required' => true, 'type' => 'string' },
84
+ { 'in' => 'formData', 'name' => "a_hash[c_array]#{braces}[param_3]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } },
85
+ { 'in' => 'formData', 'name' => 'a_hash_foo', 'required' => true, 'type' => 'string' }
86
+ ]
87
+ )
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'a parent less namespace' do
6
+ include_context 'namespace example'
7
+
8
+ before :all do
9
+ class ParentLessApi < Grape::API
10
+ prefix :api
11
+ mount TheApi::ParentLessNamespaceApi
12
+ add_swagger_documentation version: 'v1'
13
+ end
14
+ end
15
+
16
+ def app
17
+ ParentLessApi
18
+ end
19
+
20
+ describe 'retrieves swagger-documentation on /swagger_doc' do
21
+ let(:route_name) { ':animal/:breed/queues/:queue_id/reservations' }
22
+ subject do
23
+ get '/api/swagger_doc.json'
24
+ JSON.parse(last_response.body)
25
+ end
26
+
27
+ specify do
28
+ expect(subject['paths']['/api/{animal}/{breed}/queues/{queue_id}/reservations']['get']['operationId'])
29
+ .to start_with('getApiAnimalBreedQueuesQueueIdReservations')
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'referenceEntity' do
6
+ before :all do
7
+ module MyAPI
8
+ module Entities
9
+ class Something < Grape::Entity
10
+ def self.entity_name
11
+ 'SomethingCustom'
12
+ end
13
+
14
+ expose :text, documentation: { type: 'string', desc: 'Content of something.' }
15
+ end
16
+
17
+ class Kind < Grape::Entity
18
+ def self.entity_name
19
+ 'KindCustom'
20
+ end
21
+
22
+ expose :title, documentation: { type: 'string', desc: 'Title of the kind.' }
23
+ expose :something, documentation: { type: Something, desc: 'Something interesting.' }
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
39
+ end
40
+
41
+ class ResponseModelApi < Grape::API
42
+ format :json
43
+ desc 'This returns kind and something or an error',
44
+ params: Entities::Kind.documentation.slice(:something),
45
+ entity: Entities::Kind,
46
+ http_codes: [
47
+ { code: 200, message: 'OK', model: Entities::Kind }
48
+ ]
49
+ params do
50
+ optional :something, desc: 'something as parameter'
51
+ end
52
+ get '/kind' do
53
+ kind = OpenStruct.new text: 'kind'
54
+ present kind, with: Entities::Kind
55
+ end
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
+
67
+ add_swagger_documentation # models: [MyAPI::Entities::Something, MyAPI::Entities::Kind]
68
+ end
69
+ end
70
+ end
71
+
72
+ def app
73
+ MyAPI::ResponseModelApi
74
+ end
75
+
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
109
+ end
110
+
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
128
+ end
129
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'security requirement on endpoint method' do
6
+ def app
7
+ Class.new(Grape::API) do
8
+ desc 'Endpoint with security requirement', security: [{ oauth_pets: ['read:pets', 'write:pets'] }]
9
+ get '/with_security' do
10
+ { foo: 'bar' }
11
+ end
12
+
13
+ desc 'Endpoint without security requirement', security: []
14
+ get '/without_security' do
15
+ { foo: 'bar' }
16
+ end
17
+
18
+ add_swagger_documentation(
19
+ security_definitions: {
20
+ petstore_auth: {
21
+ type: 'oauth2',
22
+ flow: 'implicit',
23
+ authorizationUrl: 'https://petstore.swagger.io/oauth/dialog',
24
+ scopes: {
25
+ 'read:pets': 'read your pets',
26
+ 'write:pets': 'modify pets in your account'
27
+ }
28
+ }
29
+ }
30
+ )
31
+ end
32
+ end
33
+
34
+ subject do
35
+ get '/swagger_doc.json'
36
+ JSON.parse(last_response.body)
37
+ end
38
+
39
+ it 'defines the security requirement on the endpoint method' do
40
+ expect(subject['paths']['/with_security']['get']['security']).to eql [{ 'oauth_pets' => ['read:pets', 'write:pets'] }]
41
+ end
42
+
43
+ it 'defines an empty security requirement on the endpoint method' do
44
+ expect(subject['paths']['/without_security']['get']['security']).to eql []
45
+ end
46
+ end
@@ -0,0 +1,332 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'a simple mounted api' do
6
+ before :all do
7
+ # rubocop:disable Lint/EmptyClass
8
+ class CustomType; end
9
+ # rubocop:enable Lint/EmptyClass
10
+
11
+ class SimpleMountedApi < Grape::API
12
+ desc 'Document root',
13
+ consumes: ['application/x-www-form-urlencoded']
14
+ get do
15
+ { message: 'hi' }
16
+ end
17
+
18
+ desc 'This gets something.',
19
+ consumes: ['application/x-www-form-urlencoded'],
20
+ notes: '_test_'
21
+
22
+ get '/simple' do
23
+ { bla: 'something' }
24
+ end
25
+
26
+ desc 'This gets something for URL using - separator.',
27
+ consumes: ['application/x-www-form-urlencoded'],
28
+ notes: '_test_'
29
+
30
+ get '/simple-test' do
31
+ { bla: 'something' }
32
+ end
33
+
34
+ head '/simple-head-test' do
35
+ status 200
36
+ end
37
+
38
+ options '/simple-options-test' do
39
+ status 200
40
+ end
41
+
42
+ desc 'this gets something else',
43
+ consumes: ['application/x-www-form-urlencoded'],
44
+ headers: {
45
+ 'XAuthToken' => { description: 'A required header.', required: true },
46
+ 'XOtherHeader' => { description: 'An optional header.', required: false }
47
+ },
48
+ http_codes: [
49
+ { code: 403, message: 'invalid pony' },
50
+ { code: 405, message: 'no ponies left!' }
51
+ ]
52
+
53
+ get '/simple_with_headers' do
54
+ { bla: 'something_else' }
55
+ end
56
+
57
+ desc 'this takes an array of parameters',
58
+ consumes: ['application/x-www-form-urlencoded'],
59
+ params: {
60
+ 'items[]' => { description: 'array of items', is_array: true }
61
+ }
62
+
63
+ post '/items' do
64
+ {}
65
+ end
66
+
67
+ desc 'this uses a custom parameter',
68
+ consumes: ['application/x-www-form-urlencoded'],
69
+ params: {
70
+ 'custom' => { type: CustomType, description: 'array of items', is_array: true }
71
+ }
72
+
73
+ get '/custom' do
74
+ {}
75
+ end
76
+ end
77
+
78
+ class SimpleApi < Grape::API
79
+ mount SimpleMountedApi
80
+ add_swagger_documentation
81
+ end
82
+ end
83
+
84
+ def app
85
+ SimpleApi
86
+ end
87
+
88
+ describe 'retrieves swagger-documentation on /swagger_doc' do
89
+ subject do
90
+ get '/swagger_doc.json'
91
+ JSON.parse(last_response.body)
92
+ end
93
+
94
+ specify do
95
+ expect(subject).to eq(
96
+ 'info' => {
97
+ 'title' => 'API title', 'version' => '0.0.1'
98
+ },
99
+ 'swagger' => '2.0',
100
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
101
+ 'host' => 'example.org',
102
+ 'tags' => [
103
+ { 'name' => 'simple', 'description' => 'Operations about simples' },
104
+ { 'name' => 'simple-test', 'description' => 'Operations about simple-tests' },
105
+ { 'name' => 'simple-head-test', 'description' => 'Operations about simple-head-tests' },
106
+ { 'name' => 'simple-options-test', 'description' => 'Operations about simple-options-tests' },
107
+ { 'name' => 'simple_with_headers', 'description' => 'Operations about simple_with_headers' },
108
+ { 'name' => 'items', 'description' => 'Operations about items' },
109
+ { 'name' => 'custom', 'description' => 'Operations about customs' }
110
+ ],
111
+ 'paths' => {
112
+ '/' => {
113
+ 'get' => {
114
+ 'description' => 'Document root',
115
+ 'produces' => ['application/json'],
116
+ 'responses' => { '200' => { 'description' => 'Document root' } },
117
+ 'operationId' => 'get'
118
+ }
119
+ },
120
+ '/simple' => {
121
+ 'get' => {
122
+ 'description' => 'This gets something.',
123
+ 'produces' => ['application/json'],
124
+ 'tags' => ['simple'],
125
+ 'operationId' => 'getSimple',
126
+ 'responses' => { '200' => { 'description' => 'This gets something.' } }
127
+ }
128
+ },
129
+ '/simple-test' => {
130
+ 'get' => {
131
+ 'description' => 'This gets something for URL using - separator.',
132
+ 'produces' => ['application/json'],
133
+ 'tags' => ['simple-test'],
134
+ 'operationId' => 'getSimpleTest',
135
+ 'responses' => { '200' => { 'description' => 'This gets something for URL using - separator.' } }
136
+ }
137
+ },
138
+ '/simple-head-test' => {
139
+ 'head' => {
140
+ 'produces' => ['application/json'],
141
+ 'responses' => { '200' => { 'description' => 'head SimpleHeadTest' } },
142
+ 'tags' => ['simple-head-test'],
143
+ 'operationId' => 'headSimpleHeadTest'
144
+ }
145
+ },
146
+ '/simple-options-test' => {
147
+ 'options' => {
148
+ 'produces' => ['application/json'],
149
+ 'responses' => { '200' => { 'description' => 'option SimpleOptionsTest' } },
150
+ 'tags' => ['simple-options-test'],
151
+ 'operationId' => 'optionsSimpleOptionsTest'
152
+ }
153
+ },
154
+ '/simple_with_headers' => {
155
+ 'get' => {
156
+ 'description' => 'this gets something else',
157
+ 'produces' => ['application/json'],
158
+ 'parameters' => [
159
+ { 'in' => 'header', 'name' => 'XAuthToken', 'description' => 'A required header.', 'type' => 'string', 'required' => true },
160
+ { 'in' => 'header', 'name' => 'XOtherHeader', 'description' => 'An optional header.', 'type' => 'string', 'required' => false }
161
+ ],
162
+ 'tags' => ['simple_with_headers'],
163
+ 'operationId' => 'getSimpleWithHeaders',
164
+ 'responses' => {
165
+ '200' => { 'description' => 'this gets something else' },
166
+ '403' => { 'description' => 'invalid pony' },
167
+ '405' => { 'description' => 'no ponies left!' }
168
+ }
169
+ }
170
+ },
171
+ '/items' => {
172
+ 'post' => {
173
+ 'description' => 'this takes an array of parameters',
174
+ 'produces' => ['application/json'],
175
+ 'consumes' => ['application/x-www-form-urlencoded'],
176
+ 'parameters' => [{ 'in' => 'formData', 'name' => 'items[]', 'description' => 'array of items', 'required' => false, 'type' => 'array', 'items' => { 'type' => 'string' } }],
177
+ 'tags' => ['items'],
178
+ 'operationId' => 'postItems',
179
+ 'responses' => { '201' => { 'description' => 'this takes an array of parameters' } }
180
+ }
181
+ },
182
+ '/custom' => {
183
+ 'get' => {
184
+ 'description' => 'this uses a custom parameter',
185
+ 'produces' => ['application/json'],
186
+ 'parameters' => [{ 'in' => 'formData', 'name' => 'custom', 'description' => 'array of items', 'required' => false, 'type' => 'array', 'items' => { 'type' => 'CustomType' } }],
187
+ 'tags' => ['custom'],
188
+ 'operationId' => 'getCustom',
189
+ 'responses' => { '200' => { 'description' => 'this uses a custom parameter' } }
190
+ }
191
+ }
192
+ }
193
+ )
194
+ end
195
+ end
196
+
197
+ describe 'retrieves the documentation for mounted-api' do
198
+ subject do
199
+ get '/swagger_doc/simple.json'
200
+ JSON.parse(last_response.body)
201
+ end
202
+
203
+ specify do
204
+ expect(subject).to eq(
205
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
206
+ 'swagger' => '2.0',
207
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
208
+ 'host' => 'example.org',
209
+ 'tags' => [
210
+ { 'name' => 'simple', 'description' => 'Operations about simples' }
211
+ ],
212
+ 'paths' => {
213
+ '/simple' => {
214
+ 'get' => {
215
+ 'description' => 'This gets something.',
216
+ 'produces' => ['application/json'],
217
+ 'tags' => ['simple'],
218
+ 'operationId' => 'getSimple',
219
+ 'responses' => { '200' => { 'description' => 'This gets something.' } }
220
+ }
221
+ }
222
+ }
223
+ )
224
+ end
225
+ end
226
+
227
+ describe 'retrieves the documentation for mounted-api that' do
228
+ describe "contains '-' in URL" do
229
+ subject do
230
+ get '/swagger_doc/simple-test.json'
231
+ JSON.parse(last_response.body)
232
+ end
233
+
234
+ specify do
235
+ expect(subject).to eq(
236
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
237
+ 'swagger' => '2.0',
238
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
239
+ 'host' => 'example.org',
240
+ 'tags' => [
241
+ { 'name' => 'simple-test', 'description' => 'Operations about simple-tests' }
242
+ ],
243
+ 'paths' => {
244
+ '/simple-test' => {
245
+ 'get' => {
246
+ 'description' => 'This gets something for URL using - separator.',
247
+ 'produces' => ['application/json'],
248
+ 'tags' => ['simple-test'],
249
+ 'operationId' => 'getSimpleTest',
250
+ 'responses' => { '200' => { 'description' => 'This gets something for URL using - separator.' } }
251
+ }
252
+ }
253
+ }
254
+ )
255
+ end
256
+ end
257
+
258
+ describe 'includes headers' do
259
+ subject do
260
+ get '/swagger_doc/simple_with_headers.json'
261
+ JSON.parse(last_response.body)
262
+ end
263
+
264
+ specify do
265
+ expect(subject['paths']).to eq(
266
+ '/simple_with_headers' => {
267
+ 'get' => {
268
+ 'description' => 'this gets something else',
269
+ 'produces' => ['application/json'],
270
+ 'parameters' => [
271
+ { 'in' => 'header', 'name' => 'XAuthToken', 'description' => 'A required header.', 'type' => 'string', 'required' => true },
272
+ { 'in' => 'header', 'name' => 'XOtherHeader', 'description' => 'An optional header.', 'type' => 'string', 'required' => false }
273
+ ],
274
+ 'tags' => ['simple_with_headers'],
275
+ 'operationId' => 'getSimpleWithHeaders',
276
+ 'responses' => {
277
+ '200' => { 'description' => 'this gets something else' },
278
+ '403' => { 'description' => 'invalid pony' },
279
+ '405' => { 'description' => 'no ponies left!' }
280
+ }
281
+ }
282
+ }
283
+ )
284
+ end
285
+ end
286
+
287
+ describe 'supports array params' do
288
+ subject do
289
+ get '/swagger_doc/items.json'
290
+ JSON.parse(last_response.body)
291
+ end
292
+
293
+ specify do
294
+ expect(subject['paths']).to eq(
295
+ '/items' => {
296
+ 'post' => {
297
+ 'description' => 'this takes an array of parameters',
298
+ 'produces' => ['application/json'],
299
+ 'consumes' => ['application/x-www-form-urlencoded'],
300
+ 'parameters' => [{ 'in' => 'formData', 'name' => 'items[]', 'description' => 'array of items', 'required' => false, 'type' => 'array', 'items' => { 'type' => 'string' } }],
301
+ 'tags' => ['items'],
302
+ 'operationId' => 'postItems',
303
+ 'responses' => { '201' => { 'description' => 'this takes an array of parameters' } }
304
+ }
305
+ }
306
+ )
307
+ end
308
+ end
309
+
310
+ describe 'supports custom params types' do
311
+ subject do
312
+ get '/swagger_doc/custom.json'
313
+ JSON.parse(last_response.body)
314
+ end
315
+
316
+ specify do
317
+ expect(subject['paths']).to eq(
318
+ '/custom' => {
319
+ 'get' => {
320
+ 'description' => 'this uses a custom parameter',
321
+ 'produces' => ['application/json'],
322
+ 'parameters' => [{ 'in' => 'formData', 'name' => 'custom', 'description' => 'array of items', 'required' => false, 'type' => 'array', 'items' => { 'type' => 'CustomType' } }],
323
+ 'tags' => ['custom'],
324
+ 'operationId' => 'getCustom',
325
+ 'responses' => { '200' => { 'description' => 'this uses a custom parameter' } }
326
+ }
327
+ }
328
+ )
329
+ end
330
+ end
331
+ end
332
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe GrapeSwagger do
6
+ it '#version' do
7
+ expect(GrapeSwagger::VERSION).to_not be_nil
8
+ expect(GrapeSwagger::VERSION.split('.').count).to eq 3
9
+ end
10
+ end