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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.github/dependabot.yml +20 -0
- data/.github/workflows/ci.yml +45 -0
- data/.gitignore +44 -0
- data/.gitlab-ci.yml +19 -0
- data/.rspec +3 -0
- data/.rubocop.yml +136 -0
- data/.rubocop_todo.yml +60 -0
- data/.ruby-gemset +1 -0
- data/CHANGELOG.md +671 -0
- data/CONTRIBUTING.md +126 -0
- data/Dangerfile +3 -0
- data/Gemfile +45 -0
- data/Gemfile.lock +249 -0
- data/LICENSE.txt +20 -0
- data/README.md +1772 -0
- data/RELEASING.md +82 -0
- data/Rakefile +20 -0
- data/UPGRADING.md +201 -0
- data/example/api/endpoints.rb +131 -0
- data/example/api/entities.rb +18 -0
- data/example/config.ru +42 -0
- data/example/example_requests.postman_collection +146 -0
- data/example/splines.png +0 -0
- data/example/swagger-example.png +0 -0
- data/grape-swagger.gemspec +23 -0
- data/lib/grape-swagger/doc_methods/build_model_definition.rb +68 -0
- data/lib/grape-swagger/doc_methods/data_type.rb +110 -0
- data/lib/grape-swagger/doc_methods/extensions.rb +101 -0
- data/lib/grape-swagger/doc_methods/file_params.rb +17 -0
- data/lib/grape-swagger/doc_methods/format_data.rb +53 -0
- data/lib/grape-swagger/doc_methods/headers.rb +20 -0
- data/lib/grape-swagger/doc_methods/move_params.rb +209 -0
- data/lib/grape-swagger/doc_methods/operation_id.rb +32 -0
- data/lib/grape-swagger/doc_methods/optional_object.rb +30 -0
- data/lib/grape-swagger/doc_methods/parse_params.rb +190 -0
- data/lib/grape-swagger/doc_methods/path_string.rb +52 -0
- data/lib/grape-swagger/doc_methods/produces_consumes.rb +15 -0
- data/lib/grape-swagger/doc_methods/status_codes.rb +21 -0
- data/lib/grape-swagger/doc_methods/tag_name_description.rb +34 -0
- data/lib/grape-swagger/doc_methods/version.rb +20 -0
- data/lib/grape-swagger/doc_methods.rb +142 -0
- data/lib/grape-swagger/endpoint/params_parser.rb +76 -0
- data/lib/grape-swagger/endpoint.rb +476 -0
- data/lib/grape-swagger/errors.rb +17 -0
- data/lib/grape-swagger/instance.rb +7 -0
- data/lib/grape-swagger/model_parsers.rb +42 -0
- data/lib/grape-swagger/rake/oapi_tasks.rb +135 -0
- data/lib/grape-swagger/version.rb +5 -0
- data/lib/grape-swagger.rb +174 -0
- data/spec/issues/267_nested_namespaces.rb +55 -0
- data/spec/issues/403_versions_spec.rb +124 -0
- data/spec/issues/427_entity_as_string_spec.rb +39 -0
- data/spec/issues/430_entity_definitions_spec.rb +94 -0
- data/spec/issues/532_allow_custom_format_spec.rb +42 -0
- data/spec/issues/533_specify_status_code_spec.rb +78 -0
- data/spec/issues/537_enum_values_spec.rb +50 -0
- data/spec/issues/539_array_post_body_spec.rb +65 -0
- data/spec/issues/542_array_of_type_in_post_body_spec.rb +46 -0
- data/spec/issues/553_align_array_put_post_params_spec.rb +152 -0
- data/spec/issues/572_array_post_body_spec.rb +51 -0
- data/spec/issues/579_align_put_post_parameters_spec.rb +185 -0
- data/spec/issues/582_file_response_spec.rb +55 -0
- data/spec/issues/587_range_parameter_delimited_by_dash_spec.rb +26 -0
- data/spec/issues/605_root_route_documentation_spec.rb +23 -0
- data/spec/issues/650_params_array_spec.rb +65 -0
- data/spec/issues/677_consumes_produces_add_swagger_documentation_options_spec.rb +100 -0
- data/spec/issues/680_keep_204_error_schemas_spec.rb +55 -0
- data/spec/issues/721_set_default_parameter_location_based_on_consumes_spec.rb +62 -0
- data/spec/issues/751_deeply_nested_objects_spec.rb +190 -0
- data/spec/issues/776_multiple_presents_spec.rb +59 -0
- data/spec/issues/784_extensions_on_params_spec.rb +42 -0
- data/spec/issues/809_utf8_routes_spec.rb +55 -0
- data/spec/issues/832_array_hash_float_decimal_spec.rb +114 -0
- data/spec/issues/847_route_param_options_spec.rb +37 -0
- data/spec/issues/873_wildcard_segments_path_parameters_spec.rb +28 -0
- data/spec/issues/878_optional_path_segments_spec.rb +29 -0
- data/spec/issues/881_handle_file_params_spec.rb +38 -0
- data/spec/issues/883_query_array_parameter_spec.rb +46 -0
- data/spec/issues/884_dont_document_non_schema_examples_spec.rb +49 -0
- data/spec/issues/887_prevent_duplicate_operation_ids_spec.rb +35 -0
- data/spec/lib/data_type_spec.rb +111 -0
- data/spec/lib/endpoint/params_parser_spec.rb +124 -0
- data/spec/lib/endpoint_spec.rb +153 -0
- data/spec/lib/extensions_spec.rb +185 -0
- data/spec/lib/format_data_spec.rb +115 -0
- data/spec/lib/model_parsers_spec.rb +104 -0
- data/spec/lib/move_params_spec.rb +444 -0
- data/spec/lib/oapi_tasks_spec.rb +163 -0
- data/spec/lib/operation_id_spec.rb +55 -0
- data/spec/lib/optional_object_spec.rb +47 -0
- data/spec/lib/parse_params_spec.rb +68 -0
- data/spec/lib/path_string_spec.rb +101 -0
- data/spec/lib/produces_consumes_spec.rb +116 -0
- data/spec/lib/tag_name_description_spec.rb +80 -0
- data/spec/lib/version_spec.rb +28 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/empty_model_parser.rb +23 -0
- data/spec/support/grape_version.rb +13 -0
- data/spec/support/mock_parser.rb +23 -0
- data/spec/support/model_parsers/entity_parser.rb +334 -0
- data/spec/support/model_parsers/mock_parser.rb +346 -0
- data/spec/support/model_parsers/representable_parser.rb +406 -0
- data/spec/support/namespace_tags.rb +93 -0
- data/spec/support/the_paths_definitions.rb +109 -0
- data/spec/swagger_v2/api_documentation_spec.rb +42 -0
- data/spec/swagger_v2/api_swagger_v2_additional_properties_spec.rb +83 -0
- data/spec/swagger_v2/api_swagger_v2_body_definitions_spec.rb +48 -0
- data/spec/swagger_v2/api_swagger_v2_definitions-models_spec.rb +36 -0
- data/spec/swagger_v2/api_swagger_v2_detail_spec.rb +79 -0
- data/spec/swagger_v2/api_swagger_v2_extensions_spec.rb +145 -0
- data/spec/swagger_v2/api_swagger_v2_format-content_type_spec.rb +137 -0
- data/spec/swagger_v2/api_swagger_v2_global_configuration_spec.rb +56 -0
- data/spec/swagger_v2/api_swagger_v2_hash_and_array_spec.rb +64 -0
- data/spec/swagger_v2/api_swagger_v2_headers_spec.rb +58 -0
- data/spec/swagger_v2/api_swagger_v2_hide_documentation_path_spec.rb +57 -0
- data/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb +109 -0
- data/spec/swagger_v2/api_swagger_v2_ignore_defaults_spec.rb +48 -0
- data/spec/swagger_v2/api_swagger_v2_mounted_spec.rb +153 -0
- data/spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb +355 -0
- data/spec/swagger_v2/api_swagger_v2_param_type_body_spec.rb +217 -0
- data/spec/swagger_v2/api_swagger_v2_param_type_spec.rb +247 -0
- data/spec/swagger_v2/api_swagger_v2_request_params_fix_spec.rb +80 -0
- data/spec/swagger_v2/api_swagger_v2_response_spec.rb +147 -0
- data/spec/swagger_v2/api_swagger_v2_response_with_examples_spec.rb +135 -0
- data/spec/swagger_v2/api_swagger_v2_response_with_headers_spec.rb +216 -0
- data/spec/swagger_v2/api_swagger_v2_response_with_models_spec.rb +53 -0
- data/spec/swagger_v2/api_swagger_v2_response_with_root_spec.rb +153 -0
- data/spec/swagger_v2/api_swagger_v2_spec.rb +245 -0
- data/spec/swagger_v2/api_swagger_v2_status_codes_spec.rb +93 -0
- data/spec/swagger_v2/api_swagger_v2_type-format_spec.rb +90 -0
- data/spec/swagger_v2/boolean_params_spec.rb +38 -0
- data/spec/swagger_v2/default_api_spec.rb +175 -0
- data/spec/swagger_v2/deprecated_field_spec.rb +25 -0
- data/spec/swagger_v2/description_not_initialized_spec.rb +39 -0
- data/spec/swagger_v2/endpoint_versioned_path_spec.rb +130 -0
- data/spec/swagger_v2/errors_spec.rb +77 -0
- data/spec/swagger_v2/float_api_spec.rb +36 -0
- data/spec/swagger_v2/form_params_spec.rb +76 -0
- data/spec/swagger_v2/grape-swagger_spec.rb +17 -0
- data/spec/swagger_v2/guarded_endpoint_spec.rb +162 -0
- data/spec/swagger_v2/hide_api_spec.rb +147 -0
- data/spec/swagger_v2/host_spec.rb +43 -0
- data/spec/swagger_v2/inheritance_and_discriminator_spec.rb +57 -0
- data/spec/swagger_v2/mount_override_api_spec.rb +58 -0
- data/spec/swagger_v2/mounted_target_class_spec.rb +76 -0
- data/spec/swagger_v2/namespace_tags_prefix_spec.rb +122 -0
- data/spec/swagger_v2/namespace_tags_spec.rb +78 -0
- data/spec/swagger_v2/namespaced_api_spec.rb +121 -0
- data/spec/swagger_v2/nicknamed_api_spec.rb +25 -0
- data/spec/swagger_v2/operation_id_api_spec.rb +27 -0
- data/spec/swagger_v2/param_multi_type_spec.rb +82 -0
- data/spec/swagger_v2/param_type_spec.rb +95 -0
- data/spec/swagger_v2/param_values_spec.rb +180 -0
- data/spec/swagger_v2/params_array_collection_format_spec.rb +105 -0
- data/spec/swagger_v2/params_array_spec.rb +225 -0
- data/spec/swagger_v2/params_example_spec.rb +38 -0
- data/spec/swagger_v2/params_hash_spec.rb +77 -0
- data/spec/swagger_v2/params_nested_spec.rb +92 -0
- data/spec/swagger_v2/parent_less_namespace_spec.rb +32 -0
- data/spec/swagger_v2/reference_entity_spec.rb +129 -0
- data/spec/swagger_v2/security_requirement_spec.rb +46 -0
- data/spec/swagger_v2/simple_mounted_api_spec.rb +332 -0
- data/spec/version_spec.rb +10 -0
- metadata +225 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'http status code behaviours' do
|
|
6
|
+
include_context "#{MODEL_PARSER} swagger example"
|
|
7
|
+
|
|
8
|
+
subject do
|
|
9
|
+
get '/swagger_doc'
|
|
10
|
+
JSON.parse(last_response.body)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context 'when non-default success codes are defined' do
|
|
14
|
+
let(:app) do
|
|
15
|
+
Class.new(Grape::API) do
|
|
16
|
+
desc 'Has explicit success http_codes defined' do
|
|
17
|
+
http_codes [{ code: 202, message: 'We got it!' },
|
|
18
|
+
{ code: 204, message: 'Or returned no content' },
|
|
19
|
+
{ code: 400, message: 'Bad request' }]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
post '/accepting_endpoint' do
|
|
23
|
+
'We got the message!'
|
|
24
|
+
end
|
|
25
|
+
add_swagger_documentation
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'only includes the defined http_codes' do
|
|
30
|
+
expect(subject['paths']['/accepting_endpoint']['post']['responses'].keys.sort).to eq(%w[202 204 400].sort)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context 'when success and failures are defined' do
|
|
35
|
+
let(:app) do
|
|
36
|
+
Class.new(Grape::API) do
|
|
37
|
+
desc 'Has explicit success http_codes defined' do
|
|
38
|
+
success code: 202, model: Entities::UseResponse, message: 'a changed status code'
|
|
39
|
+
failure [[400, 'Bad Request']]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
post '/accepting_endpoint' do
|
|
43
|
+
'We got the message!'
|
|
44
|
+
end
|
|
45
|
+
add_swagger_documentation
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'only includes the defined http codes' do
|
|
50
|
+
expect(subject['paths']['/accepting_endpoint']['post']['responses'].keys.sort).to eq(%w[202 400].sort)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'when no success codes defined' do
|
|
55
|
+
let(:app) do
|
|
56
|
+
Class.new(Grape::API) do
|
|
57
|
+
desc 'Has explicit error http_codes defined' do
|
|
58
|
+
http_codes [{ code: 400, message: 'Error!' },
|
|
59
|
+
{ code: 404, message: 'Not found' }]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
post '/error_endpoint' do
|
|
63
|
+
'We got the message!'
|
|
64
|
+
end
|
|
65
|
+
add_swagger_documentation
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'adds the success codes to the response' do
|
|
70
|
+
expect(subject['paths']['/error_endpoint']['post']['responses'].keys.sort).to eq(%w[201 400 404].sort)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context 'when success and error codes are defined' do
|
|
75
|
+
let(:app) do
|
|
76
|
+
Class.new(Grape::API) do
|
|
77
|
+
desc 'Has success and error codes defined' do
|
|
78
|
+
http_codes [{ code: 200, message: 'Found' },
|
|
79
|
+
{ code: 404, message: 'Not found' }]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
get '/endpoint' do
|
|
83
|
+
'We got the message!'
|
|
84
|
+
end
|
|
85
|
+
add_swagger_documentation
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'adds the success codes and error codes to the response' do
|
|
90
|
+
expect(subject['paths']['/endpoint']['get']['responses'].keys.sort).to eq(%w[200 404].sort)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
# mapping of parameter types
|
|
6
|
+
# Grape -> Swagger (OpenApi)
|
|
7
|
+
# (type format)
|
|
8
|
+
# ---------------------------------------------------
|
|
9
|
+
# Integer -> integer int32
|
|
10
|
+
# Numeric -> integer int64
|
|
11
|
+
# Float -> number float
|
|
12
|
+
# BigDecimal -> number double
|
|
13
|
+
# String -> string
|
|
14
|
+
# Symbol -> string
|
|
15
|
+
# Date -> string date
|
|
16
|
+
# DateTime -> string date-time
|
|
17
|
+
# Time -> string date-time
|
|
18
|
+
# 'password' -> string password
|
|
19
|
+
# 'email' -> string email
|
|
20
|
+
# Boolean -> boolean
|
|
21
|
+
# JSON -> json
|
|
22
|
+
# Rack::Multipart::UploadedFile -> file
|
|
23
|
+
|
|
24
|
+
describe 'type format settings' do
|
|
25
|
+
include_context "#{MODEL_PARSER} swagger example"
|
|
26
|
+
|
|
27
|
+
before :all do
|
|
28
|
+
module TheApi
|
|
29
|
+
class TypeFormatApi < Grape::API
|
|
30
|
+
desc 'full set of request data types',
|
|
31
|
+
consumes: ['application/x-www-form-urlencoded'],
|
|
32
|
+
success: Entities::TypedDefinition
|
|
33
|
+
|
|
34
|
+
params do
|
|
35
|
+
# grape supported data types
|
|
36
|
+
requires :param_integer, type: Integer
|
|
37
|
+
requires :param_long, type: Numeric
|
|
38
|
+
requires :param_float, type: Float
|
|
39
|
+
requires :param_double, type: BigDecimal
|
|
40
|
+
optional :param_string, type: String
|
|
41
|
+
optional :param_symbol, type: Symbol
|
|
42
|
+
requires :param_date, type: Date
|
|
43
|
+
requires :param_date_time, type: DateTime
|
|
44
|
+
requires :param_time, type: Time
|
|
45
|
+
optional :param_boolean, type: Boolean
|
|
46
|
+
optional :param_file, type: File
|
|
47
|
+
optional :param_json, type: JSON
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
post '/request_types' do
|
|
51
|
+
{ 'declared_params' => declared(params) }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
add_swagger_documentation
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def app
|
|
60
|
+
TheApi::TypeFormatApi
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
subject do
|
|
64
|
+
get '/swagger_doc/request_types'
|
|
65
|
+
JSON.parse(last_response.body)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
specify do
|
|
69
|
+
expect(subject['paths']['/request_types']['post']['parameters']).to eql(
|
|
70
|
+
[
|
|
71
|
+
{ 'in' => 'formData', 'name' => 'param_integer', 'required' => true, 'type' => 'integer', 'format' => 'int32' },
|
|
72
|
+
{ 'in' => 'formData', 'name' => 'param_long', 'required' => true, 'type' => 'integer', 'format' => 'int64' },
|
|
73
|
+
{ 'in' => 'formData', 'name' => 'param_float', 'required' => true, 'type' => 'number', 'format' => 'float' },
|
|
74
|
+
{ 'in' => 'formData', 'name' => 'param_double', 'required' => true, 'type' => 'number', 'format' => 'double' },
|
|
75
|
+
{ 'in' => 'formData', 'name' => 'param_string', 'required' => false, 'type' => 'string' },
|
|
76
|
+
{ 'in' => 'formData', 'name' => 'param_symbol', 'required' => false, 'type' => 'string' },
|
|
77
|
+
{ 'in' => 'formData', 'name' => 'param_date', 'required' => true, 'type' => 'string', 'format' => 'date' },
|
|
78
|
+
{ 'in' => 'formData', 'name' => 'param_date_time', 'required' => true, 'type' => 'string', 'format' => 'date-time' },
|
|
79
|
+
{ 'in' => 'formData', 'name' => 'param_time', 'required' => true, 'type' => 'string', 'format' => 'date-time' },
|
|
80
|
+
{ 'in' => 'formData', 'name' => 'param_boolean', 'required' => false, 'type' => 'boolean' },
|
|
81
|
+
{ 'in' => 'formData', 'name' => 'param_file', 'required' => false, 'type' => 'file' },
|
|
82
|
+
{ 'in' => 'formData', 'name' => 'param_json', 'required' => false, 'type' => 'json' }
|
|
83
|
+
]
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
specify do
|
|
88
|
+
expect(subject['definitions']['TypedDefinition']['properties']).to eql(swagger_typed_defintion)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'Boolean 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_boolean, type: Grape::API::Boolean
|
|
15
|
+
optional :another_boolean, type: Grape::API::Boolean, default: false
|
|
16
|
+
end
|
|
17
|
+
post :splines do
|
|
18
|
+
{ message: 'hi' }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
add_swagger_documentation
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
subject do
|
|
26
|
+
get '/swagger_doc/splines'
|
|
27
|
+
expect(last_response.status).to eq 200
|
|
28
|
+
body = JSON.parse last_response.body
|
|
29
|
+
body['paths']['/splines']['post']['parameters']
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'converts boolean types' do
|
|
33
|
+
expect(subject).to eq [
|
|
34
|
+
{ 'in' => 'formData', 'name' => 'a_boolean', 'type' => 'boolean', 'required' => true },
|
|
35
|
+
{ 'in' => 'formData', 'name' => 'another_boolean', 'type' => 'boolean', 'required' => false, 'default' => false }
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
# require 'grape_version'
|
|
5
|
+
|
|
6
|
+
describe 'Default API' do
|
|
7
|
+
context 'with no additional options' do
|
|
8
|
+
def app
|
|
9
|
+
Class.new(Grape::API) do
|
|
10
|
+
format :json
|
|
11
|
+
desc 'This gets something.'
|
|
12
|
+
get '/something' do
|
|
13
|
+
{ bla: 'something' }
|
|
14
|
+
end
|
|
15
|
+
add_swagger_documentation
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
subject do
|
|
20
|
+
get '/swagger_doc'
|
|
21
|
+
JSON.parse(last_response.body)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'documents api' do
|
|
25
|
+
expect(subject).to eq(
|
|
26
|
+
'info' => { 'title' => 'API title', 'version' => '0.0.1' },
|
|
27
|
+
'swagger' => '2.0',
|
|
28
|
+
'produces' => ['application/json'],
|
|
29
|
+
'host' => 'example.org',
|
|
30
|
+
'tags' => [{ 'name' => 'something', 'description' => 'Operations about somethings' }],
|
|
31
|
+
'paths' => {
|
|
32
|
+
'/something' => {
|
|
33
|
+
'get' => {
|
|
34
|
+
'description' => 'This gets something.',
|
|
35
|
+
'produces' => ['application/json'],
|
|
36
|
+
'tags' => ['something'],
|
|
37
|
+
'operationId' => 'getSomething',
|
|
38
|
+
'responses' => { '200' => { 'description' => 'This gets something.' } }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context 'path inside the apis array' do
|
|
46
|
+
it 'starts with a forward slash' do
|
|
47
|
+
subject['paths'].each do |path|
|
|
48
|
+
expect(path.first).to start_with '/'
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'with additional option block given to desc', if: GrapeVersion.satisfy?('>= 0.12.0') do
|
|
55
|
+
def app
|
|
56
|
+
Class.new(Grape::API) do
|
|
57
|
+
format :json
|
|
58
|
+
desc 'This gets something.'
|
|
59
|
+
get '/something' do
|
|
60
|
+
{ bla: 'something' }
|
|
61
|
+
end
|
|
62
|
+
add_swagger_documentation
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
subject do
|
|
67
|
+
get '/swagger_doc/something'
|
|
68
|
+
JSON.parse(last_response.body)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'documents endpoint' do
|
|
72
|
+
expect(subject).to eq('info' => { 'title' => 'API title', 'version' => '0.0.1' },
|
|
73
|
+
'swagger' => '2.0',
|
|
74
|
+
'produces' => ['application/json'],
|
|
75
|
+
'host' => 'example.org',
|
|
76
|
+
'tags' => [{ 'name' => 'something', 'description' => 'Operations about somethings' }],
|
|
77
|
+
'paths' => {
|
|
78
|
+
'/something' => {
|
|
79
|
+
'get' => {
|
|
80
|
+
'description' => 'This gets something.',
|
|
81
|
+
'produces' => ['application/json'],
|
|
82
|
+
'tags' => ['something'],
|
|
83
|
+
'operationId' => 'getSomething',
|
|
84
|
+
'responses' => { '200' => { 'description' => 'This gets something.' } }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context 'with additional info' do
|
|
92
|
+
def app
|
|
93
|
+
Class.new(Grape::API) do
|
|
94
|
+
format :json
|
|
95
|
+
add_swagger_documentation info: {
|
|
96
|
+
title: 'My API Title',
|
|
97
|
+
description: 'A description of my API',
|
|
98
|
+
license: 'Apache 2',
|
|
99
|
+
license_url: 'http://test.com',
|
|
100
|
+
terms_of_service_url: 'http://terms.com',
|
|
101
|
+
contact_email: 'support@test.com',
|
|
102
|
+
x: {
|
|
103
|
+
logo: 'http://logo.com/img.png'
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
subject do
|
|
110
|
+
get '/swagger_doc'
|
|
111
|
+
JSON.parse(last_response.body)['info']
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'documents API title' do
|
|
115
|
+
expect(subject['title']).to eql('My API Title')
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'documents API description' do
|
|
119
|
+
expect(subject['description']).to eql('A description of my API')
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'should document the license' do
|
|
123
|
+
expect(subject['license']['name']).to eql('Apache 2')
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'documents the license url' do
|
|
127
|
+
expect(subject['license']['url']).to eql('http://test.com')
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'documents the terms of service url' do
|
|
131
|
+
expect(subject['termsOfService']).to eql('http://terms.com')
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'documents the contact email' do
|
|
135
|
+
expect(subject['contact']['email']).to eql('support@test.com')
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'documents the extension field' do
|
|
139
|
+
expect(subject['x-logo']).to eql('http://logo.com/img.png')
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context 'with tags' do
|
|
144
|
+
def app
|
|
145
|
+
Class.new(Grape::API) do
|
|
146
|
+
format :json
|
|
147
|
+
desc 'This gets something.'
|
|
148
|
+
get '/something' do
|
|
149
|
+
{ bla: 'something' }
|
|
150
|
+
end
|
|
151
|
+
get '/somethingelse' do
|
|
152
|
+
{ bla: 'somethingelse' }
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
add_swagger_documentation tags: [
|
|
156
|
+
{ name: 'something', description: 'customized description' }
|
|
157
|
+
]
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
subject do
|
|
162
|
+
get '/swagger_doc'
|
|
163
|
+
JSON.parse(last_response.body)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'documents the customized tag' do
|
|
167
|
+
expect(subject['tags']).to eql(
|
|
168
|
+
[
|
|
169
|
+
{ 'name' => 'somethingelse', 'description' => 'Operations about somethingelses' },
|
|
170
|
+
{ 'name' => 'something', 'description' => 'customized description' }
|
|
171
|
+
]
|
|
172
|
+
)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'deprecated endpoint' do
|
|
6
|
+
def app
|
|
7
|
+
Class.new(Grape::API) do
|
|
8
|
+
desc 'Deprecated endpoint', deprecated: true
|
|
9
|
+
get '/foobar' do
|
|
10
|
+
{ foo: 'bar' }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
add_swagger_documentation
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
subject do
|
|
18
|
+
get '/swagger_doc.json'
|
|
19
|
+
JSON.parse(last_response.body)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'includes the deprecated field' do
|
|
23
|
+
expect(subject['paths']['/foobar']['get']['deprecated']).to eql(true)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'has no description, if details or description are nil' do
|
|
6
|
+
include_context "#{MODEL_PARSER} swagger example"
|
|
7
|
+
|
|
8
|
+
before :all do
|
|
9
|
+
module TheApi
|
|
10
|
+
class GfmRcDetailApi < Grape::API
|
|
11
|
+
format :json
|
|
12
|
+
|
|
13
|
+
desc nil,
|
|
14
|
+
detail: nil,
|
|
15
|
+
entity: Entities::UseResponse,
|
|
16
|
+
failure: [{ code: 400, model: Entities::ApiError }]
|
|
17
|
+
get '/use_gfm_rc_detail' do
|
|
18
|
+
{ 'declared_params' => declared(params) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
add_swagger_documentation
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def app
|
|
27
|
+
TheApi::GfmRcDetailApi
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
subject do
|
|
31
|
+
get '/swagger_doc'
|
|
32
|
+
JSON.parse(last_response.body)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
specify do
|
|
36
|
+
expect(subject['paths']['/use_gfm_rc_detail']['get']).not_to include('description')
|
|
37
|
+
expect(subject['paths']['/use_gfm_rc_detail']['get']['description']).to eql(nil)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'Grape::Endpoint#path_and_definitions' do
|
|
6
|
+
context 'when mounting an API once' do
|
|
7
|
+
let(:item) do
|
|
8
|
+
Class.new(Grape::API) do
|
|
9
|
+
version 'v1', using: :path
|
|
10
|
+
|
|
11
|
+
resource :item do
|
|
12
|
+
get '/'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
let(:api) do
|
|
18
|
+
item_api = item
|
|
19
|
+
|
|
20
|
+
Class.new(Grape::API) do
|
|
21
|
+
mount item_api
|
|
22
|
+
add_swagger_documentation add_version: true
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
let(:options) { { add_version: true } }
|
|
27
|
+
let(:target_routes) { api.combined_namespace_routes }
|
|
28
|
+
|
|
29
|
+
subject { api.endpoints[0].path_and_definition_objects(target_routes, options) }
|
|
30
|
+
|
|
31
|
+
it 'is returning a versioned path' do
|
|
32
|
+
expect(subject[0].keys[0]).to eq '/v1/item'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'tags the endpoint with the resource name' do
|
|
36
|
+
expect(subject.first['/v1/item'][:get][:tags]).to eq ['item']
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'when custom tags are specified' do
|
|
40
|
+
let(:item) do
|
|
41
|
+
Class.new(Grape::API) do
|
|
42
|
+
version 'v1', using: :path
|
|
43
|
+
|
|
44
|
+
resource :item do
|
|
45
|
+
desc 'Item description', tags: ['special-item']
|
|
46
|
+
get '/'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'tags the endpoint with the custom tags' do
|
|
52
|
+
expect(subject.first['/v1/item'][:get][:tags]).to eq ['special-item']
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context 'when parameter with a custom type is specified' do
|
|
57
|
+
let(:item) do
|
|
58
|
+
Class.new(Grape::API) do
|
|
59
|
+
Color = Struct.new(:value) do
|
|
60
|
+
def self.parse(value)
|
|
61
|
+
new(value: value)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class ColorEntity < Grape::Entity
|
|
66
|
+
expose :value
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
version 'v1', using: :path
|
|
70
|
+
|
|
71
|
+
resource :item do
|
|
72
|
+
params do
|
|
73
|
+
requires :root, type: Hash do
|
|
74
|
+
optional :color, type: Color, documentation: { type: ColorEntity }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
post '/'
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'creates a reference to the model instead of using the non-existent type' do
|
|
83
|
+
color = subject.dig(1, 'postV1Item', :properties, :root, :properties, :color)
|
|
84
|
+
expect(color).not_to eq(type: 'ColorEntity')
|
|
85
|
+
expect(color).to eq('$ref' => '#/definitions/ColorEntity')
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'when mounting an API more than once', if: GrapeVersion.satisfy?('>= 1.2.0') do
|
|
91
|
+
let(:item) do
|
|
92
|
+
Class.new(Grape::API) do
|
|
93
|
+
resource :item do
|
|
94
|
+
desc 'Item description', tags: [configuration[:tag] || 'item']
|
|
95
|
+
get '/'
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
let(:api) do
|
|
101
|
+
item_api = item
|
|
102
|
+
Class.new(Grape::API) do
|
|
103
|
+
version 'v1', using: :path do
|
|
104
|
+
mount item_api
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
version 'v2', using: :path do
|
|
108
|
+
mount item_api, with: { tag: 'special-item' }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
add_swagger_documentation add_version: true
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
let(:options) { { add_version: true } }
|
|
116
|
+
let(:target_routes) { api.combined_namespace_routes }
|
|
117
|
+
|
|
118
|
+
subject { api.endpoints[0].path_and_definition_objects(target_routes, options) }
|
|
119
|
+
|
|
120
|
+
it 'retrieves both apis respecting their configured tags' do
|
|
121
|
+
expect(subject.first['/v1/item'][:get][:tags]).to eq ['item']
|
|
122
|
+
expect(subject.first['/v2/item'][:get][:tags]).to eq ['special-item']
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'retrieves both apis with descriptions' do
|
|
126
|
+
expect(subject.first['/v1/item'][:get][:description]).to eq 'Item description'
|
|
127
|
+
expect(subject.first['/v2/item'][:get][:description]).to eq 'Item description'
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'Errors' do
|
|
6
|
+
describe 'Empty model error' do
|
|
7
|
+
let!(:app) do
|
|
8
|
+
Class.new(Grape::API) do
|
|
9
|
+
format :json
|
|
10
|
+
|
|
11
|
+
desc 'Empty model get.' do
|
|
12
|
+
http_codes [
|
|
13
|
+
{ code: 200, message: 'get Empty model', model: EmptyClass }
|
|
14
|
+
]
|
|
15
|
+
end
|
|
16
|
+
get '/empty_model' do
|
|
17
|
+
something = OpenStruct.new text: 'something'
|
|
18
|
+
present something, with: EmptyClass
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
version 'v3', using: :path
|
|
22
|
+
add_swagger_documentation api_version: 'v1',
|
|
23
|
+
base_path: '/api',
|
|
24
|
+
info: {
|
|
25
|
+
title: 'The API title to be displayed on the API homepage.',
|
|
26
|
+
description: 'A description of the API.',
|
|
27
|
+
contact_name: 'Contact name',
|
|
28
|
+
contact_email: 'Contact@email.com',
|
|
29
|
+
contact_url: 'Contact URL',
|
|
30
|
+
license: 'The name of the license.',
|
|
31
|
+
license_url: 'www.The-URL-of-the-license.org',
|
|
32
|
+
terms_of_service_url: 'www.The-URL-of-the-terms-and-service.com'
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should raise SwaggerSpec exception' do
|
|
38
|
+
expect { get '/v3/swagger_doc' }.to raise_error(GrapeSwagger::Errors::SwaggerSpec, "Empty model EmptyClass, swagger 2.0 doesn't support empty definitions.")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'Parser not found error' do
|
|
43
|
+
let!(:app) do
|
|
44
|
+
Class.new(Grape::API) do
|
|
45
|
+
format :json
|
|
46
|
+
|
|
47
|
+
desc 'Wrong model get.' do
|
|
48
|
+
http_codes [
|
|
49
|
+
{ code: 200, message: 'get Wrong model', model: Hash }
|
|
50
|
+
]
|
|
51
|
+
end
|
|
52
|
+
get '/wrong_model' do
|
|
53
|
+
something = OpenStruct.new text: 'something'
|
|
54
|
+
present something, with: Hash
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
version 'v3', using: :path
|
|
58
|
+
add_swagger_documentation api_version: 'v1',
|
|
59
|
+
base_path: '/api',
|
|
60
|
+
info: {
|
|
61
|
+
title: 'The API title to be displayed on the API homepage.',
|
|
62
|
+
description: 'A description of the API.',
|
|
63
|
+
contact_name: 'Contact name',
|
|
64
|
+
contact_email: 'Contact@email.com',
|
|
65
|
+
contact_url: 'Contact URL',
|
|
66
|
+
license: 'The name of the license.',
|
|
67
|
+
license_url: 'www.The-URL-of-the-license.org',
|
|
68
|
+
terms_of_service_url: 'www.The-URL-of-the-terms-and-service.com'
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'should raise UnregisteredParser exception' do
|
|
74
|
+
expect { get '/v3/swagger_doc' }.to raise_error(GrapeSwagger::Errors::UnregisteredParser, 'No parser registered for Hash.')
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|