grape-swagger 0.7.2 → 0.8.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/.gitignore +33 -0
- data/.rubocop.yml +36 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +90 -0
- data/CONTRIBUTING.md +126 -0
- data/Gemfile +1 -21
- data/LICENSE.txt +1 -1
- data/README.md +397 -0
- data/RELEASING.md +80 -0
- data/Rakefile +6 -23
- data/UPGRADING.md +47 -0
- data/grape-swagger.gemspec +26 -84
- data/lib/grape-swagger.rb +237 -111
- data/lib/grape-swagger/errors.rb +9 -0
- data/lib/grape-swagger/markdown.rb +23 -0
- data/lib/grape-swagger/markdown/kramdown_adapter.rb +37 -0
- data/lib/grape-swagger/markdown/redcarpet_adapter.rb +89 -0
- data/lib/grape-swagger/version.rb +3 -0
- data/spec/api_description_spec.rb +41 -0
- data/spec/api_global_models_spec.rb +76 -0
- data/spec/api_models_spec.rb +190 -93
- data/spec/default_api_spec.rb +31 -36
- data/spec/form_params_spec.rb +56 -53
- data/spec/grape-swagger_helper_spec.rb +88 -49
- data/spec/grape-swagger_spec.rb +7 -5
- data/spec/hide_api_spec.rb +58 -55
- data/spec/markdown/kramdown_adapter_spec.rb +38 -0
- data/spec/markdown/markdown_spec.rb +27 -0
- data/spec/markdown/redcarpet_adapter_spec.rb +81 -0
- data/spec/namespaced_api_spec.rb +47 -0
- data/spec/non_default_api_spec.rb +372 -222
- data/spec/response_model_spec.rb +80 -0
- data/spec/simple_mounted_api_spec.rb +113 -118
- data/spec/spec_helper.rb +0 -1
- data/spec/version_spec.rb +8 -0
- data/test/api.rb +62 -0
- data/test/config.ru +10 -2
- data/test/splines.png +0 -0
- metadata +145 -91
- data/.rvmrc +0 -48
- data/CHANGELOG.markdown +0 -55
- data/Gemfile.lock +0 -94
- data/README.markdown +0 -168
- data/VERSION +0 -1
- data/test/nested_api.rb +0 -30
data/spec/default_api_spec.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
3
|
+
describe 'Default API' do
|
5
4
|
context 'with no additional options' do
|
6
|
-
|
7
|
-
|
5
|
+
def app
|
6
|
+
Class.new(Grape::API) do
|
8
7
|
format :json
|
9
8
|
desc 'This gets something.'
|
10
9
|
get '/something' do
|
@@ -14,37 +13,36 @@ describe "Default API" do
|
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
it "should document something" do
|
16
|
+
subject do
|
20
17
|
get '/swagger_doc'
|
21
|
-
JSON.parse(last_response.body)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
18
|
+
JSON.parse(last_response.body)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'documents api' do
|
22
|
+
expect(subject).to eq(
|
23
|
+
'apiVersion' => '0.1',
|
24
|
+
'swaggerVersion' => '1.2',
|
25
|
+
'info' => {},
|
26
|
+
'produces' => ['application/json'],
|
27
|
+
'apis' => [
|
28
|
+
{ 'path' => '/something.{format}', 'description' => 'Operations about somethings' },
|
29
|
+
{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
|
31
30
|
]
|
32
|
-
|
31
|
+
)
|
33
32
|
end
|
34
|
-
|
35
|
-
context
|
36
|
-
it
|
37
|
-
|
38
|
-
|
39
|
-
api['path'].should start_with "/"
|
33
|
+
|
34
|
+
context 'path inside the apis array' do
|
35
|
+
it 'starts with a forward slash' do
|
36
|
+
subject['apis'].each do |api|
|
37
|
+
expect(api['path']).to start_with '/'
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
45
|
-
context 'with
|
46
|
-
|
47
|
-
|
43
|
+
context 'with additional info' do
|
44
|
+
def app
|
45
|
+
Class.new(Grape::API) do
|
48
46
|
format :json
|
49
47
|
add_swagger_documentation info: {
|
50
48
|
title: 'My API Title',
|
@@ -55,20 +53,18 @@ describe "Default API" do
|
|
55
53
|
contact: 'support@test.com'
|
56
54
|
}
|
57
55
|
end
|
58
|
-
get '/swagger_doc'
|
59
56
|
end
|
60
57
|
|
61
|
-
def app; ApiInfoTest; end
|
62
|
-
|
63
58
|
subject do
|
59
|
+
get '/swagger_doc'
|
64
60
|
JSON.parse(last_response.body)['info']
|
65
61
|
end
|
66
62
|
|
67
|
-
it '
|
63
|
+
it 'documents API title' do
|
68
64
|
expect(subject['title']).to eql('My API Title')
|
69
65
|
end
|
70
66
|
|
71
|
-
it '
|
67
|
+
it 'documents API description' do
|
72
68
|
expect(subject['description']).to eql('A description of my API')
|
73
69
|
end
|
74
70
|
|
@@ -76,17 +72,16 @@ describe "Default API" do
|
|
76
72
|
expect(subject['license']).to eql('Apache 2')
|
77
73
|
end
|
78
74
|
|
79
|
-
it '
|
75
|
+
it 'documents the license url' do
|
80
76
|
expect(subject['licenseUrl']).to eql('http://test.com')
|
81
77
|
end
|
82
78
|
|
83
|
-
it '
|
79
|
+
it 'documents the terms of service url' do
|
84
80
|
expect(subject['termsOfServiceUrl']).to eql('http://terms.com')
|
85
81
|
end
|
86
82
|
|
87
|
-
it '
|
83
|
+
it 'documents the contact email' do
|
88
84
|
expect(subject['contact']).to eql('support@test.com')
|
89
85
|
end
|
90
86
|
end
|
91
|
-
|
92
87
|
end
|
data/spec/form_params_spec.rb
CHANGED
@@ -1,29 +1,30 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
6
|
-
class FormParamApi < Grape::API
|
3
|
+
describe 'Form Params' do
|
4
|
+
def app
|
5
|
+
Class.new(Grape::API) do
|
7
6
|
format :json
|
8
7
|
|
9
8
|
params do
|
10
|
-
requires :name, type: String, desc:
|
9
|
+
requires :name, type: String, desc: 'name of item'
|
11
10
|
end
|
12
11
|
post '/items' do
|
13
12
|
{}
|
14
13
|
end
|
15
14
|
|
16
15
|
params do
|
17
|
-
requires :id, type: Integer, desc:
|
18
|
-
requires :name, type: String, desc:
|
16
|
+
requires :id, type: Integer, desc: 'id of item'
|
17
|
+
requires :name, type: String, desc: 'name of item'
|
18
|
+
requires :conditions, type: Integer, desc: 'conditions of item', values: [1, 2, 3]
|
19
19
|
end
|
20
20
|
put '/items/:id' do
|
21
21
|
{}
|
22
22
|
end
|
23
23
|
|
24
24
|
params do
|
25
|
-
requires :id, type: Integer, desc:
|
26
|
-
requires :name, type: String, desc:
|
25
|
+
requires :id, type: Integer, desc: 'id of item'
|
26
|
+
requires :name, type: String, desc: 'name of item'
|
27
|
+
optional :conditions, type: String, desc: 'conditions of item', values: proc { %w(1 2) }
|
27
28
|
end
|
28
29
|
patch '/items/:id' do
|
29
30
|
{}
|
@@ -33,51 +34,53 @@ describe "Form Params" do
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
it "retrieves the documentation form params" do
|
37
|
+
subject do
|
39
38
|
get '/swagger_doc/items.json'
|
39
|
+
JSON.parse(last_response.body)
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
42
|
+
it 'retrieves the documentation form params' do
|
43
|
+
expect(subject['apis']).to eq([
|
44
|
+
{
|
45
|
+
'path' => '/items.{format}',
|
46
|
+
'operations' => [
|
47
|
+
{
|
48
|
+
'notes' => '',
|
49
|
+
'summary' => '',
|
50
|
+
'nickname' => 'POST-items---format-',
|
51
|
+
'method' => 'POST',
|
52
|
+
'parameters' => [{ 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false }],
|
53
|
+
'type' => 'void'
|
54
|
+
}
|
55
|
+
]
|
56
|
+
}, {
|
57
|
+
'path' => '/items/{id}.{format}',
|
58
|
+
'operations' => [
|
59
|
+
{
|
60
|
+
'notes' => '',
|
61
|
+
'summary' => '',
|
62
|
+
'nickname' => 'PUT-items--id---format-',
|
63
|
+
'method' => 'PUT',
|
64
|
+
'parameters' => [
|
65
|
+
{ 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' },
|
66
|
+
{ 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false },
|
67
|
+
{ 'paramType' => 'form', 'name' => 'conditions', 'description' => 'conditions of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32', 'enum' => [1, 2, 3] }
|
68
|
+
],
|
69
|
+
'type' => 'void'
|
70
|
+
},
|
71
|
+
{
|
72
|
+
'notes' => '',
|
73
|
+
'summary' => '',
|
74
|
+
'nickname' => 'PATCH-items--id---format-',
|
75
|
+
'method' => 'PATCH',
|
76
|
+
'parameters' => [
|
77
|
+
{ 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' },
|
78
|
+
{ 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false },
|
79
|
+
{ 'paramType' => 'form', 'name' => 'conditions', 'description' => 'conditions of item', 'type' => 'string', 'required' => false, 'allowMultiple' => false, 'enum' => %w(1 2) }
|
80
|
+
],
|
81
|
+
'type' => 'void'
|
82
|
+
}
|
83
|
+
]
|
84
|
+
}])
|
82
85
|
end
|
83
86
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe 'helpers' do
|
4
4
|
|
5
5
|
before :all do
|
6
6
|
class HelperTestAPI < Grape::API
|
@@ -8,98 +8,137 @@ describe "helpers" do
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
subject do
|
12
|
+
api = Object.new
|
13
13
|
|
14
14
|
# after injecting grape-swagger into the Test API we get the helper methods
|
15
15
|
# back from the first endpoint's class (the API mounted by grape-swagger
|
16
16
|
# to serve the swagger_doc
|
17
17
|
|
18
|
-
|
18
|
+
api.extend HelperTestAPI.endpoints.first.options[:app].helpers
|
19
|
+
api
|
19
20
|
end
|
20
21
|
|
21
|
-
context
|
22
|
-
it
|
22
|
+
context 'parsing parameters' do
|
23
|
+
it 'parses params as query strings for a GET' do
|
23
24
|
params = {
|
24
|
-
name: { type: 'String', desc:
|
25
|
+
name: { type: 'String', desc: 'A name', required: true, default: 'default' },
|
25
26
|
level: 'max'
|
26
27
|
}
|
27
|
-
path =
|
28
|
-
method =
|
29
|
-
|
30
|
-
{ paramType:
|
31
|
-
{ paramType:
|
28
|
+
path = '/coolness'
|
29
|
+
method = 'GET'
|
30
|
+
expect(subject.parse_params(params, path, method)).to eq [
|
31
|
+
{ paramType: 'query', name: :name, description: 'A name', type: 'string', required: true, allowMultiple: false, defaultValue: 'default' },
|
32
|
+
{ paramType: 'query', name: :level, description: '', type: 'string', required: false, allowMultiple: false }
|
32
33
|
]
|
33
34
|
end
|
34
35
|
|
35
|
-
it
|
36
|
+
it 'parses params as form for a POST' do
|
36
37
|
params = {
|
37
|
-
name: { type: 'String', :
|
38
|
+
name: { type: 'String', desc: 'A name', required: true },
|
38
39
|
level: 'max'
|
39
40
|
}
|
40
|
-
path =
|
41
|
-
method =
|
42
|
-
|
43
|
-
{ paramType:
|
44
|
-
{ paramType:
|
41
|
+
path = '/coolness'
|
42
|
+
method = 'POST'
|
43
|
+
expect(subject.parse_params(params, path, method)).to eq [
|
44
|
+
{ paramType: 'form', name: :name, description: 'A name', type: 'string', required: true, allowMultiple: false },
|
45
|
+
{ paramType: 'form', name: :level, description: '', type: 'string', required: false, allowMultiple: false }
|
45
46
|
]
|
46
47
|
end
|
47
48
|
|
48
|
-
|
49
|
+
it 'parses file param' do
|
50
|
+
params = {
|
51
|
+
rack: {
|
52
|
+
type: 'Rack::Multipart::UploadedFile',
|
53
|
+
desc: 'rack file',
|
54
|
+
datafile: 'content',
|
55
|
+
required: true
|
56
|
+
},
|
57
|
+
rails: {
|
58
|
+
type: 'Hash',
|
59
|
+
desc: 'rails file',
|
60
|
+
datafile: 'content',
|
61
|
+
required: true
|
62
|
+
}
|
63
|
+
}
|
64
|
+
path = '/coolness'
|
65
|
+
method = 'POST'
|
66
|
+
expect(subject.parse_params(params, path, method)).to eq [
|
67
|
+
{
|
68
|
+
paramType: 'body',
|
69
|
+
name: :rack,
|
70
|
+
description: 'rack file',
|
71
|
+
type: 'File',
|
72
|
+
required: true,
|
73
|
+
allowMultiple: false
|
74
|
+
},
|
75
|
+
{
|
76
|
+
paramType: 'body',
|
77
|
+
name: :rails,
|
78
|
+
description: 'rails file',
|
79
|
+
type: 'File',
|
80
|
+
required: true,
|
81
|
+
allowMultiple: false
|
82
|
+
}
|
83
|
+
]
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'custom type' do
|
49
88
|
before :all do
|
50
89
|
class CustomType
|
51
90
|
end
|
52
91
|
end
|
53
|
-
it
|
92
|
+
it 'parses a custom parameters' do
|
54
93
|
params = {
|
55
|
-
option: { type: CustomType, desc:
|
94
|
+
option: { type: CustomType, desc: 'Custom option' }
|
56
95
|
}
|
57
|
-
path =
|
58
|
-
method =
|
59
|
-
|
60
|
-
{ paramType:
|
96
|
+
path = '/coolness'
|
97
|
+
method = 'GET'
|
98
|
+
expect(subject.parse_params(params, path, method)).to eq [
|
99
|
+
{ paramType: 'query', name: :option, description: 'Custom option', type: 'CustomType', required: false, allowMultiple: false }
|
61
100
|
]
|
62
101
|
end
|
63
102
|
end
|
64
103
|
|
65
104
|
end
|
66
105
|
|
67
|
-
context
|
68
|
-
it
|
69
|
-
path =
|
70
|
-
|
106
|
+
context 'parsing the path' do
|
107
|
+
it 'parses the path' do
|
108
|
+
path = ':abc/def(.:format)'
|
109
|
+
expect(subject.parse_path(path, nil)).to eq '{abc}/def.{format}'
|
71
110
|
end
|
72
111
|
|
73
|
-
it
|
74
|
-
path =
|
75
|
-
|
112
|
+
it 'parses a path that has vars with underscores in the name' do
|
113
|
+
path = 'abc/:def_g(.:format)'
|
114
|
+
expect(subject.parse_path(path, nil)).to eq 'abc/{def_g}.{format}'
|
76
115
|
end
|
77
116
|
|
78
|
-
it
|
79
|
-
path =
|
80
|
-
|
117
|
+
it 'parses a path that has vars with numbers in the name' do
|
118
|
+
path = 'abc/:sha1(.:format)'
|
119
|
+
expect(subject.parse_path(path, nil)).to eq 'abc/{sha1}.{format}'
|
81
120
|
end
|
82
121
|
|
83
|
-
it
|
84
|
-
path1 =
|
85
|
-
path2 =
|
86
|
-
|
87
|
-
|
122
|
+
it 'parses a path that has multiple variables' do
|
123
|
+
path1 = 'abc/:def/:geh(.:format)'
|
124
|
+
path2 = 'abc/:def:geh(.:format)'
|
125
|
+
expect(subject.parse_path(path1, nil)).to eq 'abc/{def}/{geh}.{format}'
|
126
|
+
expect(subject.parse_path(path2, nil)).to eq 'abc/{def}{geh}.{format}'
|
88
127
|
end
|
89
128
|
|
90
|
-
it
|
91
|
-
path =
|
92
|
-
|
129
|
+
it 'parses the path with a specified version' do
|
130
|
+
path = ':abc/{version}/def(.:format)'
|
131
|
+
expect(subject.parse_path(path, 'v1')).to eq '{abc}/v1/def.{format}'
|
93
132
|
end
|
94
133
|
end
|
95
134
|
|
96
|
-
context
|
97
|
-
it
|
135
|
+
context 'parsing header parameters' do
|
136
|
+
it 'parses params for the header' do
|
98
137
|
params = {
|
99
|
-
|
138
|
+
'XAuthToken' => { description: 'A required header.', required: true, default: 'default' }
|
100
139
|
}
|
101
|
-
|
102
|
-
{ paramType:
|
140
|
+
expect(subject.parse_header_params(params)).to eq [
|
141
|
+
{ paramType: 'header', name: 'XAuthToken', description: 'A required header.', type: 'String', required: true, defaultValue: 'default' }
|
103
142
|
]
|
104
143
|
end
|
105
144
|
end
|
data/spec/grape-swagger_spec.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Grape::API do
|
4
|
-
|
5
|
-
|
6
|
-
Grape::API.should respond_to :combined_routes
|
4
|
+
it 'added combined-routes' do
|
5
|
+
expect(Grape::API).to respond_to :combined_routes
|
7
6
|
end
|
8
7
|
|
9
|
-
it
|
10
|
-
Grape::API.
|
8
|
+
it 'added add_swagger_documentation' do
|
9
|
+
expect(Grape::API).to respond_to :add_swagger_documentation
|
11
10
|
end
|
12
11
|
|
12
|
+
it 'added combined-namespaces' do
|
13
|
+
expect(Grape::API).to respond_to :combined_namespaces
|
14
|
+
end
|
13
15
|
end
|