grape-swagger 0.10.0 → 0.10.2
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 +4 -4
- data/.rubocop_todo.yml +10 -10
- data/.travis.yml +4 -1
- data/CHANGELOG.md +92 -63
- data/CONTRIBUTING.md +8 -8
- data/Gemfile +1 -1
- data/README.md +90 -16
- data/RELEASING.md +1 -1
- data/UPGRADING.md +26 -5
- data/grape-swagger.gemspec +1 -1
- data/lib/grape-swagger/doc_methods.rb +495 -0
- data/lib/grape-swagger/version.rb +1 -1
- data/lib/grape-swagger.rb +50 -476
- data/spec/api_description_spec.rb +2 -2
- data/spec/api_global_models_spec.rb +21 -21
- data/spec/api_models_spec.rb +62 -42
- data/spec/api_paths_spec.rb +64 -0
- data/spec/api_with_nil_types.rb +50 -0
- data/spec/api_with_prefix_and_namespace_spec.rb +32 -0
- data/spec/api_with_standalone_namespace_spec.rb +16 -16
- data/spec/array_entity_spec.rb +34 -0
- data/spec/array_params_spec.rb +35 -6
- data/spec/default_api_spec.rb +42 -0
- data/spec/float_api_spec.rb +1 -1
- data/spec/grape-swagger_helper_spec.rb +14 -1
- data/spec/mounted_target_class_spec.rb +63 -0
- data/spec/non_default_api_spec.rb +47 -16
- data/spec/param_type_spec.rb +52 -0
- data/spec/param_values_spec.rb +130 -0
- data/spec/reference_entity.rb +80 -0
- data/spec/simple_mounted_api_spec.rb +2 -2
- data/spec/support/grape_version.rb +11 -0
- metadata +54 -40
- data/.ruby-version +0 -1
- data/spec/range_values_spec.rb +0 -49
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'docs mounted separately from api' do
|
4
|
+
before :all do
|
5
|
+
class ActualApi < Grape::API
|
6
|
+
desc 'Document root'
|
7
|
+
|
8
|
+
desc 'This gets something.',
|
9
|
+
notes: '_test_'
|
10
|
+
get '/simple' do
|
11
|
+
{ bla: 'something' }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class MountedDocs < Grape::API
|
16
|
+
add_swagger_documentation(target_class: ActualApi)
|
17
|
+
end
|
18
|
+
|
19
|
+
class WholeApp < Grape::API
|
20
|
+
mount ActualApi
|
21
|
+
mount MountedDocs
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def app
|
26
|
+
WholeApp
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'retrieves docs for actual api class' do
|
30
|
+
get '/swagger_doc.json'
|
31
|
+
expect(JSON.parse(last_response.body)).to eq(
|
32
|
+
'apiVersion' => '0.1',
|
33
|
+
'swaggerVersion' => '1.2',
|
34
|
+
'info' => {},
|
35
|
+
'produces' => Grape::ContentTypes::CONTENT_TYPES.values.uniq,
|
36
|
+
'apis' => [
|
37
|
+
{ 'path' => '/simple.{format}', 'description' => 'Operations about simples' }
|
38
|
+
]
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'retrieves docs for endpoint in actual api class' do
|
43
|
+
get '/swagger_doc/simple.json'
|
44
|
+
expect(JSON.parse(last_response.body)).to eq(
|
45
|
+
'apiVersion' => '0.1',
|
46
|
+
'swaggerVersion' => '1.2',
|
47
|
+
'basePath' => 'http://example.org',
|
48
|
+
'resourcePath' => '/simple',
|
49
|
+
'produces' => Grape::ContentTypes::CONTENT_TYPES.values.uniq,
|
50
|
+
'apis' => [{
|
51
|
+
'path' => '/simple.{format}',
|
52
|
+
'operations' => [{
|
53
|
+
'notes' => '_test_',
|
54
|
+
'summary' => 'This gets something.',
|
55
|
+
'nickname' => 'GET-simple---format-',
|
56
|
+
'method' => 'GET',
|
57
|
+
'parameters' => [],
|
58
|
+
'type' => 'void'
|
59
|
+
}]
|
60
|
+
}]
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|
@@ -323,7 +323,6 @@ describe 'options: ' do
|
|
323
323
|
'apis' => [{
|
324
324
|
'path' => '/abc/v20/something.{format}',
|
325
325
|
'operations' => [{
|
326
|
-
'notes' => nil,
|
327
326
|
'notes' => '',
|
328
327
|
'summary' => 'This gets something.',
|
329
328
|
'nickname' => 'GET-abc--version-something---format-',
|
@@ -497,30 +496,62 @@ describe 'options: ' do
|
|
497
496
|
end
|
498
497
|
|
499
498
|
context ':hide_format' do
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
499
|
+
context 'with no explicit api format specified' do
|
500
|
+
before :all do
|
501
|
+
class HidePathsApi < Grape::API
|
502
|
+
desc 'This gets something.'
|
503
|
+
get '/something' do
|
504
|
+
{ bla: 'something' }
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
class SimpleApiWithHiddenPaths < Grape::API
|
509
|
+
mount HidePathsApi
|
510
|
+
add_swagger_documentation hide_format: true
|
505
511
|
end
|
506
512
|
end
|
507
513
|
|
508
|
-
|
509
|
-
|
510
|
-
add_swagger_documentation hide_format: true
|
514
|
+
def app
|
515
|
+
SimpleApiWithHiddenPaths
|
511
516
|
end
|
512
|
-
end
|
513
517
|
|
514
|
-
|
515
|
-
|
518
|
+
it 'does not end with format' do
|
519
|
+
get '/swagger_doc/something.json'
|
520
|
+
JSON.parse(last_response.body)['apis'].each do |api|
|
521
|
+
expect(api['path']).to_not end_with '.{format}'
|
522
|
+
end
|
523
|
+
end
|
516
524
|
end
|
517
525
|
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
526
|
+
context 'with single api format specified' do
|
527
|
+
before :all do
|
528
|
+
class SingleFormatApi < Grape::API
|
529
|
+
format :json
|
530
|
+
desc 'This gets something.'
|
531
|
+
get '/something' do
|
532
|
+
{ bla: 'something' }
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
class SimpleApiWithSingleFormat < Grape::API
|
537
|
+
mount SingleFormatApi
|
538
|
+
add_swagger_documentation hide_format: true
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
def app
|
543
|
+
SimpleApiWithSingleFormat
|
544
|
+
end
|
545
|
+
|
546
|
+
it 'does not end with format' do
|
547
|
+
get '/swagger_doc/something.json'
|
548
|
+
JSON.parse(last_response.body)['apis'].each do |api|
|
549
|
+
expect(api['path']).to_not end_with '.{format}'
|
550
|
+
expect(api['path']).to_not end_with '(.json)'
|
551
|
+
end
|
522
552
|
end
|
523
553
|
end
|
554
|
+
|
524
555
|
end
|
525
556
|
|
526
557
|
context 'multiple documentations' do
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Params Types' do
|
4
|
+
def app
|
5
|
+
Class.new(Grape::API) do
|
6
|
+
format :json
|
7
|
+
|
8
|
+
params do
|
9
|
+
requires :input, type: String, documentation: { param_type: 'query' }
|
10
|
+
end
|
11
|
+
post :action do
|
12
|
+
end
|
13
|
+
|
14
|
+
add_swagger_documentation
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
subject do
|
19
|
+
get '/swagger_doc/action'
|
20
|
+
expect(last_response.status).to eq 200
|
21
|
+
body = JSON.parse last_response.body
|
22
|
+
body['apis'].first['operations'].first['parameters']
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'reads param type correctly' do
|
26
|
+
expect(subject).to eq [
|
27
|
+
{ 'paramType' => 'query', 'name' => 'input', 'description' => nil, 'type' => 'string', 'required' => true, 'allowMultiple' => false }
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'header params' do
|
32
|
+
def app
|
33
|
+
Class.new(Grape::API) do
|
34
|
+
format :json
|
35
|
+
|
36
|
+
desc 'Some API', headers: { 'My-Header' => { required: true, description: 'Set this!' } }
|
37
|
+
params do
|
38
|
+
requires :input, type: String
|
39
|
+
end
|
40
|
+
post :action do
|
41
|
+
end
|
42
|
+
|
43
|
+
add_swagger_documentation
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'has consistent types' do
|
48
|
+
types = subject.map { |param| param['type'] }
|
49
|
+
expect(types).to eq(%w(string string))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'grape_version'
|
3
|
+
|
4
|
+
describe 'Convert values to enum or Range' do
|
5
|
+
def app
|
6
|
+
Class.new(Grape::API) do
|
7
|
+
format :json
|
8
|
+
|
9
|
+
params do
|
10
|
+
requires :letter, type: String, values: %w(a b c)
|
11
|
+
end
|
12
|
+
post :plain_array do
|
13
|
+
end
|
14
|
+
|
15
|
+
params do
|
16
|
+
requires :letter, type: String, values: proc { %w(d e f) }
|
17
|
+
end
|
18
|
+
post :array_in_proc do
|
19
|
+
end
|
20
|
+
|
21
|
+
params do
|
22
|
+
requires :letter, type: String, values: 'a'..'z'
|
23
|
+
end
|
24
|
+
post :range_letter do
|
25
|
+
end
|
26
|
+
|
27
|
+
params do
|
28
|
+
requires :integer, type: Integer, values: -5..5
|
29
|
+
end
|
30
|
+
post :range_integer do
|
31
|
+
end
|
32
|
+
|
33
|
+
add_swagger_documentation
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def first_parameter_info(request)
|
38
|
+
get "/swagger_doc/#{request}"
|
39
|
+
expect(last_response.status).to eq 200
|
40
|
+
body = JSON.parse last_response.body
|
41
|
+
body['apis'].first['operations'].first['parameters']
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'Plain array values' do
|
45
|
+
subject(:plain_array) { first_parameter_info('plain_array') }
|
46
|
+
|
47
|
+
it 'has values as array in enum' do
|
48
|
+
expect(plain_array).to eq [
|
49
|
+
{ 'paramType' => 'form', 'name' => 'letter', 'description' => nil, 'type' => 'string', 'required' => true, 'allowMultiple' => false, 'enum' => %w(a b c) }
|
50
|
+
]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'Array in proc values' do
|
55
|
+
subject(:array_in_proc) { first_parameter_info('array_in_proc') }
|
56
|
+
|
57
|
+
it 'has proc returned values as array in enum' do
|
58
|
+
expect(array_in_proc).to eq [
|
59
|
+
{ 'paramType' => 'form', 'name' => 'letter', 'description' => nil, 'type' => 'string', 'required' => true, 'allowMultiple' => false, 'enum' => %w(d e f) }
|
60
|
+
]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'Range values' do
|
65
|
+
subject(:range_letter) { first_parameter_info('range_letter') }
|
66
|
+
|
67
|
+
it 'has letter range values' do
|
68
|
+
expect(range_letter).to eq [
|
69
|
+
{ 'paramType' => 'form', 'name' => 'letter', 'description' => nil, 'type' => 'string', 'required' => true, 'allowMultiple' => false }
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
subject(:range_integer) { first_parameter_info('range_integer') }
|
74
|
+
|
75
|
+
it 'has integer range values' do
|
76
|
+
expect(range_integer).to eq [
|
77
|
+
{ 'paramType' => 'form', 'name' => 'integer', 'description' => nil, 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32', 'minimum' => -5, 'maximum' => 5 }
|
78
|
+
]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'Convert values to enum for float range and not arrays inside a proc', if: GrapeVersion.satisfy?('>= 0.11.0') do
|
84
|
+
def app
|
85
|
+
Class.new(Grape::API) do
|
86
|
+
format :json
|
87
|
+
|
88
|
+
params do
|
89
|
+
requires :letter, type: String, values: proc { 'string' }
|
90
|
+
end
|
91
|
+
post :non_array_in_proc do
|
92
|
+
end
|
93
|
+
|
94
|
+
params do
|
95
|
+
requires :float, type: Float, values: -5.0..5.0
|
96
|
+
end
|
97
|
+
post :range_float do
|
98
|
+
end
|
99
|
+
|
100
|
+
add_swagger_documentation
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def first_parameter_info(request)
|
105
|
+
get "/swagger_doc/#{request}"
|
106
|
+
expect(last_response.status).to eq 200
|
107
|
+
body = JSON.parse last_response.body
|
108
|
+
body['apis'].first['operations'].first['parameters']
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'Non array in proc values' do
|
112
|
+
subject(:non_array_in_proc) { first_parameter_info('non_array_in_proc') }
|
113
|
+
|
114
|
+
it 'has proc returned value as string in enum' do
|
115
|
+
expect(non_array_in_proc).to eq [
|
116
|
+
{ 'paramType' => 'form', 'name' => 'letter', 'description' => nil, 'type' => 'string', 'required' => true, 'allowMultiple' => false, 'enum' => 'string' }
|
117
|
+
]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'Range values' do
|
122
|
+
subject(:range_float) { first_parameter_info('range_float') }
|
123
|
+
|
124
|
+
it 'has float range values as string' do
|
125
|
+
expect(range_float).to eq [
|
126
|
+
{ 'paramType' => 'form', 'name' => 'float', 'description' => nil, 'type' => 'number', 'format' => 'float', 'required' => true, 'allowMultiple' => false }
|
127
|
+
]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'referenceEntity' do
|
4
|
+
before :all do
|
5
|
+
module MyAPI
|
6
|
+
module Entities
|
7
|
+
class Something < Grape::Entity
|
8
|
+
def self.entity_name
|
9
|
+
'SomethingCustom'
|
10
|
+
end
|
11
|
+
|
12
|
+
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
|
13
|
+
end
|
14
|
+
|
15
|
+
class Kind < Grape::Entity
|
16
|
+
def self.entity_name
|
17
|
+
'KindCustom'
|
18
|
+
end
|
19
|
+
|
20
|
+
expose :title, documentation: { type: 'string', desc: 'Title of the kind.' }
|
21
|
+
expose :something, documentation: { type: Something, desc: 'Something interesting.' }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ResponseModelApi < Grape::API
|
26
|
+
format :json
|
27
|
+
desc 'This returns kind and something or an error',
|
28
|
+
params: Entities::Kind.documentation.slice(:something),
|
29
|
+
entity: Entities::Kind,
|
30
|
+
http_codes: [
|
31
|
+
[200, 'OK', Entities::Kind]
|
32
|
+
]
|
33
|
+
|
34
|
+
get '/kind' do
|
35
|
+
kind = OpenStruct.new text: 'kind'
|
36
|
+
present kind, with: Entities::Kind
|
37
|
+
end
|
38
|
+
|
39
|
+
add_swagger_documentation models: [MyAPI::Entities::Something, MyAPI::Entities::Kind]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def app
|
45
|
+
MyAPI::ResponseModelApi
|
46
|
+
end
|
47
|
+
|
48
|
+
subject do
|
49
|
+
get '/swagger_doc/kind'
|
50
|
+
JSON.parse(last_response.body)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should document specified models' do
|
54
|
+
expect(subject['apis'][0]['operations'][0]['parameters']).to eq [{
|
55
|
+
'paramType' => 'query',
|
56
|
+
'name' => 'something',
|
57
|
+
'description' => 'Something interesting.',
|
58
|
+
'type' => 'MySomething',
|
59
|
+
'required' => false,
|
60
|
+
'allowMultiple' => false
|
61
|
+
}]
|
62
|
+
|
63
|
+
expect(subject['models'].keys).to include 'MySomething'
|
64
|
+
expect(subject['models']['MySomething']).to eq(
|
65
|
+
'id' => 'MyAPI::Something',
|
66
|
+
'properties' => {
|
67
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' }
|
68
|
+
}
|
69
|
+
)
|
70
|
+
|
71
|
+
expect(subject['models'].keys).to include 'MyKind'
|
72
|
+
expect(subject['models']['MyKind']).to eq(
|
73
|
+
'id' => 'MyKind',
|
74
|
+
'properties' => {
|
75
|
+
'title' => { 'type' => 'string', 'description' => 'Title of the kind.' },
|
76
|
+
'something' => { '$ref' => 'MySomething', 'description' => 'Something interesting.' }
|
77
|
+
}
|
78
|
+
)
|
79
|
+
end
|
80
|
+
end
|
@@ -139,8 +139,8 @@ describe 'a simple mounted api' do
|
|
139
139
|
'nickname' => 'GET-simple_with_headers---format-',
|
140
140
|
'method' => 'GET',
|
141
141
|
'parameters' => [
|
142
|
-
{ 'paramType' => 'header', 'name' => 'XAuthToken', 'description' => 'A required header.', 'type' => '
|
143
|
-
{ 'paramType' => 'header', 'name' => 'XOtherHeader', 'description' => 'An optional header.', 'type' => '
|
142
|
+
{ 'paramType' => 'header', 'name' => 'XAuthToken', 'description' => 'A required header.', 'type' => 'string', 'required' => true },
|
143
|
+
{ 'paramType' => 'header', 'name' => 'XOtherHeader', 'description' => 'An optional header.', 'type' => 'string', 'required' => false }
|
144
144
|
],
|
145
145
|
'type' => 'void',
|
146
146
|
'responseMessages' => [
|