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,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grape'
4
+
5
+ require 'grape-swagger/instance'
6
+
7
+ require 'grape-swagger/version'
8
+ require 'grape-swagger/endpoint'
9
+ require 'grape-swagger/errors'
10
+
11
+ require 'grape-swagger/doc_methods'
12
+ require 'grape-swagger/model_parsers'
13
+
14
+ module GrapeSwagger
15
+ class << self
16
+ def model_parsers
17
+ @model_parsers ||= GrapeSwagger::ModelParsers.new
18
+ end
19
+ end
20
+ autoload :Rake, 'grape-swagger/rake/oapi_tasks'
21
+ end
22
+
23
+ module SwaggerRouting
24
+ private
25
+
26
+ def combine_routes(app, doc_klass)
27
+ app.routes.each do |route|
28
+ route_path = route.path
29
+ route_match = route_path.split(/^.*?#{route.prefix}/).last
30
+ next unless route_match
31
+
32
+ # want to match emojis … ;)
33
+ # route_match = route_match
34
+ # .match('\/([\p{Alnum}p{Emoji}\-\_]*?)[\.\/\(]') || route_match.match('\/([\p{Alpha}\p{Emoji}\-\_]*)$')
35
+ route_match = route_match.match('\/([\p{Alnum}\-\_]*?)[\.\/\(]') || route_match.match('\/([\p{Alpha}\-\_]*)$')
36
+ next unless route_match
37
+
38
+ resource = route_match.captures.first
39
+ resource = '/' if resource.empty?
40
+ @target_class.combined_routes[resource] ||= []
41
+ next if doc_klass.hide_documentation_path && route.path.match(/#{doc_klass.mount_path}($|\/|\(\.)/)
42
+
43
+ @target_class.combined_routes[resource].unshift route
44
+ end
45
+ end
46
+
47
+ def determine_namespaced_routes(name, parent_route)
48
+ if parent_route.nil?
49
+ @target_class.combined_routes.values.flatten
50
+ else
51
+ parent_route.reject do |route|
52
+ !route_path_start_with?(route, name) || !route_instance_variable_equals?(route, name)
53
+ end
54
+ end
55
+ end
56
+
57
+ def combine_namespace_routes(namespaces)
58
+ # iterate over each single namespace
59
+ namespaces.each_key do |name, _|
60
+ # get the parent route for the namespace
61
+ parent_route_name = extract_parent_route(name)
62
+ parent_route = @target_class.combined_routes[parent_route_name]
63
+ # fetch all routes that are within the current namespace
64
+ namespace_routes = determine_namespaced_routes(name, parent_route)
65
+
66
+ # default case when not explicitly specified or nested == true
67
+ standalone_namespaces = namespaces.reject do |_, ns|
68
+ !ns.options.key?(:swagger) ||
69
+ !ns.options[:swagger].key?(:nested) ||
70
+ ns.options[:swagger][:nested] != false
71
+ end
72
+
73
+ parent_standalone_namespaces = standalone_namespaces.select { |ns_name, _| name.start_with?(ns_name) }
74
+ # add only to the main route
75
+ # if the namespace is not within any other namespace appearing as standalone resource
76
+ # rubocop:disable Style/Next
77
+ if parent_standalone_namespaces.empty?
78
+ # default option, append namespace methods to parent route
79
+ parent_route = @target_class.combined_namespace_routes.key?(parent_route_name)
80
+ @target_class.combined_namespace_routes[parent_route_name] = [] unless parent_route
81
+ @target_class.combined_namespace_routes[parent_route_name].push(*namespace_routes)
82
+ end
83
+ # rubocop:enable Style/Next
84
+ end
85
+ end
86
+
87
+ def extract_parent_route(name)
88
+ route_name = name.match(%r{^/?([^/]*).*$})[1]
89
+ return route_name unless route_name.include? ':'
90
+
91
+ matches = name.match(/\/\p{Alpha}+/)
92
+ matches.nil? ? route_name : matches[0].delete('/')
93
+ end
94
+
95
+ def route_instance_variable(route)
96
+ route.instance_variable_get(:@options)[:namespace]
97
+ end
98
+
99
+ def route_instance_variable_equals?(route, name)
100
+ route_instance_variable(route) == "/#{name}" ||
101
+ route_instance_variable(route) == "/:version/#{name}"
102
+ end
103
+
104
+ def route_path_start_with?(route, name)
105
+ route_prefix = route.prefix ? "/#{route.prefix}/#{name}" : "/#{name}"
106
+ route_versioned_prefix = route.prefix ? "/#{route.prefix}/:version/#{name}" : "/:version/#{name}"
107
+
108
+ route.path.start_with?(route_prefix, route_versioned_prefix)
109
+ end
110
+ end
111
+
112
+ module SwaggerDocumentationAdder
113
+ attr_accessor :combined_namespaces, :combined_namespace_identifiers, :combined_routes, :combined_namespace_routes
114
+
115
+ include SwaggerRouting
116
+
117
+ def add_swagger_documentation(options = {})
118
+ documentation_class = create_documentation_class
119
+
120
+ version_for(options)
121
+ options = { target_class: self }.merge(options)
122
+ @target_class = options[:target_class]
123
+ auth_wrapper = options[:endpoint_auth_wrapper] || Class.new
124
+
125
+ use auth_wrapper if auth_wrapper.method_defined?(:before) && !middleware.flatten.include?(auth_wrapper)
126
+
127
+ documentation_class.setup(options)
128
+ mount(documentation_class)
129
+
130
+ @target_class.combined_routes = {}
131
+ combine_routes(@target_class, documentation_class)
132
+
133
+ @target_class.combined_namespaces = {}
134
+ combine_namespaces(@target_class)
135
+
136
+ @target_class.combined_namespace_routes = {}
137
+ @target_class.combined_namespace_identifiers = {}
138
+ combine_namespace_routes(@target_class.combined_namespaces)
139
+
140
+ exclusive_route_keys = @target_class.combined_routes.keys - @target_class.combined_namespaces.keys
141
+ exclusive_route_keys.each do |key|
142
+ @target_class.combined_namespace_routes[key] = @target_class.combined_routes[key]
143
+ end
144
+ documentation_class
145
+ end
146
+
147
+ private
148
+
149
+ def version_for(options)
150
+ options[:version] = version if version
151
+ end
152
+
153
+ def combine_namespaces(app)
154
+ app.endpoints.each do |endpoint|
155
+ ns = endpoint.namespace_stackable(:namespace).last
156
+
157
+ # use the full namespace here (not the latest level only)
158
+ # and strip leading slash
159
+ mount_path = (endpoint.namespace_stackable(:mount_path) || []).join('/')
160
+ full_namespace = (mount_path + endpoint.namespace).sub(/\/{2,}/, '/').sub(/^\//, '')
161
+ @target_class.combined_namespaces[full_namespace] = ns if ns
162
+
163
+ combine_namespaces(endpoint.options[:app]) if endpoint.options[:app]
164
+ end
165
+ end
166
+
167
+ def create_documentation_class
168
+ Class.new(GrapeInstance) do
169
+ extend GrapeSwagger::DocMethods
170
+ end
171
+ end
172
+ end
173
+
174
+ GrapeInstance.extend(SwaggerDocumentationAdder)
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'nested namespaces' do
6
+ let(:app) do
7
+ Class.new(Grape::API) do
8
+ route_param :root do
9
+ resources :apps do
10
+ route_param :app_id do
11
+ resource :build do
12
+ desc 'Builds an application'
13
+ post do
14
+ { name: 'Test' }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ add_swagger_documentation version: 'v1'
22
+ end
23
+ end
24
+
25
+ describe 'combined_namespace_routes' do
26
+ it 'parses root namespace properly' do
27
+ expect(app.combined_namespace_routes.keys).to include('apps')
28
+ end
29
+ end
30
+
31
+ describe '#extract_parent_route' do
32
+ it 'extracts parent for non-namespaced path properly' do
33
+ expect(app.send(:extract_parent_route, '/apps/:app_id/build')).to eq('apps')
34
+ end
35
+
36
+ it 'extracts parent for namespaced path properly' do
37
+ expect(app.send(:extract_parent_route, '/:root/apps/:app_id/build')).to eq('apps')
38
+ end
39
+ end
40
+
41
+ describe 'retrieves swagger-documentation on /swagger_doc' do
42
+ let(:route_name) { '{root}/apps/{app_id}/build' }
43
+
44
+ subject do
45
+ get '/swagger_doc.json'
46
+ JSON.parse(last_response.body)
47
+ end
48
+
49
+ context 'paths' do
50
+ specify do
51
+ expect(subject['paths'].keys).to include "/#{route_name}"
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'describing versions' do
6
+ describe 'nothings given' do
7
+ def app
8
+ Class.new(Grape::API) do
9
+ desc 'no versions given'
10
+ get '/nothings' do
11
+ { message: 'hello world …' }
12
+ end
13
+
14
+ add_swagger_documentation format: :json
15
+ end
16
+ end
17
+
18
+ subject do
19
+ get '/swagger_doc'
20
+ JSON.parse(last_response.body)
21
+ end
22
+
23
+ specify do
24
+ expect(subject['info']['version']).to eql '0.0.1'
25
+ expect(subject['paths'].keys.first).to eql '/nothings'
26
+ end
27
+ end
28
+
29
+ describe 'API version given' do
30
+ def app
31
+ Class.new(Grape::API) do
32
+ version 'v2', using: :path
33
+ desc 'api versions given'
34
+ get '/api_version' do
35
+ { message: 'hello world …' }
36
+ end
37
+
38
+ add_swagger_documentation format: :json
39
+ end
40
+ end
41
+
42
+ subject do
43
+ get '/v2/swagger_doc'
44
+ JSON.parse(last_response.body)
45
+ end
46
+
47
+ specify do
48
+ expect(subject['info']['version']).to eql '0.0.1'
49
+ expect(subject['paths'].keys.first).to eql '/v2/api_version'
50
+ end
51
+ end
52
+
53
+ describe 'DOC version given' do
54
+ def app
55
+ Class.new(Grape::API) do
56
+ desc 'doc versions given'
57
+ get '/doc_version' do
58
+ { message: 'hello world …' }
59
+ end
60
+
61
+ add_swagger_documentation doc_version: '0.1'
62
+ end
63
+ end
64
+
65
+ subject do
66
+ get '/swagger_doc'
67
+ JSON.parse(last_response.body)
68
+ end
69
+
70
+ specify do
71
+ expect(subject['info']['version']).to eql '0.1'
72
+ expect(subject['paths'].keys.first).to eql '/doc_version'
73
+ end
74
+ end
75
+
76
+ describe 'both versions given' do
77
+ def app
78
+ Class.new(Grape::API) do
79
+ version :v3, using: :path
80
+ desc 'both versions given'
81
+ get '/both_versions' do
82
+ { message: 'hello world …' }
83
+ end
84
+
85
+ add_swagger_documentation doc_version: '0.2'
86
+ end
87
+ end
88
+
89
+ subject do
90
+ get '/v3/swagger_doc'
91
+ JSON.parse(last_response.body)
92
+ end
93
+
94
+ specify do
95
+ expect(subject['info']['version']).to eql '0.2'
96
+ expect(subject['paths'].keys.first).to eql '/v3/both_versions'
97
+ end
98
+ end
99
+
100
+ describe 'try to override grape given version' do
101
+ def app
102
+ Class.new(Grape::API) do
103
+ version :v4, using: :path
104
+ desc 'overriding grape given version?'
105
+ get '/grape_version' do
106
+ { message: 'hello world …' }
107
+ end
108
+
109
+ add_swagger_documentation doc_version: '0.0.3',
110
+ version: 'v5'
111
+ end
112
+ end
113
+
114
+ subject do
115
+ get '/v4/swagger_doc'
116
+ JSON.parse(last_response.body)
117
+ end
118
+
119
+ specify do
120
+ expect(subject['info']['version']).to eql '0.0.3'
121
+ expect(subject['paths'].keys.first).to eql '/v4/grape_version'
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe '#427 nested entity given as string' do
6
+ let(:app) do
7
+ Class.new(Grape::API) do
8
+ namespace :issue_427 do
9
+ module Permission
10
+ class WithoutRole < Grape::Entity
11
+ expose :id
12
+ expose :description
13
+ end
14
+ end
15
+
16
+ class RoleEntity < Grape::Entity
17
+ expose :id
18
+ expose :description
19
+ expose :role
20
+ expose :permissions, using: 'Permission::WithoutRole'
21
+ end
22
+ desc 'Get a list of roles',
23
+ success: RoleEntity
24
+ get '/' do
25
+ present [], with: RoleEntity
26
+ end
27
+ end
28
+
29
+ add_swagger_documentation format: :json
30
+ end
31
+ end
32
+
33
+ subject do
34
+ get '/swagger_doc'
35
+ JSON.parse(last_response.body)['definitions']
36
+ end
37
+
38
+ specify { expect(subject.keys).to include 'RoleEntity', 'Permission_WithoutRole' }
39
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'definition names' do
6
+ before :all do
7
+ module TestDefinition
8
+ module DummyEntities
9
+ module WithVeryLongName
10
+ module AnotherGroupingModule
11
+ class Class1
12
+ class Entity < Grape::Entity
13
+ expose :first_thing
14
+ end
15
+ end
16
+
17
+ class Class2
18
+ class Entities < Grape::Entity
19
+ expose :second_thing
20
+ end
21
+ end
22
+
23
+ class Class3
24
+ class Entity < Grape::Entity
25
+ expose :third_thing
26
+
27
+ def self.entity_name
28
+ 'FooKlass'
29
+ end
30
+ end
31
+ end
32
+
33
+ class Class4
34
+ class FourthEntity < Grape::Entity
35
+ expose :fourth_thing
36
+ end
37
+ end
38
+
39
+ class Class5
40
+ class FithEntity < Class4::FourthEntity
41
+ expose :fith_thing
42
+ end
43
+ end
44
+
45
+ class Class6
46
+ class SixthEntity < Grape::Entity
47
+ expose :sixth_thing
48
+
49
+ def self.entity_name
50
+ 'BarKlass'
51
+ end
52
+ end
53
+ end
54
+
55
+ class Class7
56
+ class SeventhEntity < Class6::SixthEntity
57
+ expose :seventh_thing
58
+
59
+ private_class_method :entity_name
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ class NameApi < Grape::API
67
+ add_swagger_documentation models: [
68
+ DummyEntities::WithVeryLongName::AnotherGroupingModule::Class1::Entity,
69
+ DummyEntities::WithVeryLongName::AnotherGroupingModule::Class2::Entities,
70
+ DummyEntities::WithVeryLongName::AnotherGroupingModule::Class3::Entity,
71
+ DummyEntities::WithVeryLongName::AnotherGroupingModule::Class4::FourthEntity,
72
+ DummyEntities::WithVeryLongName::AnotherGroupingModule::Class5::FithEntity,
73
+ DummyEntities::WithVeryLongName::AnotherGroupingModule::Class6::SixthEntity,
74
+ DummyEntities::WithVeryLongName::AnotherGroupingModule::Class7::SeventhEntity
75
+ ]
76
+ end
77
+ end
78
+ end
79
+
80
+ let(:app) { TestDefinition::NameApi }
81
+
82
+ subject do
83
+ get '/swagger_doc'
84
+ JSON.parse(last_response.body)['definitions']
85
+ end
86
+
87
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class1' }
88
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class2' }
89
+ specify { expect(subject).to include 'FooKlass' }
90
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class4_FourthEntity' }
91
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class5_FithEntity' }
92
+ specify { expect(subject).to include 'BarKlass' }
93
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class7_SeventhEntity' }
94
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe '#532 allow custom format' do
6
+ let(:app) do
7
+ Class.new(Grape::API) do
8
+ namespace :issue_532 do
9
+ desc 'issue_532' do
10
+ consumes ['application/x-www-form-urlencoded']
11
+ end
12
+
13
+ params do
14
+ requires :logs, type: String, documentation: { format: 'log' }
15
+ optional :phone_number, type: Integer, documentation: { format: 'phone_number' }
16
+ end
17
+
18
+ post do
19
+ present params
20
+ end
21
+ end
22
+
23
+ add_swagger_documentation format: :json
24
+ end
25
+ end
26
+
27
+ subject do
28
+ get '/swagger_doc'
29
+ JSON.parse(last_response.body)
30
+ end
31
+
32
+ let(:parameters) { subject['paths']['/issue_532']['post']['parameters'] }
33
+
34
+ specify do
35
+ expect(parameters).to eql(
36
+ [
37
+ { 'in' => 'formData', 'name' => 'logs', 'type' => 'string', 'format' => 'log', 'required' => true },
38
+ { 'in' => 'formData', 'name' => 'phone_number', 'type' => 'integer', 'format' => 'phone_number', 'required' => false }
39
+ ]
40
+ )
41
+ end
42
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe '#533 specify status codes' do
6
+ include_context "#{MODEL_PARSER} swagger example"
7
+
8
+ let(:app) do
9
+ Class.new(Grape::API) do
10
+ namespace :issue_533 do
11
+ desc 'Get a list of stuff',
12
+ success: { code: 202, model: Entities::UseResponse, message: 'a changed status code' }
13
+ get do
14
+ status 202
15
+ { foo: 'that is the response' }
16
+ end
17
+
18
+ desc 'Post some stuff',
19
+ success: { code: 202, model: Entities::UseResponse, message: 'a changed status code' }
20
+ post do
21
+ status 202
22
+ { foo: 'that is the response' }
23
+ end
24
+
25
+ desc 'Post some stuff',
26
+ success: { code: 204, message: 'a changed status code' }
27
+ patch do
28
+ status 204
29
+ end
30
+
31
+ desc 'Delete some stuff',
32
+ success: { code: 203 }
33
+ delete do
34
+ status 203
35
+ end
36
+ end
37
+
38
+ add_swagger_documentation format: :json
39
+ end
40
+ end
41
+
42
+ subject do
43
+ get '/swagger_doc'
44
+ JSON.parse(last_response.body)['paths']['/issue_533']
45
+ end
46
+
47
+ let(:get_response) { get '/issue_533' }
48
+ specify { expect(get_response.status).to eql 202 }
49
+ let(:get_response_documentation) { subject['get']['responses'] }
50
+ specify do
51
+ expect(get_response_documentation.keys.first).to eql '202'
52
+ expect(get_response_documentation['202']).to include 'schema'
53
+ end
54
+
55
+ let(:post_response) { post '/issue_533' }
56
+ specify { expect(post_response.status).to eql 202 }
57
+ let(:post_response_documentation) { subject['post']['responses'] }
58
+ specify do
59
+ expect(post_response_documentation.keys.first).to eql '202'
60
+ expect(post_response_documentation['202']).to include 'schema'
61
+ end
62
+
63
+ let(:patch_response) { patch '/issue_533' }
64
+ specify { expect(patch_response.status).to eql 204 }
65
+ let(:patch_response_documentation) { subject['patch']['responses'] }
66
+ specify do
67
+ expect(patch_response_documentation.keys.first).to eql '204'
68
+ expect(patch_response_documentation['204']).not_to include 'schema'
69
+ end
70
+
71
+ let(:delete_response) { delete '/issue_533' }
72
+ specify { expect(delete_response.status).to eql 203 }
73
+ let(:delete_response_documentation) { subject['delete']['responses'] }
74
+ specify do
75
+ expect(delete_response_documentation.keys.first).to eql '203'
76
+ expect(delete_response_documentation['203']).not_to include 'schema'
77
+ end
78
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe '#537 enum values spec' do
6
+ let(:app) do
7
+ Class.new(Grape::API) do
8
+ namespace :issue_537 do
9
+ class Spec < Grape::Entity
10
+ expose :enum_property, documentation: { values: %i[foo bar] }
11
+ expose :enum_property_default, documentation: { values: %w[a b c], default: 'c' }
12
+ expose :own_format, documentation: { format: 'log' }
13
+ end
14
+
15
+ desc 'create account',
16
+ success: Spec
17
+ get do
18
+ { message: 'hi' }
19
+ end
20
+ end
21
+
22
+ add_swagger_documentation format: :json
23
+ end
24
+ end
25
+
26
+ subject do
27
+ get '/swagger_doc'
28
+ JSON.parse(last_response.body)
29
+ end
30
+
31
+ let(:property) { subject['definitions']['Spec']['properties']['enum_property'] }
32
+ specify do
33
+ expect(property).to include 'enum'
34
+ expect(property['enum']).to eql %w[foo bar]
35
+ end
36
+
37
+ let(:property_default) { subject['definitions']['Spec']['properties']['enum_property_default'] }
38
+ specify do
39
+ expect(property_default).to include 'enum'
40
+ expect(property_default['enum']).to eql %w[a b c]
41
+ expect(property_default).to include 'default'
42
+ expect(property_default['default']).to eql 'c'
43
+ end
44
+
45
+ let(:own_format) { subject['definitions']['Spec']['properties']['own_format'] }
46
+ specify do
47
+ expect(own_format).to include 'format'
48
+ expect(own_format['format']).to eql 'log'
49
+ end
50
+ end