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,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'nested group params' do
|
|
6
|
+
[true, false].each do |array_use_braces|
|
|
7
|
+
context "when array_use_braces option is set to #{array_use_braces}" do
|
|
8
|
+
let(:braces) { array_use_braces ? '[]' : '' }
|
|
9
|
+
let(:app) do
|
|
10
|
+
Class.new(Grape::API) do
|
|
11
|
+
format :json
|
|
12
|
+
|
|
13
|
+
desc 'nested array' do
|
|
14
|
+
consumes ['application/x-www-form-urlencoded']
|
|
15
|
+
end
|
|
16
|
+
params do
|
|
17
|
+
requires :a_array, type: Array do
|
|
18
|
+
requires :param_1, type: Integer
|
|
19
|
+
requires :b_array, type: Array do
|
|
20
|
+
requires :param_2, type: String
|
|
21
|
+
end
|
|
22
|
+
requires :c_hash, type: Hash do
|
|
23
|
+
requires :param_3, type: String
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
requires :a_array_foo, type: String
|
|
27
|
+
end
|
|
28
|
+
post '/nested_array' do
|
|
29
|
+
{ 'declared_params' => declared(params) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
desc 'nested hash' do
|
|
33
|
+
consumes ['application/x-www-form-urlencoded']
|
|
34
|
+
end
|
|
35
|
+
params do
|
|
36
|
+
requires :a_hash, type: Hash do
|
|
37
|
+
requires :param_1, type: Integer
|
|
38
|
+
requires :b_hash, type: Hash do
|
|
39
|
+
requires :param_2, type: String
|
|
40
|
+
end
|
|
41
|
+
requires :c_array, type: Array do
|
|
42
|
+
requires :param_3, type: String
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
requires :a_hash_foo, type: String
|
|
46
|
+
end
|
|
47
|
+
post '/nested_hash' do
|
|
48
|
+
{ 'declared_params' => declared(params) }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
add_swagger_documentation array_use_braces: array_use_braces
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe 'retrieves the documentation for nested array parameters' do
|
|
56
|
+
subject do
|
|
57
|
+
get '/swagger_doc/nested_array'
|
|
58
|
+
JSON.parse(last_response.body)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
specify do
|
|
62
|
+
expect(subject['paths']['/nested_array']['post']['parameters']).to eql(
|
|
63
|
+
[
|
|
64
|
+
{ 'in' => 'formData', 'name' => "a_array#{braces}[param_1]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'integer', 'format' => 'int32' } },
|
|
65
|
+
{ 'in' => 'formData', 'name' => "a_array#{braces}[b_array]#{braces}[param_2]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } },
|
|
66
|
+
{ 'in' => 'formData', 'name' => "a_array#{braces}[c_hash][param_3]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } },
|
|
67
|
+
{ 'in' => 'formData', 'name' => 'a_array_foo', 'required' => true, 'type' => 'string' }
|
|
68
|
+
]
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe 'retrieves the documentation for nested hash parameters' do
|
|
74
|
+
subject do
|
|
75
|
+
get '/swagger_doc/nested_hash'
|
|
76
|
+
JSON.parse(last_response.body)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
specify do
|
|
80
|
+
expect(subject['paths']['/nested_hash']['post']['parameters']).to eql(
|
|
81
|
+
[
|
|
82
|
+
{ 'in' => 'formData', 'name' => 'a_hash[param_1]', 'required' => true, 'type' => 'integer', 'format' => 'int32' },
|
|
83
|
+
{ 'in' => 'formData', 'name' => 'a_hash[b_hash][param_2]', 'required' => true, 'type' => 'string' },
|
|
84
|
+
{ 'in' => 'formData', 'name' => "a_hash[c_array]#{braces}[param_3]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } },
|
|
85
|
+
{ 'in' => 'formData', 'name' => 'a_hash_foo', 'required' => true, 'type' => 'string' }
|
|
86
|
+
]
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'a parent less namespace' do
|
|
6
|
+
include_context 'namespace example'
|
|
7
|
+
|
|
8
|
+
before :all do
|
|
9
|
+
class ParentLessApi < Grape::API
|
|
10
|
+
prefix :api
|
|
11
|
+
mount TheApi::ParentLessNamespaceApi
|
|
12
|
+
add_swagger_documentation version: 'v1'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def app
|
|
17
|
+
ParentLessApi
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe 'retrieves swagger-documentation on /swagger_doc' do
|
|
21
|
+
let(:route_name) { ':animal/:breed/queues/:queue_id/reservations' }
|
|
22
|
+
subject do
|
|
23
|
+
get '/api/swagger_doc.json'
|
|
24
|
+
JSON.parse(last_response.body)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
specify do
|
|
28
|
+
expect(subject['paths']['/api/{animal}/{breed}/queues/{queue_id}/reservations']['get']['operationId'])
|
|
29
|
+
.to start_with('getApiAnimalBreedQueuesQueueIdReservations')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'referenceEntity' do
|
|
6
|
+
before :all do
|
|
7
|
+
module MyAPI
|
|
8
|
+
module Entities
|
|
9
|
+
class Something < Grape::Entity
|
|
10
|
+
def self.entity_name
|
|
11
|
+
'SomethingCustom'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Kind < Grape::Entity
|
|
18
|
+
def self.entity_name
|
|
19
|
+
'KindCustom'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
expose :title, documentation: { type: 'string', desc: 'Title of the kind.' }
|
|
23
|
+
expose :something, documentation: { type: Something, desc: 'Something interesting.' }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Base < Grape::Entity
|
|
27
|
+
def self.entity_name
|
|
28
|
+
parts = to_s.split('::')
|
|
29
|
+
|
|
30
|
+
"MyAPI::#{parts.last}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
expose :title, documentation: { type: 'string', desc: 'Title of the parent.' }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class Child < Base
|
|
37
|
+
expose :child, documentation: { type: 'string', desc: 'Child property.' }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class ResponseModelApi < Grape::API
|
|
42
|
+
format :json
|
|
43
|
+
desc 'This returns kind and something or an error',
|
|
44
|
+
params: Entities::Kind.documentation.slice(:something),
|
|
45
|
+
entity: Entities::Kind,
|
|
46
|
+
http_codes: [
|
|
47
|
+
{ code: 200, message: 'OK', model: Entities::Kind }
|
|
48
|
+
]
|
|
49
|
+
params do
|
|
50
|
+
optional :something, desc: 'something as parameter'
|
|
51
|
+
end
|
|
52
|
+
get '/kind' do
|
|
53
|
+
kind = OpenStruct.new text: 'kind'
|
|
54
|
+
present kind, with: Entities::Kind
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
desc 'This returns a child entity',
|
|
58
|
+
entity: Entities::Child,
|
|
59
|
+
http_codes: [
|
|
60
|
+
{ code: 200, message: 'OK', model: Entities::Child }
|
|
61
|
+
]
|
|
62
|
+
get '/child' do
|
|
63
|
+
child = OpenStruct.new text: 'child'
|
|
64
|
+
present child, with: Entities::Child
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
add_swagger_documentation # models: [MyAPI::Entities::Something, MyAPI::Entities::Kind]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def app
|
|
73
|
+
MyAPI::ResponseModelApi
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe 'kind' do
|
|
77
|
+
subject do
|
|
78
|
+
get '/swagger_doc/kind'
|
|
79
|
+
JSON.parse(last_response.body)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'should document specified models' do
|
|
83
|
+
expect(subject['paths']['/kind']['get']['parameters']).to eq [{
|
|
84
|
+
'in' => 'query',
|
|
85
|
+
'name' => 'something',
|
|
86
|
+
'description' => 'Something interesting.',
|
|
87
|
+
'type' => 'SomethingCustom',
|
|
88
|
+
'required' => false
|
|
89
|
+
}]
|
|
90
|
+
|
|
91
|
+
expect(subject['definitions'].keys).to include 'SomethingCustom'
|
|
92
|
+
expect(subject['definitions']['SomethingCustom']).to eq(
|
|
93
|
+
'type' => 'object', 'properties' => { 'text' => { 'type' => 'string', 'description' => 'Content of something.' } }
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
expect(subject['definitions'].keys).to include 'KindCustom'
|
|
97
|
+
expect(subject['definitions']['KindCustom']).to eq(
|
|
98
|
+
'type' => 'object',
|
|
99
|
+
'properties' => {
|
|
100
|
+
'title' => { 'type' => 'string', 'description' => 'Title of the kind.' },
|
|
101
|
+
'something' => {
|
|
102
|
+
'$ref' => '#/definitions/SomethingCustom',
|
|
103
|
+
'description' => 'Something interesting.'
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
'description' => 'KindCustom model'
|
|
107
|
+
)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe 'child' do
|
|
112
|
+
subject do
|
|
113
|
+
get '/swagger_doc/child'
|
|
114
|
+
JSON.parse(last_response.body)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'should document specified models' do
|
|
118
|
+
expect(subject['definitions'].keys).to include 'MyAPI::Child'
|
|
119
|
+
expect(subject['definitions']['MyAPI::Child']).to eq(
|
|
120
|
+
'type' => 'object',
|
|
121
|
+
'properties' => {
|
|
122
|
+
'title' => { 'type' => 'string', 'description' => 'Title of the parent.' },
|
|
123
|
+
'child' => { 'type' => 'string', 'description' => 'Child property.' }
|
|
124
|
+
},
|
|
125
|
+
'description' => 'MyAPI::Child model'
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'security requirement on endpoint method' do
|
|
6
|
+
def app
|
|
7
|
+
Class.new(Grape::API) do
|
|
8
|
+
desc 'Endpoint with security requirement', security: [{ oauth_pets: ['read:pets', 'write:pets'] }]
|
|
9
|
+
get '/with_security' do
|
|
10
|
+
{ foo: 'bar' }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
desc 'Endpoint without security requirement', security: []
|
|
14
|
+
get '/without_security' do
|
|
15
|
+
{ foo: 'bar' }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
add_swagger_documentation(
|
|
19
|
+
security_definitions: {
|
|
20
|
+
petstore_auth: {
|
|
21
|
+
type: 'oauth2',
|
|
22
|
+
flow: 'implicit',
|
|
23
|
+
authorizationUrl: 'https://petstore.swagger.io/oauth/dialog',
|
|
24
|
+
scopes: {
|
|
25
|
+
'read:pets': 'read your pets',
|
|
26
|
+
'write:pets': 'modify pets in your account'
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
subject do
|
|
35
|
+
get '/swagger_doc.json'
|
|
36
|
+
JSON.parse(last_response.body)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'defines the security requirement on the endpoint method' do
|
|
40
|
+
expect(subject['paths']['/with_security']['get']['security']).to eql [{ 'oauth_pets' => ['read:pets', 'write:pets'] }]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'defines an empty security requirement on the endpoint method' do
|
|
44
|
+
expect(subject['paths']['/without_security']['get']['security']).to eql []
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe 'a simple mounted api' do
|
|
6
|
+
before :all do
|
|
7
|
+
# rubocop:disable Lint/EmptyClass
|
|
8
|
+
class CustomType; end
|
|
9
|
+
# rubocop:enable Lint/EmptyClass
|
|
10
|
+
|
|
11
|
+
class SimpleMountedApi < Grape::API
|
|
12
|
+
desc 'Document root',
|
|
13
|
+
consumes: ['application/x-www-form-urlencoded']
|
|
14
|
+
get do
|
|
15
|
+
{ message: 'hi' }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
desc 'This gets something.',
|
|
19
|
+
consumes: ['application/x-www-form-urlencoded'],
|
|
20
|
+
notes: '_test_'
|
|
21
|
+
|
|
22
|
+
get '/simple' do
|
|
23
|
+
{ bla: 'something' }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
desc 'This gets something for URL using - separator.',
|
|
27
|
+
consumes: ['application/x-www-form-urlencoded'],
|
|
28
|
+
notes: '_test_'
|
|
29
|
+
|
|
30
|
+
get '/simple-test' do
|
|
31
|
+
{ bla: 'something' }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
head '/simple-head-test' do
|
|
35
|
+
status 200
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
options '/simple-options-test' do
|
|
39
|
+
status 200
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
desc 'this gets something else',
|
|
43
|
+
consumes: ['application/x-www-form-urlencoded'],
|
|
44
|
+
headers: {
|
|
45
|
+
'XAuthToken' => { description: 'A required header.', required: true },
|
|
46
|
+
'XOtherHeader' => { description: 'An optional header.', required: false }
|
|
47
|
+
},
|
|
48
|
+
http_codes: [
|
|
49
|
+
{ code: 403, message: 'invalid pony' },
|
|
50
|
+
{ code: 405, message: 'no ponies left!' }
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
get '/simple_with_headers' do
|
|
54
|
+
{ bla: 'something_else' }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
desc 'this takes an array of parameters',
|
|
58
|
+
consumes: ['application/x-www-form-urlencoded'],
|
|
59
|
+
params: {
|
|
60
|
+
'items[]' => { description: 'array of items', is_array: true }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
post '/items' do
|
|
64
|
+
{}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
desc 'this uses a custom parameter',
|
|
68
|
+
consumes: ['application/x-www-form-urlencoded'],
|
|
69
|
+
params: {
|
|
70
|
+
'custom' => { type: CustomType, description: 'array of items', is_array: true }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get '/custom' do
|
|
74
|
+
{}
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
class SimpleApi < Grape::API
|
|
79
|
+
mount SimpleMountedApi
|
|
80
|
+
add_swagger_documentation
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def app
|
|
85
|
+
SimpleApi
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe 'retrieves swagger-documentation on /swagger_doc' do
|
|
89
|
+
subject do
|
|
90
|
+
get '/swagger_doc.json'
|
|
91
|
+
JSON.parse(last_response.body)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
specify do
|
|
95
|
+
expect(subject).to eq(
|
|
96
|
+
'info' => {
|
|
97
|
+
'title' => 'API title', 'version' => '0.0.1'
|
|
98
|
+
},
|
|
99
|
+
'swagger' => '2.0',
|
|
100
|
+
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
|
|
101
|
+
'host' => 'example.org',
|
|
102
|
+
'tags' => [
|
|
103
|
+
{ 'name' => 'simple', 'description' => 'Operations about simples' },
|
|
104
|
+
{ 'name' => 'simple-test', 'description' => 'Operations about simple-tests' },
|
|
105
|
+
{ 'name' => 'simple-head-test', 'description' => 'Operations about simple-head-tests' },
|
|
106
|
+
{ 'name' => 'simple-options-test', 'description' => 'Operations about simple-options-tests' },
|
|
107
|
+
{ 'name' => 'simple_with_headers', 'description' => 'Operations about simple_with_headers' },
|
|
108
|
+
{ 'name' => 'items', 'description' => 'Operations about items' },
|
|
109
|
+
{ 'name' => 'custom', 'description' => 'Operations about customs' }
|
|
110
|
+
],
|
|
111
|
+
'paths' => {
|
|
112
|
+
'/' => {
|
|
113
|
+
'get' => {
|
|
114
|
+
'description' => 'Document root',
|
|
115
|
+
'produces' => ['application/json'],
|
|
116
|
+
'responses' => { '200' => { 'description' => 'Document root' } },
|
|
117
|
+
'operationId' => 'get'
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
'/simple' => {
|
|
121
|
+
'get' => {
|
|
122
|
+
'description' => 'This gets something.',
|
|
123
|
+
'produces' => ['application/json'],
|
|
124
|
+
'tags' => ['simple'],
|
|
125
|
+
'operationId' => 'getSimple',
|
|
126
|
+
'responses' => { '200' => { 'description' => 'This gets something.' } }
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
'/simple-test' => {
|
|
130
|
+
'get' => {
|
|
131
|
+
'description' => 'This gets something for URL using - separator.',
|
|
132
|
+
'produces' => ['application/json'],
|
|
133
|
+
'tags' => ['simple-test'],
|
|
134
|
+
'operationId' => 'getSimpleTest',
|
|
135
|
+
'responses' => { '200' => { 'description' => 'This gets something for URL using - separator.' } }
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
'/simple-head-test' => {
|
|
139
|
+
'head' => {
|
|
140
|
+
'produces' => ['application/json'],
|
|
141
|
+
'responses' => { '200' => { 'description' => 'head SimpleHeadTest' } },
|
|
142
|
+
'tags' => ['simple-head-test'],
|
|
143
|
+
'operationId' => 'headSimpleHeadTest'
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
'/simple-options-test' => {
|
|
147
|
+
'options' => {
|
|
148
|
+
'produces' => ['application/json'],
|
|
149
|
+
'responses' => { '200' => { 'description' => 'option SimpleOptionsTest' } },
|
|
150
|
+
'tags' => ['simple-options-test'],
|
|
151
|
+
'operationId' => 'optionsSimpleOptionsTest'
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
'/simple_with_headers' => {
|
|
155
|
+
'get' => {
|
|
156
|
+
'description' => 'this gets something else',
|
|
157
|
+
'produces' => ['application/json'],
|
|
158
|
+
'parameters' => [
|
|
159
|
+
{ 'in' => 'header', 'name' => 'XAuthToken', 'description' => 'A required header.', 'type' => 'string', 'required' => true },
|
|
160
|
+
{ 'in' => 'header', 'name' => 'XOtherHeader', 'description' => 'An optional header.', 'type' => 'string', 'required' => false }
|
|
161
|
+
],
|
|
162
|
+
'tags' => ['simple_with_headers'],
|
|
163
|
+
'operationId' => 'getSimpleWithHeaders',
|
|
164
|
+
'responses' => {
|
|
165
|
+
'200' => { 'description' => 'this gets something else' },
|
|
166
|
+
'403' => { 'description' => 'invalid pony' },
|
|
167
|
+
'405' => { 'description' => 'no ponies left!' }
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
'/items' => {
|
|
172
|
+
'post' => {
|
|
173
|
+
'description' => 'this takes an array of parameters',
|
|
174
|
+
'produces' => ['application/json'],
|
|
175
|
+
'consumes' => ['application/x-www-form-urlencoded'],
|
|
176
|
+
'parameters' => [{ 'in' => 'formData', 'name' => 'items[]', 'description' => 'array of items', 'required' => false, 'type' => 'array', 'items' => { 'type' => 'string' } }],
|
|
177
|
+
'tags' => ['items'],
|
|
178
|
+
'operationId' => 'postItems',
|
|
179
|
+
'responses' => { '201' => { 'description' => 'this takes an array of parameters' } }
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
'/custom' => {
|
|
183
|
+
'get' => {
|
|
184
|
+
'description' => 'this uses a custom parameter',
|
|
185
|
+
'produces' => ['application/json'],
|
|
186
|
+
'parameters' => [{ 'in' => 'formData', 'name' => 'custom', 'description' => 'array of items', 'required' => false, 'type' => 'array', 'items' => { 'type' => 'CustomType' } }],
|
|
187
|
+
'tags' => ['custom'],
|
|
188
|
+
'operationId' => 'getCustom',
|
|
189
|
+
'responses' => { '200' => { 'description' => 'this uses a custom parameter' } }
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
describe 'retrieves the documentation for mounted-api' do
|
|
198
|
+
subject do
|
|
199
|
+
get '/swagger_doc/simple.json'
|
|
200
|
+
JSON.parse(last_response.body)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
specify do
|
|
204
|
+
expect(subject).to eq(
|
|
205
|
+
'info' => { 'title' => 'API title', 'version' => '0.0.1' },
|
|
206
|
+
'swagger' => '2.0',
|
|
207
|
+
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
|
|
208
|
+
'host' => 'example.org',
|
|
209
|
+
'tags' => [
|
|
210
|
+
{ 'name' => 'simple', 'description' => 'Operations about simples' }
|
|
211
|
+
],
|
|
212
|
+
'paths' => {
|
|
213
|
+
'/simple' => {
|
|
214
|
+
'get' => {
|
|
215
|
+
'description' => 'This gets something.',
|
|
216
|
+
'produces' => ['application/json'],
|
|
217
|
+
'tags' => ['simple'],
|
|
218
|
+
'operationId' => 'getSimple',
|
|
219
|
+
'responses' => { '200' => { 'description' => 'This gets something.' } }
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
describe 'retrieves the documentation for mounted-api that' do
|
|
228
|
+
describe "contains '-' in URL" do
|
|
229
|
+
subject do
|
|
230
|
+
get '/swagger_doc/simple-test.json'
|
|
231
|
+
JSON.parse(last_response.body)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
specify do
|
|
235
|
+
expect(subject).to eq(
|
|
236
|
+
'info' => { 'title' => 'API title', 'version' => '0.0.1' },
|
|
237
|
+
'swagger' => '2.0',
|
|
238
|
+
'produces' => ['application/xml', 'application/json', 'application/octet-stream', 'text/plain'],
|
|
239
|
+
'host' => 'example.org',
|
|
240
|
+
'tags' => [
|
|
241
|
+
{ 'name' => 'simple-test', 'description' => 'Operations about simple-tests' }
|
|
242
|
+
],
|
|
243
|
+
'paths' => {
|
|
244
|
+
'/simple-test' => {
|
|
245
|
+
'get' => {
|
|
246
|
+
'description' => 'This gets something for URL using - separator.',
|
|
247
|
+
'produces' => ['application/json'],
|
|
248
|
+
'tags' => ['simple-test'],
|
|
249
|
+
'operationId' => 'getSimpleTest',
|
|
250
|
+
'responses' => { '200' => { 'description' => 'This gets something for URL using - separator.' } }
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
)
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
describe 'includes headers' do
|
|
259
|
+
subject do
|
|
260
|
+
get '/swagger_doc/simple_with_headers.json'
|
|
261
|
+
JSON.parse(last_response.body)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
specify do
|
|
265
|
+
expect(subject['paths']).to eq(
|
|
266
|
+
'/simple_with_headers' => {
|
|
267
|
+
'get' => {
|
|
268
|
+
'description' => 'this gets something else',
|
|
269
|
+
'produces' => ['application/json'],
|
|
270
|
+
'parameters' => [
|
|
271
|
+
{ 'in' => 'header', 'name' => 'XAuthToken', 'description' => 'A required header.', 'type' => 'string', 'required' => true },
|
|
272
|
+
{ 'in' => 'header', 'name' => 'XOtherHeader', 'description' => 'An optional header.', 'type' => 'string', 'required' => false }
|
|
273
|
+
],
|
|
274
|
+
'tags' => ['simple_with_headers'],
|
|
275
|
+
'operationId' => 'getSimpleWithHeaders',
|
|
276
|
+
'responses' => {
|
|
277
|
+
'200' => { 'description' => 'this gets something else' },
|
|
278
|
+
'403' => { 'description' => 'invalid pony' },
|
|
279
|
+
'405' => { 'description' => 'no ponies left!' }
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
describe 'supports array params' do
|
|
288
|
+
subject do
|
|
289
|
+
get '/swagger_doc/items.json'
|
|
290
|
+
JSON.parse(last_response.body)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
specify do
|
|
294
|
+
expect(subject['paths']).to eq(
|
|
295
|
+
'/items' => {
|
|
296
|
+
'post' => {
|
|
297
|
+
'description' => 'this takes an array of parameters',
|
|
298
|
+
'produces' => ['application/json'],
|
|
299
|
+
'consumes' => ['application/x-www-form-urlencoded'],
|
|
300
|
+
'parameters' => [{ 'in' => 'formData', 'name' => 'items[]', 'description' => 'array of items', 'required' => false, 'type' => 'array', 'items' => { 'type' => 'string' } }],
|
|
301
|
+
'tags' => ['items'],
|
|
302
|
+
'operationId' => 'postItems',
|
|
303
|
+
'responses' => { '201' => { 'description' => 'this takes an array of parameters' } }
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
)
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
describe 'supports custom params types' do
|
|
311
|
+
subject do
|
|
312
|
+
get '/swagger_doc/custom.json'
|
|
313
|
+
JSON.parse(last_response.body)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
specify do
|
|
317
|
+
expect(subject['paths']).to eq(
|
|
318
|
+
'/custom' => {
|
|
319
|
+
'get' => {
|
|
320
|
+
'description' => 'this uses a custom parameter',
|
|
321
|
+
'produces' => ['application/json'],
|
|
322
|
+
'parameters' => [{ 'in' => 'formData', 'name' => 'custom', 'description' => 'array of items', 'required' => false, 'type' => 'array', 'items' => { 'type' => 'CustomType' } }],
|
|
323
|
+
'tags' => ['custom'],
|
|
324
|
+
'operationId' => 'getCustom',
|
|
325
|
+
'responses' => { '200' => { 'description' => 'this uses a custom parameter' } }
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
)
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|