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,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Float Params' do
6
+ def app
7
+ Class.new(Grape::API) do
8
+ format :json
9
+
10
+ desc 'splines' do
11
+ consumes ['application/x-www-form-urlencoded']
12
+ end
13
+ params do
14
+ requires :a_float, type: Float
15
+ end
16
+ post :splines do
17
+ { message: 'hi' }
18
+ end
19
+
20
+ add_swagger_documentation
21
+ end
22
+ end
23
+
24
+ subject do
25
+ get '/swagger_doc/splines'
26
+ expect(last_response.status).to eq 200
27
+ body = JSON.parse last_response.body
28
+ body['paths']['/splines']['post']['parameters']
29
+ end
30
+
31
+ it 'converts float types' do
32
+ expect(subject).to eq [
33
+ { 'in' => 'formData', 'name' => 'a_float', 'type' => 'number', 'required' => true, 'format' => 'float' }
34
+ ]
35
+ end
36
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Form Params' do
6
+ def app
7
+ Class.new(Grape::API) do
8
+ format :json
9
+
10
+ desc 'get items' do
11
+ consumes ['application/x-www-form-urlencoded']
12
+ end
13
+ params do
14
+ requires :name, type: String, desc: 'name of item'
15
+ end
16
+ post '/items' do
17
+ {}
18
+ end
19
+
20
+ desc 'get item' do
21
+ consumes ['application/x-www-form-urlencoded']
22
+ end
23
+ params do
24
+ requires :id, type: Integer, desc: 'id of item'
25
+ requires :name, type: String, desc: 'name of item'
26
+ requires :conditions, type: Integer, desc: 'conditions of item', values: [1, 2, 3]
27
+ end
28
+ put '/items/:id' do
29
+ {}
30
+ end
31
+
32
+ params do
33
+ requires :id, type: Integer, desc: 'id of item'
34
+ requires :name, type: String, desc: 'name of item'
35
+ optional :conditions, type: String, desc: 'conditions of item', values: proc { %w[1 2] }
36
+ end
37
+ patch '/items/:id' do
38
+ {}
39
+ end
40
+
41
+ desc 'create item' do
42
+ consumes ['application/x-www-form-urlencoded']
43
+ end
44
+ params do
45
+ requires :id, type: Integer, desc: 'id of item'
46
+ requires :name, type: String, desc: 'name of item'
47
+ optional :conditions, type: Symbol, desc: 'conditions of item', values: %i[one two]
48
+ end
49
+ post '/items/:id' do
50
+ {}
51
+ end
52
+
53
+ add_swagger_documentation
54
+ end
55
+ end
56
+
57
+ subject do
58
+ get '/swagger_doc/items'
59
+ JSON.parse(last_response.body)
60
+ end
61
+
62
+ it 'retrieves the documentation form params' do
63
+ expect(subject['paths'].length).to eq 2
64
+ expect(subject['paths'].keys).to include('/items', '/items/{id}')
65
+ expect(subject['paths']['/items'].keys).to include 'post'
66
+ expect(subject['paths']['/items/{id}'].keys).to include('post', 'patch', 'put')
67
+ end
68
+
69
+ it 'treats Symbol parameter as form param' do
70
+ expect(subject['paths']['/items/{id}']['post']['parameters']).to eq [
71
+ { 'in' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'format' => 'int32' },
72
+ { 'in' => 'formData', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true },
73
+ { 'in' => 'formData', 'name' => 'conditions', 'description' => 'conditions of item', 'type' => 'string', 'required' => false, 'enum' => %w[one two] }
74
+ ]
75
+ end
76
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe GrapeInstance do
6
+ it 'added combined-routes' do
7
+ expect(described_class).to respond_to :combined_routes
8
+ end
9
+
10
+ it 'added add_swagger_documentation' do
11
+ expect(described_class).to respond_to :add_swagger_documentation
12
+ end
13
+
14
+ it 'added combined-namespaces' do
15
+ expect(described_class).to respond_to :combined_namespaces
16
+ end
17
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ class SampleAuth < Grape::Middleware::Base
6
+ module AuthMethods
7
+ attr_accessor :access_token
8
+
9
+ def protected_endpoint=(protected)
10
+ @protected_endpoint = protected
11
+ end
12
+
13
+ def protected_endpoint?
14
+ @protected_endpoint || false
15
+ end
16
+
17
+ def resource_owner
18
+ @resource_owner = true if access_token == '12345'
19
+ end
20
+ end
21
+
22
+ def context
23
+ env['api.endpoint']
24
+ end
25
+
26
+ def before
27
+ context.extend(SampleAuth::AuthMethods)
28
+ context.protected_endpoint = context.options[:route_options][:auth].present?
29
+
30
+ return unless context.protected_endpoint?
31
+
32
+ scopes = context.options[:route_options][:auth][:scopes]
33
+ authorize!(*scopes) unless scopes.include? false
34
+ context.access_token = env['HTTP_AUTHORIZATION']
35
+ end
36
+ end
37
+
38
+ module Extension
39
+ def sample_auth(*scopes)
40
+ description = route_setting(:description) || route_setting(:description, {})
41
+ description[:auth] = { scopes: scopes }
42
+ end
43
+
44
+ GrapeInstance.extend self
45
+ end
46
+
47
+ describe 'a guarded api endpoint' do
48
+ before :all do
49
+ class GuardedMountedApi < Grape::API
50
+ resource_owner_valid = proc { |token_owner = nil| token_owner.nil? }
51
+
52
+ desc 'Show endpoint if authenticated'
53
+ route_setting :swagger, hidden: resource_owner_valid
54
+ get '/auth' do
55
+ { foo: 'bar' }
56
+ end
57
+ end
58
+
59
+ class GuardedApi < Grape::API
60
+ mount GuardedMountedApi
61
+ add_swagger_documentation endpoint_auth_wrapper: SampleAuth,
62
+ swagger_endpoint_guard: 'sample_auth false',
63
+ token_owner: 'resource_owner'
64
+ end
65
+ end
66
+
67
+ def app
68
+ GuardedApi
69
+ end
70
+
71
+ let(:endpoint) { '/swagger_doc.json' }
72
+ let(:auth_token) { nil }
73
+
74
+ subject do
75
+ get endpoint, {}, 'HTTP_AUTHORIZATION' => auth_token
76
+ JSON.parse(last_response.body)
77
+ end
78
+
79
+ context 'accessing the main doc endpoint' do
80
+ let(:endpoint) { '/swagger_doc.json' }
81
+
82
+ context 'when a correct token is passed with the request' do
83
+ let(:auth_token) { '12345' }
84
+
85
+ it 'retrieves swagger-documentation for the endpoint' do
86
+ expect(subject).to eq(
87
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
88
+ 'swagger' => '2.0',
89
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
90
+ 'host' => 'example.org',
91
+ 'tags' => [{ 'name' => 'auth', 'description' => 'Operations about auths' }],
92
+ 'paths' => {
93
+ '/auth' => {
94
+ 'get' => {
95
+ 'description' => 'Show endpoint if authenticated',
96
+ 'produces' => ['application/json'],
97
+ 'tags' => ['auth'],
98
+ 'operationId' => 'getAuth',
99
+ 'responses' => { '200' => { 'description' => 'Show endpoint if authenticated' } }
100
+ }
101
+ }
102
+ }
103
+ )
104
+ end
105
+ end
106
+
107
+ context 'when a bad token is passed with the request' do
108
+ let(:auth_token) { '123456' }
109
+
110
+ it 'does not retrieve swagger-documentation for the endpoint - only the info_object' do
111
+ expect(subject).to eq(
112
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
113
+ 'swagger' => '2.0',
114
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
115
+ 'host' => 'example.org'
116
+ )
117
+ end
118
+ end
119
+ end
120
+
121
+ context 'accessing the tag specific endpoint' do
122
+ let(:endpoint) { '/swagger_doc/auth.json' }
123
+
124
+ context 'when a correct token is passed with the request' do
125
+ let(:auth_token) { '12345' }
126
+
127
+ it 'retrieves swagger-documentation for the endpoint' do
128
+ expect(subject).to eq(
129
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
130
+ 'swagger' => '2.0',
131
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
132
+ 'host' => 'example.org',
133
+ 'tags' => [{ 'name' => 'auth', 'description' => 'Operations about auths' }],
134
+ 'paths' => {
135
+ '/auth' => {
136
+ 'get' => {
137
+ 'description' => 'Show endpoint if authenticated',
138
+ 'produces' => ['application/json'],
139
+ 'tags' => ['auth'],
140
+ 'operationId' => 'getAuth',
141
+ 'responses' => { '200' => { 'description' => 'Show endpoint if authenticated' } }
142
+ }
143
+ }
144
+ }
145
+ )
146
+ end
147
+ end
148
+
149
+ context 'when a bad token is passed with the request' do
150
+ let(:auth_token) { '123456' }
151
+
152
+ it 'does not retrieve swagger-documentation for the endpoint - only the info_object' do
153
+ expect(subject).to eq(
154
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
155
+ 'swagger' => '2.0',
156
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
157
+ 'host' => 'example.org'
158
+ )
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'a hide mounted api' do
6
+ before :all do
7
+ class HideMountedApi < Grape::API
8
+ desc 'Show this endpoint'
9
+ get '/simple' do
10
+ { foo: 'bar' }
11
+ end
12
+
13
+ desc 'Hide this endpoint', hidden: true
14
+ get '/hide' do
15
+ { foo: 'bar' }
16
+ end
17
+
18
+ desc 'Hide this endpoint using route setting'
19
+ route_setting :swagger, hidden: true
20
+ get '/hide_as_well' do
21
+ { foo: 'bar' }
22
+ end
23
+
24
+ desc 'Lazily show endpoint', hidden: -> { false }
25
+ get '/lazy' do
26
+ { foo: 'bar' }
27
+ end
28
+ end
29
+
30
+ class HideApi < Grape::API
31
+ mount HideMountedApi
32
+ add_swagger_documentation
33
+ end
34
+ end
35
+
36
+ def app
37
+ HideApi
38
+ end
39
+
40
+ subject do
41
+ get '/swagger_doc.json'
42
+ JSON.parse(last_response.body)
43
+ end
44
+
45
+ it "retrieves swagger-documentation that doesn't include hidden endpoints" do
46
+ expect(subject).to eq(
47
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
48
+ 'swagger' => '2.0',
49
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
50
+ 'host' => 'example.org',
51
+ 'tags' => [{ 'name' => 'simple', 'description' => 'Operations about simples' }, { 'name' => 'lazy', 'description' => 'Operations about lazies' }],
52
+ 'paths' => {
53
+ '/simple' => {
54
+ 'get' => {
55
+ 'description' => 'Show this endpoint',
56
+ 'produces' => ['application/json'],
57
+ 'tags' => ['simple'],
58
+ 'operationId' => 'getSimple',
59
+ 'responses' => { '200' => { 'description' => 'Show this endpoint' } }
60
+ }
61
+ },
62
+ '/lazy' => {
63
+ 'get' => {
64
+ 'description' => 'Lazily show endpoint',
65
+ 'produces' => ['application/json'],
66
+ 'tags' => ['lazy'],
67
+ 'operationId' => 'getLazy',
68
+ 'responses' => { '200' => { 'description' => 'Lazily show endpoint' } }
69
+ }
70
+ }
71
+ }
72
+ )
73
+ end
74
+ end
75
+
76
+ describe 'a hide mounted api with same namespace' do
77
+ before :all do
78
+ class HideNamespaceMountedApi < Grape::API
79
+ desc 'Show this endpoint'
80
+ get '/simple/show' do
81
+ { foo: 'bar' }
82
+ end
83
+
84
+ desc 'Hide this endpoint', hidden: true
85
+ get '/simple/hide' do
86
+ { foo: 'bar' }
87
+ end
88
+
89
+ desc 'Lazily hide endpoint', hidden: -> { true }
90
+ get '/simple/lazy' do
91
+ { foo: 'bar' }
92
+ end
93
+ end
94
+
95
+ class HideNamespaceApi < Grape::API
96
+ mount HideNamespaceMountedApi
97
+ add_swagger_documentation
98
+ end
99
+ end
100
+
101
+ def app
102
+ HideNamespaceApi
103
+ end
104
+
105
+ it 'retrieves swagger-documentation on /swagger_doc' do
106
+ get '/swagger_doc.json'
107
+ expect(JSON.parse(last_response.body)).to eq(
108
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
109
+ 'swagger' => '2.0',
110
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
111
+ 'host' => 'example.org',
112
+ 'tags' => [{ 'name' => 'simple', 'description' => 'Operations about simples' }],
113
+ 'paths' => {
114
+ '/simple/show' => {
115
+ 'get' => {
116
+ 'description' => 'Show this endpoint',
117
+ 'produces' => ['application/json'],
118
+ 'operationId' => 'getSimpleShow',
119
+ 'tags' => ['simple'], 'responses' => { '200' => { 'description' => 'Show this endpoint' } }
120
+ }
121
+ }
122
+ }
123
+ )
124
+ end
125
+
126
+ it "retrieves the documentation for mounted-api that doesn't include hidden endpoints" do
127
+ get '/swagger_doc/simple.json'
128
+ expect(JSON.parse(last_response.body)).to eq(
129
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
130
+ 'swagger' => '2.0',
131
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
132
+ 'host' => 'example.org',
133
+ 'tags' => [{ 'name' => 'simple', 'description' => 'Operations about simples' }],
134
+ 'paths' => {
135
+ '/simple/show' => {
136
+ 'get' => {
137
+ 'description' => 'Show this endpoint',
138
+ 'produces' => ['application/json'],
139
+ 'tags' => ['simple'],
140
+ 'operationId' => 'getSimpleShow',
141
+ 'responses' => { '200' => { 'description' => 'Show this endpoint' } }
142
+ }
143
+ }
144
+ }
145
+ )
146
+ end
147
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'host in the swagger_doc' do
6
+ before :all do
7
+ module TheApi
8
+ class EmptyApi < Grape::API
9
+ format :json
10
+
11
+ add_swagger_documentation
12
+ end
13
+ end
14
+ end
15
+
16
+ def app
17
+ TheApi::EmptyApi
18
+ end
19
+
20
+ describe 'host should include port' do
21
+ subject do
22
+ get 'http://example.com:8080/swagger_doc'
23
+ JSON.parse(last_response.body)
24
+ end
25
+
26
+ specify do
27
+ expect(subject['host']).to eq 'example.com:8080'
28
+ end
29
+ end
30
+
31
+ describe 'respect X-Forwarded-Host over Host header' do
32
+ subject do
33
+ header 'Host', 'dummy.example.com'
34
+ header 'X-Forwarded-Host', 'real.example.com'
35
+ get '/swagger_doc'
36
+ JSON.parse(last_response.body)
37
+ end
38
+
39
+ specify do
40
+ expect(subject['host']).to eq 'real.example.com'
41
+ end
42
+ end
43
+ end
@@ -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
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'mount override api' do
6
+ def app
7
+ old_api = Class.new(Grape::API) do
8
+ desc 'old endpoint', success: { code: 200, message: 'old message' }
9
+ params do
10
+ optional :param, type: Integer, desc: 'old param'
11
+ end
12
+ get do
13
+ 'old'
14
+ end
15
+ end
16
+
17
+ new_api = Class.new(Grape::API) do
18
+ desc 'new endpoint', success: { code: 200, message: 'new message' }
19
+ params do
20
+ optional :param, type: String, desc: 'new param'
21
+ end
22
+ get do
23
+ 'new'
24
+ end
25
+ end
26
+
27
+ Class.new(Grape::API) do
28
+ mount new_api
29
+ mount old_api
30
+
31
+ add_swagger_documentation format: :json
32
+ end
33
+ end
34
+
35
+ context 'actual api request' do
36
+ subject do
37
+ get '/'
38
+ last_response.body
39
+ end
40
+
41
+ it 'returns data from new endpoint' do
42
+ is_expected.to eq 'new'
43
+ end
44
+ end
45
+
46
+ context 'api documentation' do
47
+ subject do
48
+ get '/swagger_doc'
49
+ JSON.parse(last_response.body)['paths']['/']['get']
50
+ end
51
+
52
+ it 'shows documentation from new endpoint' do
53
+ expect(subject['parameters'][0]['description']).to eql('new param')
54
+ expect(subject['parameters'][0]['type']).to eql('string')
55
+ expect(subject['responses']['200']['description']).to eql('new message')
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ xdescribe 'docs mounted separately from api' do
6
+ before :all do
7
+ class ActualApi < Grape::API
8
+ desc 'Document root'
9
+
10
+ desc 'This gets something.',
11
+ notes: '_test_'
12
+ get '/simple' do
13
+ { bla: 'something' }
14
+ end
15
+ end
16
+
17
+ class MountedDocs < Grape::API
18
+ add_swagger_documentation(target_class: ActualApi)
19
+ end
20
+
21
+ class WholeApp < Grape::API
22
+ mount ActualApi
23
+ mount MountedDocs
24
+ end
25
+ end
26
+
27
+ def app
28
+ WholeApp
29
+ end
30
+
31
+ it 'retrieves docs for actual api class' do
32
+ get '/swagger_doc.json'
33
+ expect(JSON.parse(last_response.body)).to eq(
34
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
35
+ 'swagger' => '2.0',
36
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
37
+ 'host' => 'example.org',
38
+ 'tags' => [{ 'name' => 'simple', 'description' => 'Operations about simples' }],
39
+ 'paths' => {
40
+ '/simple' => {
41
+ 'get' => {
42
+ 'description' => 'This gets something.',
43
+ 'produces' => ['application/json'],
44
+ 'responses' => { '200' => { 'description' => 'This gets something.' } },
45
+ 'tags' => ['simple'],
46
+ 'operationId' => 'getSimple'
47
+ }
48
+ }
49
+ }
50
+ )
51
+ end
52
+
53
+ it 'retrieves docs for endpoint in actual api class' do
54
+ get '/swagger_doc/simple.json'
55
+ expect(JSON.parse(last_response.body)).to eq(
56
+ 'info' => { 'title' => 'API title', 'version' => '0.0.1' },
57
+ 'swagger' => '2.0',
58
+ 'tags' => [{ 'name' => 'simple', 'description' => 'Operations about simples' }],
59
+ 'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
60
+ 'host' => 'example.org',
61
+ 'paths' => {
62
+ '/simple' => {
63
+ 'get' => {
64
+ 'description' => 'This gets something.',
65
+ 'produces' => ['application/json'],
66
+ 'responses' => {
67
+ '200' => { 'description' => 'This gets something.' }
68
+ },
69
+ 'tags' => ['simple'],
70
+ 'operationId' => 'getSimple'
71
+ }
72
+ }
73
+ }
74
+ )
75
+ end
76
+ end