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,444 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe GrapeSwagger::DocMethods::MoveParams do
6
+ include_context 'the api paths/defs'
7
+
8
+ subject { described_class }
9
+
10
+ it { expect(subject.to_s).to eql 'GrapeSwagger::DocMethods::MoveParams' }
11
+
12
+ describe 'parameters can_be_moved' do
13
+ let(:movable_params) do
14
+ [
15
+ { param_type: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
16
+ { param_type: 'body', name: 'in_body', description: 'in_body', type: 'integer', format: 'int32', required: true },
17
+ { param_type: 'query', name: 'in_query', description: 'in_query', type: 'integer', format: 'int32', required: true },
18
+ { param_type: 'header', name: 'in_header', description: 'in_header', type: 'integer', format: 'int32', required: true },
19
+ { param_type: 'formData', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
20
+ ]
21
+ end
22
+
23
+ let(:not_movable_params) do
24
+ [
25
+ { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
26
+ { in: 'query', name: 'in_query', description: 'in_query', type: 'integer', format: 'int32', required: true },
27
+ { in: 'header', name: 'in_header', description: 'in_header', type: 'integer', format: 'int32', required: true },
28
+ { in: 'formData', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
29
+ ]
30
+ end
31
+
32
+ let(:allowed_verbs) do
33
+ [:post, :put, :patch, 'POST', 'PUT', 'PATCH']
34
+ end
35
+
36
+ let(:not_allowed_verbs) do
37
+ [:get, :delete, 'GET', 'DELETE']
38
+ end
39
+
40
+ describe 'movable params' do
41
+ specify 'allowed verbs' do
42
+ allowed_verbs.each do |verb|
43
+ expect(subject.can_be_moved?(verb, movable_params)).to be true
44
+ end
45
+ end
46
+
47
+ specify 'not allowed verbs' do
48
+ not_allowed_verbs.each do |verb|
49
+ expect(subject.can_be_moved?(verb, movable_params)).to be false
50
+ end
51
+ end
52
+ end
53
+
54
+ describe 'not movable params' do
55
+ specify 'allowed verbs' do
56
+ allowed_verbs.each do |verb|
57
+ expect(subject.can_be_moved?(verb, not_movable_params)).to be false
58
+ end
59
+ end
60
+
61
+ specify 'not allowed verbs' do
62
+ not_allowed_verbs.each do |verb|
63
+ expect(subject.can_be_moved?(verb, not_movable_params)).to be false
64
+ end
65
+ end
66
+ end
67
+
68
+ describe 'movable_params' do
69
+ before do
70
+ subject.send(:unify!, movable_params)
71
+ end
72
+ let(:expected_params) do
73
+ [
74
+ { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
75
+ { in: 'query', name: 'in_query', description: 'in_query', type: 'integer', format: 'int32', required: true },
76
+ { in: 'header', name: 'in_header', description: 'in_header', type: 'integer', format: 'int32', required: true }
77
+ ]
78
+ end
79
+
80
+ let(:expected_movable_params) do
81
+ [
82
+ { in: 'body', name: 'in_body', description: 'in_body', type: 'integer', format: 'int32', required: true },
83
+ { in: 'body', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
84
+ ]
85
+ end
86
+
87
+ specify do
88
+ params_to_move = subject.send(:movable_params, movable_params)
89
+ expect(movable_params).to eql expected_params
90
+ expect(params_to_move).to eql expected_movable_params
91
+ end
92
+ end
93
+ end
94
+
95
+ describe 'parent_definition_of_params' do
96
+ let(:path) { '/in_body' }
97
+ let(:route_options) { { requirements: {} } }
98
+ describe 'POST' do
99
+ let(:params) { paths[path][:post][:parameters] }
100
+ let(:route) { Grape::Router::Route.new('POST', path.dup, **route_options) }
101
+
102
+ specify do
103
+ subject.to_definition(path, params, route, definitions)
104
+ expect(params).to eql(
105
+ [
106
+ { name: 'postInBody', in: 'body', required: true, schema: { '$ref' => '#/definitions/postInBody' } }
107
+ ]
108
+ )
109
+ expect(subject.definitions['postInBody']).not_to include :description
110
+ expect(subject.definitions['postInBody']).to eql expected_post_defs
111
+ end
112
+
113
+ context 'with a nickname' do
114
+ let(:route_options) { { nickname: 'post-body' } }
115
+
116
+ specify do
117
+ subject.to_definition(path, params, route, definitions)
118
+ expect(params).to eql(
119
+ [
120
+ { name: 'post-body', in: 'body', required: true, schema: { '$ref' => '#/definitions/post-body' } }
121
+ ]
122
+ )
123
+ expect(subject.definitions['post-body']).not_to include :description
124
+ expect(subject.definitions['post-body']).to eql expected_post_defs
125
+ end
126
+ end
127
+ end
128
+
129
+ describe 'PUT' do
130
+ let(:params) { paths['/in_body/{key}'][:put][:parameters] }
131
+ let(:route) { Grape::Router::Route.new('PUT', path.dup, **route_options) }
132
+
133
+ specify do
134
+ subject.to_definition(path, params, route, definitions)
135
+ expect(params).to eql(
136
+ [
137
+ { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
138
+ { name: 'putInBody', in: 'body', required: true, schema: { '$ref' => '#/definitions/putInBody' } }
139
+ ]
140
+ )
141
+ expect(subject.definitions['putInBody']).not_to include :description
142
+ expect(subject.definitions['putInBody']).to eql expected_put_defs
143
+ end
144
+
145
+ context 'with a nickname' do
146
+ let(:route_options) { { nickname: 'put-body' } }
147
+
148
+ specify do
149
+ subject.to_definition(path, params, route, definitions)
150
+ expect(params).to eql(
151
+ [
152
+ { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
153
+ { name: 'put-body', in: 'body', required: true, schema: { '$ref' => '#/definitions/put-body' } }
154
+ ]
155
+ )
156
+ expect(subject.definitions['put-body']).not_to include :description
157
+ expect(subject.definitions['put-body']).to eql expected_put_defs
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ describe 'nested definitions related' do
164
+ describe 'prepare_nested_names' do
165
+ let(:property) { 'address' }
166
+ before do
167
+ subject.send(:prepare_nested_names, property, params)
168
+ end
169
+
170
+ describe 'simple' do
171
+ let(:params) { [{ in: 'body', name: 'address[street]', description: 'street', type: 'string', required: true }] }
172
+ let(:expected) { [{ in: 'body', name: 'street', description: 'street', type: 'string', required: true }] }
173
+ specify do
174
+ expect(params).to eql expected
175
+ end
176
+ end
177
+
178
+ describe 'nested' do
179
+ let(:params) { [{ in: 'body', name: 'address[street][name]', description: 'street', type: 'string', required: true }] }
180
+ let(:expected) { [{ in: 'body', name: 'street[name]', description: 'street', type: 'string', required: true }] }
181
+ specify do
182
+ expect(params).to eql expected
183
+ end
184
+ end
185
+
186
+ describe 'array' do
187
+ let(:params) { [{ in: 'body', name: 'address[street_lines]', description: 'street lines', type: 'array', items: { type: 'string' }, required: true }] }
188
+ let(:expected) { [{ in: 'body', name: 'street_lines', description: 'street lines', type: 'array', items: { type: 'string' }, required: true }] }
189
+ specify do
190
+ expect(params).to eql expected
191
+ end
192
+ end
193
+ end
194
+ end
195
+
196
+ describe 'private methods' do
197
+ describe 'build_definition' do
198
+ let(:params) { [{ in: 'body', name: 'address[street][name]', description: 'street', type: 'string', required: true }] }
199
+ before do
200
+ subject.instance_variable_set(:@definitions, definitions)
201
+ subject.send(:build_definition, name, params)
202
+ end
203
+
204
+ let(:name) { 'FooBar' }
205
+ let(:definitions) { {} }
206
+
207
+ specify do
208
+ definition = definitions.to_a.first
209
+ expect(definition.first).to eql 'FooBar'
210
+ expect(definition.last).to eql(type: 'object', properties: {})
211
+ end
212
+ end
213
+
214
+ describe 'build_body_parameter' do
215
+ let(:name) { 'Foo' }
216
+ let(:reference) { 'Bar' }
217
+ let(:expected_param) do
218
+ { name: name, in: 'body', required: true, schema: { '$ref' => "#/definitions/#{name}" } }
219
+ end
220
+ specify do
221
+ parameter = subject.send(:build_body_parameter, name, {})
222
+ expect(parameter).to eql expected_param
223
+ end
224
+
225
+ describe 'body_name option specified' do
226
+ let(:route_options) { { body_name: 'body' } }
227
+ let(:expected_param) do
228
+ { name: route_options[:body_name], in: 'body', required: true, schema: { '$ref' => "#/definitions/#{name}" } }
229
+ end
230
+ specify do
231
+ parameter = subject.send(:build_body_parameter, name, route_options)
232
+ expect(parameter).to eql expected_param
233
+ end
234
+ end
235
+ end
236
+
237
+ describe 'parse_model' do
238
+ let(:ref) { '#/definitions/InBody' }
239
+ describe 'post request' do
240
+ subject(:object) { described_class.send(:parse_model, ref) }
241
+
242
+ specify { expect(object).to eql ref }
243
+ end
244
+
245
+ describe 'post request' do
246
+ let(:put_ref) { '#/definitions/InBody/{id}' }
247
+ subject(:object) { described_class.send(:parse_model, put_ref) }
248
+
249
+ specify { expect(object).to eql ref }
250
+ end
251
+ end
252
+
253
+ describe 'deletable' do
254
+ describe 'path' do
255
+ let(:param) { { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true } }
256
+ it { expect(subject.send(:deletable?, param)).to be false }
257
+ end
258
+
259
+ describe 'body' do
260
+ let(:param) { { in: 'body', name: 'in_body_1', description: 'in_body_1', type: 'integer', format: 'int32', required: true } }
261
+ it { expect(subject.send(:deletable?, param)).to be true }
262
+ end
263
+
264
+ describe 'query' do
265
+ let(:param) { { in: 'query', name: 'in_query_1', description: 'in_query_1', type: 'integer', format: 'int32', required: true } }
266
+ it { expect(subject.send(:deletable?, param)).to be false }
267
+ end
268
+
269
+ describe 'header' do
270
+ let(:param) { { in: 'header', name: 'in_header_1', description: 'in_header_1', type: 'integer', format: 'int32', required: true } }
271
+ it { expect(subject.send(:deletable?, param)).to be false }
272
+ end
273
+ end
274
+
275
+ describe 'unify' do
276
+ before :each do
277
+ subject.send(:unify!, params)
278
+ end
279
+ describe 'param type with `:in` given' do
280
+ let(:params) do
281
+ [
282
+ { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
283
+ { in: 'body', name: 'in_body', description: 'in_body', type: 'integer', format: 'int32', required: true },
284
+ { in: 'query', name: 'in_query', description: 'in_query', type: 'integer', format: 'int32', required: true },
285
+ { in: 'header', name: 'in_header', description: 'in_header', type: 'integer', format: 'int32', required: true },
286
+ { in: 'formData', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
287
+ ]
288
+ end
289
+
290
+ let(:expected_params) do
291
+ [
292
+ { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
293
+ { in: 'body', name: 'in_body', description: 'in_body', type: 'integer', format: 'int32', required: true },
294
+ { in: 'query', name: 'in_query', description: 'in_query', type: 'integer', format: 'int32', required: true },
295
+ { in: 'header', name: 'in_header', description: 'in_header', type: 'integer', format: 'int32', required: true },
296
+ { in: 'body', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
297
+ ]
298
+ end
299
+ it { expect(params).to eql expected_params }
300
+ end
301
+
302
+ describe 'let it as is' do
303
+ let(:params) do
304
+ [
305
+ { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
306
+ { in: 'formData', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
307
+ ]
308
+ end
309
+
310
+ let(:expected_params) do
311
+ [
312
+ { in: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
313
+ { in: 'formData', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
314
+ ]
315
+ end
316
+ it { expect(params).to eql expected_params }
317
+ end
318
+
319
+ describe 'param type with `:param_type` given' do
320
+ let(:params) do
321
+ [
322
+ { param_type: 'path', name: 'key', description: nil, type: 'integer', format: 'int32', required: true },
323
+ { param_type: 'body', name: 'in_body', description: 'in_body', type: 'integer', format: 'int32', required: true },
324
+ { param_type: 'query', name: 'in_query', description: 'in_query', type: 'integer', format: 'int32', required: true },
325
+ { param_type: 'header', name: 'in_header', description: 'in_header', type: 'integer', format: 'int32', required: true },
326
+ { param_type: 'formData', name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true }
327
+ ]
328
+ end
329
+
330
+ let(:expected_params) do
331
+ [
332
+ { name: 'key', description: nil, type: 'integer', format: 'int32', required: true, in: 'path' },
333
+ { name: 'in_body', description: 'in_body', type: 'integer', format: 'int32', required: true, in: 'body' },
334
+ { name: 'in_query', description: 'in_query', type: 'integer', format: 'int32', required: true, in: 'query' },
335
+ { name: 'in_header', description: 'in_header', type: 'integer', format: 'int32', required: true, in: 'header' },
336
+ { name: 'in_form_data', description: 'in_form_data', type: 'integer', format: 'int32', required: true, in: 'body' }
337
+ ]
338
+ end
339
+ it { expect(params).to eql expected_params }
340
+ end
341
+ end
342
+
343
+ describe 'add_properties_to_definition' do
344
+ before :each do
345
+ subject.send(:add_properties_to_definition, definition, properties, [])
346
+ end
347
+
348
+ context 'when definition has items key' do
349
+ let(:definition) do
350
+ {
351
+ type: 'array',
352
+ items: {
353
+ type: 'object',
354
+ properties: {
355
+ description: 'Test description'
356
+ }
357
+ }
358
+ }
359
+ end
360
+
361
+ let(:properties) do
362
+ {
363
+ strings: {
364
+ type: 'string',
365
+ description: 'string elements'
366
+ }
367
+ }
368
+ end
369
+
370
+ let(:expected_definition) do
371
+ {
372
+ type: 'array',
373
+ items: {
374
+ type: 'object',
375
+ properties: {
376
+ description: 'Test description',
377
+ strings: {
378
+ type: 'string',
379
+ description: 'string elements'
380
+ }
381
+ }
382
+ }
383
+ }
384
+ end
385
+
386
+ it 'deep merges properties into definition item properties' do
387
+ expect(definition).to eq expected_definition
388
+ end
389
+ end
390
+
391
+ context 'when definition does not have items key' do
392
+ let(:definition) do
393
+ {
394
+ type: 'object',
395
+ properties: {
396
+ parent: {
397
+ type: 'object',
398
+ description: 'Parent to child'
399
+ }
400
+ }
401
+ }
402
+ end
403
+
404
+ let(:properties) do
405
+ {
406
+ parent: {
407
+ type: 'object',
408
+ properties: {
409
+ id: {
410
+ type: 'string',
411
+ description: 'Parent ID'
412
+ }
413
+ },
414
+ required: [:id]
415
+ }
416
+ }
417
+ end
418
+
419
+ let(:expected_definition) do
420
+ {
421
+ type: 'object',
422
+ properties: {
423
+ parent: {
424
+ type: 'object',
425
+ description: 'Parent to child',
426
+ properties: {
427
+ id: {
428
+ type: 'string',
429
+ description: 'Parent ID'
430
+ }
431
+ },
432
+ required: [:id]
433
+ }
434
+ }
435
+ }
436
+ end
437
+
438
+ it 'deep merges properties into definition properties' do
439
+ expect(definition).to eq expected_definition
440
+ end
441
+ end
442
+ end
443
+ end
444
+ end
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe GrapeSwagger::Rake::OapiTasks do
6
+ module Api
7
+ class Item < Grape::API
8
+ version 'v1', using: :path
9
+
10
+ namespace :item do
11
+ get '/'
12
+ end
13
+
14
+ namespace :otherItem do
15
+ get '/'
16
+ end
17
+ end
18
+
19
+ class Base < Grape::API
20
+ prefix :api
21
+ mount Api::Item
22
+ add_swagger_documentation add_version: true
23
+ end
24
+ end
25
+
26
+ subject { described_class.new(Api::Base) }
27
+
28
+ let(:api_class) { subject.send(:api_class) }
29
+ let(:docs_url) { subject.send(:urls_for, api_class).first }
30
+
31
+ describe '.new' do
32
+ it 'accepts class name as a constant' do
33
+ expect(described_class.new(::Api::Base).send(:api_class)).to eq(Api::Base)
34
+ end
35
+
36
+ it 'accepts class name as a string' do
37
+ expect(described_class.new('::Api::Base').send(:api_class)).to eq(Api::Base)
38
+ end
39
+ end
40
+
41
+ describe '#make_request' do
42
+ describe 'complete documentation' do
43
+ before do
44
+ subject.send(:make_request, docs_url)
45
+ end
46
+
47
+ describe 'not storing' do
48
+ it 'has no error' do
49
+ expect(subject.send(:error?)).to be false
50
+ end
51
+
52
+ it 'does not allow to save' do
53
+ expect(subject.send(:save_to_file?)).to be false
54
+ end
55
+
56
+ it 'requests doc url' do
57
+ expect(docs_url).to eql '/api/swagger_doc'
58
+ end
59
+ end
60
+
61
+ describe 'store it' do
62
+ before { ENV['store'] = 'true' }
63
+ after { ENV.delete('store') }
64
+
65
+ it 'allows to save' do
66
+ expect(subject.send(:save_to_file?)).to be true
67
+ end
68
+ end
69
+ end
70
+
71
+ describe 'documentation for resource' do
72
+ before do
73
+ ENV['resource'] = resource
74
+ subject.send(:make_request, docs_url)
75
+ end
76
+
77
+ let(:response) do
78
+ JSON.parse(
79
+ subject.send(:make_request, docs_url)
80
+ )
81
+ end
82
+
83
+ after { ENV.delete('resource') }
84
+
85
+ describe 'valid name' do
86
+ let(:resource) { 'otherItem' }
87
+
88
+ it 'has no error' do
89
+ expect(subject.send(:error?)).to be false
90
+ end
91
+
92
+ it 'requests doc url' do
93
+ expect(docs_url).to eql "/api/swagger_doc/#{resource}"
94
+ end
95
+
96
+ it 'has only one resource path' do
97
+ expect(response['paths'].length).to eql 1
98
+ expect(response['paths'].keys.first).to end_with resource
99
+ end
100
+ end
101
+
102
+ describe 'wrong name' do
103
+ let(:resource) { 'foo' }
104
+
105
+ it 'has error' do
106
+ expect(subject.send(:error?)).to be true
107
+ end
108
+ end
109
+
110
+ describe 'empty name' do
111
+ let(:resource) { nil }
112
+
113
+ it 'has no error' do
114
+ expect(subject.send(:error?)).to be false
115
+ end
116
+
117
+ it 'returns complete doc' do
118
+ expect(response['paths'].length).to eql 2
119
+ end
120
+ end
121
+ end
122
+
123
+ describe 'call it' do
124
+ before do
125
+ subject.send(:make_request, docs_url)
126
+ end
127
+ specify do
128
+ expect(subject).to respond_to :oapi
129
+ expect(subject.oapi).to be_a String
130
+ expect(subject.oapi).not_to be_empty
131
+ end
132
+ end
133
+ end
134
+
135
+ describe '#file' do
136
+ describe 'no store given' do
137
+ it 'returns swagger_doc.json' do
138
+ expect(subject.send(:file, docs_url)).to end_with 'swagger_doc.json'
139
+ end
140
+ end
141
+
142
+ describe 'store given' do
143
+ after { ENV.delete('store') }
144
+
145
+ describe 'boolean true' do
146
+ before { ENV['store'] = 'true' }
147
+
148
+ it 'returns swagger_doc.json' do
149
+ expect(subject.send(:file, docs_url)).to end_with 'swagger_doc.json'
150
+ end
151
+ end
152
+
153
+ describe 'name given' do
154
+ let(:name) { 'oapi_doc.json' }
155
+ before { ENV['store'] = name }
156
+
157
+ it 'returns swagger_doc.json' do
158
+ expect(subject.send(:file, docs_url)).to include(name.split('.')[0])
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'spec_helper'
4
+
5
+ describe GrapeSwagger::DocMethods::OperationId do
6
+ subject { described_class }
7
+
8
+ specify { expect(subject).to eql GrapeSwagger::DocMethods::OperationId }
9
+ specify { expect(subject).to respond_to :build }
10
+
11
+ describe 'build' do
12
+ let(:route) { Grape::Router::Route.new(method, '/path', requirements: {}) }
13
+
14
+ describe 'GET' do
15
+ let(:method) { 'GET' }
16
+ specify { expect(subject.build(route)).to eql 'get' }
17
+ end
18
+ describe 'get' do
19
+ let(:method) { 'get' }
20
+ specify { expect(subject.build(route)).to eql 'get' }
21
+ end
22
+ describe ':get' do
23
+ let(:method) { :get }
24
+ specify { expect(subject.build(route)).to eql 'get' }
25
+ end
26
+
27
+ describe 'path given' do
28
+ let(:method) { 'GET' }
29
+ it 'GET with path foo' do
30
+ expect(subject.build(route, 'foo')).to eql 'getFoo'
31
+ end
32
+ it 'GET with path /foo' do
33
+ expect(subject.build(route, '/foo')).to eql 'getFoo'
34
+ end
35
+ it 'GET with path bar/foo' do
36
+ expect(subject.build(route, 'bar/foo')).to eql 'getBarFoo'
37
+ end
38
+ it 'GET with path bar/foo{id}' do
39
+ expect(subject.build(route, 'bar/foo{id}')).to eql 'getBarFooId'
40
+ end
41
+ it 'GET with path /bar_foo{id}' do
42
+ expect(subject.build(route, '/bar_foo{id}')).to eql 'getBarFooId'
43
+ end
44
+ it 'GET with path /bar-foo{id}' do
45
+ expect(subject.build(route, '/bar-foo{id}')).to eql 'getBarFooId'
46
+ end
47
+ it 'GET with path /simple_test/bar-foo{id}' do
48
+ expect(subject.build(route, '/simple_test/bar-foo{id}')).to eql 'getSimpleTestBarFooId'
49
+ end
50
+ it 'GET path with optional format' do
51
+ expect(subject.build(route, 'foo(.{format})')).to eql 'getFoo(.Format)'
52
+ end
53
+ end
54
+ end
55
+ end