grape-swagger 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/hide_api_spec.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe 'a hide mounted api' do
|
4
4
|
before :all do
|
5
5
|
class HideMountedApi < Grape::API
|
6
6
|
desc 'Show this endpoint'
|
7
7
|
get '/simple' do
|
8
|
-
{ :
|
8
|
+
{ foo: 'bar' }
|
9
9
|
end
|
10
10
|
|
11
|
-
desc 'Hide this endpoint',
|
12
|
-
|
13
|
-
|
11
|
+
desc 'Hide this endpoint',
|
12
|
+
hidden: true
|
13
|
+
|
14
14
|
get '/hide' do
|
15
|
-
{ :
|
15
|
+
{ foo: 'bar' }
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -22,39 +22,42 @@ describe "a hide mounted api" do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def app
|
25
|
+
def app
|
26
|
+
HideApi
|
27
|
+
end
|
26
28
|
|
27
|
-
|
29
|
+
subject do
|
28
30
|
get '/swagger_doc.json'
|
29
|
-
JSON.parse(last_response.body)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
31
|
+
JSON.parse(last_response.body)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "retrieves swagger-documentation that doesn't include hidden endpoints" do
|
35
|
+
expect(subject).to eq(
|
36
|
+
'apiVersion' => '0.1',
|
37
|
+
'swaggerVersion' => '1.2',
|
38
|
+
'info' => {},
|
39
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
40
|
+
'apis' => [
|
41
|
+
{ 'path' => '/simple.{format}', 'description' => 'Operations about simples' },
|
42
|
+
{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
|
39
43
|
]
|
40
|
-
|
44
|
+
)
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
|
-
|
45
|
-
describe "a hide mounted api with same namespace" do
|
48
|
+
describe 'a hide mounted api with same namespace' do
|
46
49
|
before :all do
|
47
50
|
class HideNamespaceMountedApi < Grape::API
|
48
51
|
desc 'Show this endpoint'
|
49
52
|
get '/simple/show' do
|
50
|
-
{ :
|
53
|
+
{ foo: 'bar' }
|
51
54
|
end
|
52
55
|
|
53
|
-
desc 'Hide this endpoint',
|
54
|
-
|
55
|
-
|
56
|
+
desc 'Hide this endpoint',
|
57
|
+
hidden: true
|
58
|
+
|
56
59
|
get '/simple/hide' do
|
57
|
-
{ :
|
60
|
+
{ foo: 'bar' }
|
58
61
|
end
|
59
62
|
end
|
60
63
|
|
@@ -64,43 +67,43 @@ describe "a hide mounted api with same namespace" do
|
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
67
|
-
def app
|
70
|
+
def app
|
71
|
+
HideNamespaceApi
|
72
|
+
end
|
68
73
|
|
69
|
-
it
|
74
|
+
it 'retrieves swagger-documentation on /swagger_doc' do
|
70
75
|
get '/swagger_doc.json'
|
71
|
-
JSON.parse(last_response.body).
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
{ "path" => "/swagger_doc/simple.{format}" },
|
80
|
-
{ "path" => "/swagger_doc/swagger_doc.{format}" }
|
76
|
+
expect(JSON.parse(last_response.body)).to eq(
|
77
|
+
'apiVersion' => '0.1',
|
78
|
+
'swaggerVersion' => '1.2',
|
79
|
+
'info' => {},
|
80
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
81
|
+
'apis' => [
|
82
|
+
{ 'path' => '/simple.{format}', 'description' => 'Operations about simples' },
|
83
|
+
{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
|
81
84
|
]
|
82
|
-
|
85
|
+
)
|
83
86
|
end
|
84
87
|
|
85
88
|
it "retrieves the documentation for mounted-api that doesn't include hidden endpoints" do
|
86
89
|
get '/swagger_doc/simple.json'
|
87
|
-
JSON.parse(last_response.body).
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
90
|
+
expect(JSON.parse(last_response.body)).to eq(
|
91
|
+
'apiVersion' => '0.1',
|
92
|
+
'swaggerVersion' => '1.2',
|
93
|
+
'basePath' => 'http://example.org',
|
94
|
+
'resourcePath' => '/simple',
|
95
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
96
|
+
'apis' => [{
|
97
|
+
'path' => '/simple/show.{format}',
|
98
|
+
'operations' => [{
|
99
|
+
'notes' => '',
|
100
|
+
'summary' => 'Show this endpoint',
|
101
|
+
'nickname' => 'GET-simple-show---format-',
|
102
|
+
'method' => 'GET',
|
103
|
+
'parameters' => [],
|
104
|
+
'type' => 'void'
|
102
105
|
}]
|
103
106
|
}]
|
104
|
-
|
107
|
+
)
|
105
108
|
end
|
106
109
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GrapeSwagger::Markdown::KramdownAdapter do
|
4
|
+
|
5
|
+
context 'initialization' do
|
6
|
+
it 'uses GFM as default input and disable coderay' do
|
7
|
+
adapter = GrapeSwagger::Markdown::KramdownAdapter.new
|
8
|
+
|
9
|
+
expect(adapter.options).to eq(input: 'GFM', enable_coderay: false)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'overrides default values' do
|
13
|
+
options = { input: 'kramdown', enable_coderay: true }
|
14
|
+
|
15
|
+
adapter = GrapeSwagger::Markdown::KramdownAdapter.new options
|
16
|
+
|
17
|
+
expect(adapter.options).to eq(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'raises an GrapeSwagger::Errors::MarkdownDependencyMissingError if module can not be required' do
|
21
|
+
expect_any_instance_of(Kernel).to receive(:require).with('kramdown').and_raise(LoadError)
|
22
|
+
|
23
|
+
expect { GrapeSwagger::Markdown::KramdownAdapter.new }.to raise_error(GrapeSwagger::Errors::MarkdownDependencyMissingError, 'Missing required dependency: kramdown')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'markdown' do
|
28
|
+
it 'marks down with the configured options' do
|
29
|
+
text = '# hello world #'
|
30
|
+
options = { input: 'GFM', enable_coderay: true, auto_ids: false, hard_wrap: true }
|
31
|
+
expect(Kramdown::Document).to receive(:new).with(text, options).and_call_original
|
32
|
+
|
33
|
+
output = GrapeSwagger::Markdown::KramdownAdapter.new(options).markdown(text)
|
34
|
+
|
35
|
+
expect(output).to include('<h1>hello world</h1>')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GrapeSwagger::Markdown do
|
4
|
+
context 'initialization' do
|
5
|
+
it 'initializes with an class that respond to markdown' do
|
6
|
+
adapter = GrapeSwagger::Markdown::KramdownAdapter.new
|
7
|
+
|
8
|
+
markdown = GrapeSwagger::Markdown.new adapter
|
9
|
+
|
10
|
+
expect(markdown.adapter).to eq(adapter)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'raises an exception when the class does not respond to markdown' do
|
14
|
+
expect { GrapeSwagger::Markdown.new(Class.new) }.to raise_error(ArgumentError, 'The configured markdown adapter should implement the method markdown')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'as_markdown' do
|
19
|
+
it 'calls markdown on the configured adapter' do
|
20
|
+
text = '# Hello world #'
|
21
|
+
adapter = GrapeSwagger::Markdown::KramdownAdapter.new
|
22
|
+
expect(adapter).to receive(:markdown).with(text)
|
23
|
+
|
24
|
+
GrapeSwagger::Markdown.new(adapter).as_markdown(text)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GrapeSwagger::Markdown::RedcarpetAdapter, unless: RUBY_PLATFORM.eql?('java') do
|
4
|
+
|
5
|
+
context 'initialization' do
|
6
|
+
context 'initialization' do
|
7
|
+
it 'uses fenced_code_blocks, auto_links and rouge as default.' do
|
8
|
+
expect_any_instance_of(GrapeSwagger::Markdown::RedcarpetAdapter).to receive(:new_redcarpet_renderer).with(:rouge).and_call_original
|
9
|
+
|
10
|
+
adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new
|
11
|
+
|
12
|
+
expect(adapter.extension_options).to eq(fenced_code_blocks: true, autolink: true)
|
13
|
+
expect(adapter.render_options).to eq({})
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'initializes with no highlighter.' do
|
17
|
+
expect_any_instance_of(GrapeSwagger::Markdown::RedcarpetAdapter).to receive(:new_redcarpet_renderer).with(:none).and_call_original
|
18
|
+
|
19
|
+
adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new render_options: { highlighter: :none }
|
20
|
+
|
21
|
+
expect(adapter.extension_options).to eq(fenced_code_blocks: true, autolink: true)
|
22
|
+
expect(adapter.render_options).to eq({})
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'overrides default values' do
|
26
|
+
extensions = { fenced_code_blocks: true, autolink: true }
|
27
|
+
render_options = { highlighter: :none, no_links: true }
|
28
|
+
|
29
|
+
adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new extensions: extensions, render_options: render_options
|
30
|
+
|
31
|
+
expect(adapter.extension_options).to eq(extensions)
|
32
|
+
expect(adapter.render_options).to eq(no_links: true)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'raises an GrapeSwagger::Errors::MarkdownDependencyMissingError if module can not be required.' do
|
36
|
+
expect_any_instance_of(Kernel).to receive(:require).with('redcarpet').and_raise(LoadError)
|
37
|
+
|
38
|
+
expect { GrapeSwagger::Markdown::RedcarpetAdapter.new }.to raise_error(GrapeSwagger::Errors::MarkdownDependencyMissingError, 'Missing required dependency: redcarpet')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'markdown' do
|
43
|
+
it 'marks down with the configured options' do
|
44
|
+
text = '# hello world #'
|
45
|
+
extensions = { fenced_code_blocks: true, autolink: true }
|
46
|
+
render_options = { highlighter: :none, no_links: true, highlighter: :none }
|
47
|
+
expect_any_instance_of(Redcarpet::Markdown).to receive(:render).with(text).and_call_original
|
48
|
+
|
49
|
+
output = GrapeSwagger::Markdown::RedcarpetAdapter.new(extensions: extensions, render_options: render_options).markdown(text)
|
50
|
+
|
51
|
+
expect(output).to include('<h1>hello world</h1>')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'new_redcarpet_renderer' do
|
56
|
+
it 'returns a rouge syntax highlighter' do
|
57
|
+
adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new
|
58
|
+
renderer = adapter.send(:new_redcarpet_renderer, :rouge)
|
59
|
+
|
60
|
+
expect(renderer).to include(Rouge::Plugins::Redcarpet)
|
61
|
+
expect(renderer.superclass).to be(Redcarpet::Render::HTML)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'throws an error when rouge syntax highlighter cant be included' do
|
65
|
+
adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new
|
66
|
+
|
67
|
+
expect_any_instance_of(Kernel).to receive(:require).with('rouge').and_raise(LoadError)
|
68
|
+
|
69
|
+
expect { adapter.send(:new_redcarpet_renderer, :rouge) }.to raise_error(GrapeSwagger::Errors::MarkdownDependencyMissingError, 'Missing required dependency: rouge')
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'returns a default syntax highlighter' do
|
73
|
+
adapter = GrapeSwagger::Markdown::RedcarpetAdapter.new
|
74
|
+
renderer = adapter.send(:new_redcarpet_renderer, :none)
|
75
|
+
|
76
|
+
expect(renderer).to include(GrapeSwagger::Markdown::RedcarpetAdapter::RenderWithoutSyntaxHighlighter)
|
77
|
+
expect(renderer.superclass).to be(Redcarpet::Render::HTML)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'namespace' do
|
4
|
+
context 'at root level' do
|
5
|
+
def app
|
6
|
+
Class.new(Grape::API) do
|
7
|
+
namespace :aspace, desc: 'Description for aspace' do
|
8
|
+
get '/'
|
9
|
+
end
|
10
|
+
add_swagger_documentation format: :json
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
subject do
|
15
|
+
get '/swagger_doc'
|
16
|
+
JSON.parse(last_response.body)['apis'][0]
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'shows the namespace description in the json spec' do
|
20
|
+
expect(subject['description']).to eql('Description for aspace')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'mounted' do
|
25
|
+
def app
|
26
|
+
namespaced_api = Class.new(Grape::API) do
|
27
|
+
namespace :aspace, desc: 'Description for aspace' do
|
28
|
+
get '/'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Class.new(Grape::API) do
|
33
|
+
mount namespaced_api
|
34
|
+
add_swagger_documentation format: :json
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
subject do
|
39
|
+
get '/swagger_doc'
|
40
|
+
JSON.parse(last_response.body)['apis'][0]
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'shows the namespace description in the json spec' do
|
44
|
+
expect(subject['description']).to eql('Description for aspace')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
context
|
3
|
+
describe 'options: ' do
|
4
|
+
context 'overriding the basepath' do
|
5
5
|
before :all do
|
6
6
|
|
7
7
|
class BasePathMountedApi < Grape::API
|
@@ -12,30 +12,35 @@ describe "options: " do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class SimpleApiWithBasePath < Grape::API
|
15
|
-
NON_DEFAULT_BASE_PATH =
|
15
|
+
NON_DEFAULT_BASE_PATH = 'http://www.breakcoregivesmewood.com'
|
16
16
|
|
17
17
|
mount BasePathMountedApi
|
18
|
-
add_swagger_documentation :
|
18
|
+
add_swagger_documentation base_path: NON_DEFAULT_BASE_PATH
|
19
19
|
end
|
20
20
|
|
21
21
|
end
|
22
22
|
|
23
|
-
def app
|
24
|
-
|
25
|
-
it "retrieves the given base-path on /swagger_doc" do
|
26
|
-
get '/swagger_doc.json'
|
27
|
-
JSON.parse(last_response.body)["basePath"].should == SimpleApiWithBasePath::NON_DEFAULT_BASE_PATH
|
23
|
+
def app
|
24
|
+
SimpleApiWithBasePath
|
28
25
|
end
|
29
26
|
|
30
|
-
|
27
|
+
subject do
|
31
28
|
get '/swagger_doc/something.json'
|
32
|
-
JSON.parse(last_response.body)
|
29
|
+
JSON.parse(last_response.body)
|
30
|
+
end
|
31
|
+
|
32
|
+
# it "retrieves the given base-path on /swagger_doc" do
|
33
|
+
# get '/swagger_doc.json'
|
34
|
+
# JSON.parse(last_response.body)["basePath"].should == SimpleApiWithBasePath::NON_DEFAULT_BASE_PATH
|
35
|
+
# end
|
36
|
+
|
37
|
+
it 'retrieves the same given base-path for mounted-api' do
|
38
|
+
expect(subject['basePath']).to eq SimpleApiWithBasePath::NON_DEFAULT_BASE_PATH
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
36
|
-
context
|
42
|
+
context 'overriding the basepath with a proc' do
|
37
43
|
before :all do
|
38
|
-
|
39
44
|
class ProcBasePathMountedApi < Grape::API
|
40
45
|
desc 'This gets something.'
|
41
46
|
get '/something' do
|
@@ -45,26 +50,31 @@ describe "options: " do
|
|
45
50
|
|
46
51
|
class SimpleApiWithProcBasePath < Grape::API
|
47
52
|
mount ProcBasePathMountedApi
|
48
|
-
add_swagger_documentation base_path:
|
53
|
+
add_swagger_documentation base_path: proc { |request| "#{request.base_url}/some_value" }
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
52
|
-
def app
|
53
|
-
|
54
|
-
it "retrieves the given base-path on /swagger_doc" do
|
55
|
-
get '/swagger_doc.json'
|
56
|
-
JSON.parse(last_response.body)["basePath"].should == "http://example.org/some_value"
|
57
|
+
def app
|
58
|
+
SimpleApiWithProcBasePath
|
57
59
|
end
|
58
60
|
|
59
|
-
|
61
|
+
subject do
|
60
62
|
get '/swagger_doc/something.json'
|
61
|
-
JSON.parse(last_response.body)
|
63
|
+
JSON.parse(last_response.body)
|
64
|
+
end
|
65
|
+
|
66
|
+
# it "retrieves the given base-path on /swagger_doc" do
|
67
|
+
# get '/swagger_doc.json'
|
68
|
+
# JSON.parse(last_response.body)["basePath"].should == "http://example.org/some_value"
|
69
|
+
# end
|
70
|
+
|
71
|
+
it 'retrieves the same given base-path for mounted-api' do
|
72
|
+
expect(subject['basePath']).to eq 'http://example.org/some_value'
|
62
73
|
end
|
63
74
|
end
|
64
75
|
|
65
|
-
context
|
76
|
+
context 'relative base_path' do
|
66
77
|
before :all do
|
67
|
-
|
68
78
|
class RelativeBasePathMountedApi < Grape::API
|
69
79
|
desc 'This gets something.'
|
70
80
|
get '/something' do
|
@@ -74,26 +84,32 @@ describe "options: " do
|
|
74
84
|
|
75
85
|
class SimpleApiWithRelativeBasePath < Grape::API
|
76
86
|
mount RelativeBasePathMountedApi
|
77
|
-
add_swagger_documentation base_path:
|
87
|
+
add_swagger_documentation base_path: '/some_value'
|
78
88
|
end
|
79
89
|
end
|
80
90
|
|
81
|
-
def app
|
91
|
+
def app
|
92
|
+
SimpleApiWithRelativeBasePath
|
93
|
+
end
|
82
94
|
|
83
|
-
|
84
|
-
get '/swagger_doc.json'
|
85
|
-
JSON.parse(last_response.body)
|
95
|
+
subject do
|
96
|
+
get '/swagger_doc/something.json'
|
97
|
+
JSON.parse(last_response.body)
|
86
98
|
end
|
87
99
|
|
88
|
-
it "retrieves the
|
100
|
+
# it "retrieves the given base-path on /swagger_doc" do
|
101
|
+
# get '/swagger_doc.json'
|
102
|
+
# JSON.parse(last_response.body)["basePath"].should == "http://example.org/some_value"
|
103
|
+
# end
|
104
|
+
|
105
|
+
it 'retrieves the same given base-path for mounted-api' do
|
89
106
|
get '/swagger_doc/something.json'
|
90
|
-
|
107
|
+
expect(subject['basePath']).to eq 'http://example.org/some_value'
|
91
108
|
end
|
92
109
|
end
|
93
110
|
|
94
|
-
context
|
111
|
+
context 'overriding the version' do
|
95
112
|
before :all do
|
96
|
-
|
97
113
|
class ApiVersionMountedApi < Grape::API
|
98
114
|
desc 'This gets something.'
|
99
115
|
get '/something' do
|
@@ -102,29 +118,30 @@ describe "options: " do
|
|
102
118
|
end
|
103
119
|
|
104
120
|
class SimpleApiWithApiVersion < Grape::API
|
105
|
-
API_VERSION =
|
121
|
+
API_VERSION = '101'
|
106
122
|
|
107
123
|
mount ApiVersionMountedApi
|
108
|
-
add_swagger_documentation :
|
124
|
+
add_swagger_documentation api_version: API_VERSION
|
109
125
|
end
|
110
126
|
end
|
111
127
|
|
112
|
-
def app
|
128
|
+
def app
|
129
|
+
SimpleApiWithApiVersion
|
130
|
+
end
|
113
131
|
|
114
|
-
it
|
132
|
+
it 'retrieves the api version on /swagger_doc' do
|
115
133
|
get '/swagger_doc.json'
|
116
|
-
JSON.parse(last_response.body)[
|
134
|
+
expect(JSON.parse(last_response.body)['apiVersion']).to eq SimpleApiWithApiVersion::API_VERSION
|
117
135
|
end
|
118
136
|
|
119
|
-
it
|
137
|
+
it 'retrieves the same api version for mounted-api' do
|
120
138
|
get '/swagger_doc/something.json'
|
121
|
-
JSON.parse(last_response.body)[
|
139
|
+
expect(JSON.parse(last_response.body)['apiVersion']).to eq SimpleApiWithApiVersion::API_VERSION
|
122
140
|
end
|
123
141
|
end
|
124
142
|
|
125
|
-
context
|
143
|
+
context 'mounting in a versioned api' do
|
126
144
|
before :all do
|
127
|
-
|
128
145
|
class SimpleApiToMountInVersionedApi < Grape::API
|
129
146
|
desc 'This gets something.'
|
130
147
|
get '/something' do
|
@@ -133,58 +150,57 @@ describe "options: " do
|
|
133
150
|
end
|
134
151
|
|
135
152
|
class SimpleApiWithVersionInPath < Grape::API
|
136
|
-
version 'v1', :
|
153
|
+
version 'v1', using: :path
|
137
154
|
|
138
155
|
mount SimpleApiToMountInVersionedApi
|
139
156
|
add_swagger_documentation
|
140
157
|
end
|
141
158
|
end
|
142
159
|
|
143
|
-
def app
|
160
|
+
def app
|
161
|
+
SimpleApiWithVersionInPath
|
162
|
+
end
|
144
163
|
|
145
|
-
it
|
164
|
+
it 'gets the documentation on a versioned path /v1/swagger_doc' do
|
146
165
|
get '/v1/swagger_doc.json'
|
147
|
-
|
148
|
-
JSON.parse(last_response.body).
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
{ "path" => "/v1/swagger_doc/something.{format}" },
|
157
|
-
{ "path" => "/v1/swagger_doc/swagger_doc.{format}" }
|
166
|
+
expect(last_response.status).to eq 200
|
167
|
+
expect(JSON.parse(last_response.body)).to eq(
|
168
|
+
'apiVersion' => '0.1',
|
169
|
+
'swaggerVersion' => '1.2',
|
170
|
+
'info' => {},
|
171
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
172
|
+
'apis' => [
|
173
|
+
{ 'path' => '/something.{format}', 'description' => 'Operations about somethings' },
|
174
|
+
{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
|
158
175
|
]
|
159
|
-
|
176
|
+
)
|
160
177
|
end
|
161
178
|
|
162
|
-
it
|
179
|
+
it 'gets the resource specific documentation on a versioned path /v1/swagger_doc/something' do
|
163
180
|
get '/v1/swagger_doc/something.json'
|
164
|
-
last_response.status.
|
165
|
-
JSON.parse(last_response.body).
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
181
|
+
expect(last_response.status).to eq 200
|
182
|
+
expect(JSON.parse(last_response.body)).to eq(
|
183
|
+
'apiVersion' => '0.1',
|
184
|
+
'swaggerVersion' => '1.2',
|
185
|
+
'basePath' => 'http://example.org',
|
186
|
+
'resourcePath' => '/something',
|
187
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
188
|
+
'apis' => [{
|
189
|
+
'path' => '/0.1/something.{format}',
|
190
|
+
'operations' => [{
|
191
|
+
'notes' => '',
|
192
|
+
'summary' => 'This gets something.',
|
193
|
+
'nickname' => 'GET--version-something---format-',
|
194
|
+
'method' => 'GET',
|
195
|
+
'parameters' => [],
|
196
|
+
'type' => 'void'
|
180
197
|
}]
|
181
198
|
}]
|
182
|
-
|
199
|
+
)
|
183
200
|
end
|
184
|
-
|
185
201
|
end
|
186
202
|
|
187
|
-
context
|
203
|
+
context 'overriding hiding the documentation paths' do
|
188
204
|
before :all do
|
189
205
|
class HideDocumentationPathMountedApi < Grape::API
|
190
206
|
desc 'This gets something.'
|
@@ -195,29 +211,33 @@ describe "options: " do
|
|
195
211
|
|
196
212
|
class SimpleApiWithHiddenDocumentation < Grape::API
|
197
213
|
mount HideDocumentationPathMountedApi
|
198
|
-
add_swagger_documentation :
|
214
|
+
add_swagger_documentation hide_documentation_path: true
|
199
215
|
end
|
200
216
|
end
|
201
217
|
|
202
|
-
def app
|
218
|
+
def app
|
219
|
+
SimpleApiWithHiddenDocumentation
|
220
|
+
end
|
203
221
|
|
204
|
-
|
222
|
+
subject do
|
205
223
|
get '/swagger_doc.json'
|
206
|
-
JSON.parse(last_response.body)
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
224
|
+
JSON.parse(last_response.body)
|
225
|
+
end
|
226
|
+
|
227
|
+
it "it doesn't show the documentation path on /swagger_doc" do
|
228
|
+
expect(subject).to eq(
|
229
|
+
'apiVersion' => '0.1',
|
230
|
+
'swaggerVersion' => '1.2',
|
231
|
+
'info' => {},
|
232
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
233
|
+
'apis' => [
|
234
|
+
{ 'path' => '/something.{format}', 'description' => 'Operations about somethings' }
|
215
235
|
]
|
216
|
-
|
236
|
+
)
|
217
237
|
end
|
218
238
|
end
|
219
239
|
|
220
|
-
context
|
240
|
+
context 'overriding hiding the documentation paths in prefixed API' do
|
221
241
|
before :all do
|
222
242
|
class HideDocumentationPathPrefixedMountedApi < Grape::API
|
223
243
|
desc 'This gets something.'
|
@@ -227,40 +247,46 @@ describe "options: " do
|
|
227
247
|
end
|
228
248
|
|
229
249
|
class PrefixedApiWithHiddenDocumentation < Grape::API
|
230
|
-
prefix
|
250
|
+
prefix 'abc'
|
231
251
|
mount HideDocumentationPathPrefixedMountedApi
|
232
|
-
add_swagger_documentation :
|
252
|
+
add_swagger_documentation hide_documentation_path: true
|
233
253
|
end
|
234
254
|
|
235
255
|
end
|
236
256
|
|
237
|
-
def app
|
257
|
+
def app
|
258
|
+
PrefixedApiWithHiddenDocumentation
|
259
|
+
end
|
238
260
|
|
239
|
-
|
261
|
+
subject do
|
240
262
|
get '/abc/swagger_doc/something.json'
|
241
|
-
JSON.parse(last_response.body)
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
263
|
+
JSON.parse(last_response.body)
|
264
|
+
end
|
265
|
+
|
266
|
+
it "it doesn't show the documentation path on /abc/swagger_doc/something.json" do
|
267
|
+
expect(subject).to eq(
|
268
|
+
'apiVersion' => '0.1',
|
269
|
+
'swaggerVersion' => '1.2',
|
270
|
+
'basePath' => 'http://example.org',
|
271
|
+
'resourcePath' => '/something',
|
272
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
273
|
+
'apis' => [{
|
274
|
+
'path' => '/abc/something.{format}',
|
275
|
+
'operations' => [{
|
276
|
+
'notes' => '',
|
277
|
+
'summary' => 'This gets something.',
|
278
|
+
'nickname' => 'GET-abc-something---format-',
|
279
|
+
'method' => 'GET',
|
280
|
+
'parameters' => [],
|
281
|
+
'type' => 'void'
|
256
282
|
}]
|
257
283
|
}]
|
258
|
-
|
284
|
+
)
|
259
285
|
end
|
260
286
|
|
261
287
|
end
|
262
288
|
|
263
|
-
context
|
289
|
+
context 'overriding hiding the documentation paths in prefixed and versioned API' do
|
264
290
|
before :all do
|
265
291
|
class HideDocumentationPathMountedApi2 < Grape::API
|
266
292
|
desc 'This gets something.'
|
@@ -270,43 +296,49 @@ describe "options: " do
|
|
270
296
|
end
|
271
297
|
|
272
298
|
class PrefixedAndVersionedApiWithHiddenDocumentation < Grape::API
|
273
|
-
prefix
|
274
|
-
version 'v20', :
|
299
|
+
prefix 'abc'
|
300
|
+
version 'v20', using: :path
|
275
301
|
|
276
302
|
mount HideDocumentationPathMountedApi2
|
277
303
|
|
278
|
-
add_swagger_documentation :
|
304
|
+
add_swagger_documentation hide_documentation_path: true, api_version: version
|
279
305
|
end
|
280
306
|
end
|
281
307
|
|
282
|
-
def app
|
308
|
+
def app
|
309
|
+
PrefixedAndVersionedApiWithHiddenDocumentation
|
310
|
+
end
|
283
311
|
|
284
|
-
|
312
|
+
subject do
|
285
313
|
get '/abc/v20/swagger_doc/something.json'
|
314
|
+
JSON.parse(last_response.body)
|
315
|
+
end
|
286
316
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
317
|
+
it "it doesn't show the documentation path on /abc/v1/swagger_doc/something.json" do
|
318
|
+
expect(subject).to eq(
|
319
|
+
'apiVersion' => 'v20',
|
320
|
+
'swaggerVersion' => '1.2',
|
321
|
+
'basePath' => 'http://example.org',
|
322
|
+
'resourcePath' => '/something',
|
323
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
324
|
+
'apis' => [{
|
325
|
+
'path' => '/abc/v20/something.{format}',
|
326
|
+
'operations' => [{
|
327
|
+
'notes' => nil,
|
328
|
+
'notes' => '',
|
329
|
+
'summary' => 'This gets something.',
|
330
|
+
'nickname' => 'GET-abc--version-something---format-',
|
331
|
+
'method' => 'GET',
|
332
|
+
'parameters' => [],
|
333
|
+
'type' => 'void'
|
302
334
|
}]
|
303
335
|
}]
|
304
|
-
|
336
|
+
)
|
305
337
|
end
|
306
338
|
|
307
339
|
end
|
308
340
|
|
309
|
-
context
|
341
|
+
context 'overriding the mount-path' do
|
310
342
|
before :all do
|
311
343
|
class DifferentMountMountedApi < Grape::API
|
312
344
|
desc 'This gets something.'
|
@@ -316,42 +348,41 @@ describe "options: " do
|
|
316
348
|
end
|
317
349
|
|
318
350
|
class SimpleApiWithDifferentMount < Grape::API
|
319
|
-
MOUNT_PATH =
|
351
|
+
MOUNT_PATH = '/api_doc'
|
320
352
|
|
321
353
|
mount DifferentMountMountedApi
|
322
|
-
add_swagger_documentation :
|
354
|
+
add_swagger_documentation mount_path: MOUNT_PATH
|
323
355
|
end
|
324
356
|
end
|
325
357
|
|
326
|
-
def app
|
327
|
-
|
328
|
-
|
329
|
-
it "retrieves the given base-path on /api_doc" do
|
330
|
-
get '/api_doc.json'
|
331
|
-
JSON.parse(last_response.body)["apis"].each do |api|
|
332
|
-
api["path"].should start_with SimpleApiWithDifferentMount::MOUNT_PATH
|
333
|
-
end
|
358
|
+
def app
|
359
|
+
SimpleApiWithDifferentMount
|
334
360
|
end
|
335
361
|
|
336
|
-
it "retrieves the
|
362
|
+
# it "retrieves the given base-path on /api_doc" do
|
363
|
+
# get '/api_doc.json'
|
364
|
+
# JSON.parse(last_response.body)["apis"].each do |api|
|
365
|
+
# api["path"].should start_with SimpleApiWithDifferentMount::MOUNT_PATH
|
366
|
+
# end
|
367
|
+
# end
|
368
|
+
|
369
|
+
it 'retrieves the same given base-path for mounted-api' do
|
337
370
|
get '/api_doc/something.json'
|
338
|
-
JSON.parse(last_response.body)[
|
339
|
-
api[
|
371
|
+
JSON.parse(last_response.body)['apis'].each do |api|
|
372
|
+
expect(api['path']).to_not start_with SimpleApiWithDifferentMount::MOUNT_PATH
|
340
373
|
end
|
341
374
|
end
|
342
375
|
|
343
|
-
it
|
376
|
+
it 'does not respond to swagger_doc' do
|
344
377
|
get '/swagger_doc.json'
|
345
|
-
last_response.status.
|
378
|
+
expect(last_response.status).to eq 404
|
346
379
|
end
|
347
380
|
end
|
348
381
|
|
349
|
-
context
|
382
|
+
context 'overriding the markdown' do
|
350
383
|
before :all do
|
351
384
|
class MarkDownMountedApi < Grape::API
|
352
|
-
desc 'This gets something.',
|
353
|
-
:notes => '_test_'
|
354
|
-
}
|
385
|
+
desc 'This gets something.', notes: '_test_'
|
355
386
|
get '/something' do
|
356
387
|
{ bla: 'something' }
|
357
388
|
end
|
@@ -359,35 +390,54 @@ describe "options: " do
|
|
359
390
|
|
360
391
|
class SimpleApiWithMarkdown < Grape::API
|
361
392
|
mount MarkDownMountedApi
|
362
|
-
add_swagger_documentation :
|
393
|
+
add_swagger_documentation markdown: GrapeSwagger::Markdown::KramdownAdapter.new, info: { description: '_test_' }
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
subject do
|
398
|
+
Class.new(Grape::API) do
|
399
|
+
mount MarkDownMountedApi
|
363
400
|
end
|
364
401
|
end
|
365
402
|
|
366
|
-
def app
|
403
|
+
def app
|
404
|
+
SimpleApiWithMarkdown
|
405
|
+
end
|
367
406
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
407
|
+
context 'with instance' do
|
408
|
+
before do
|
409
|
+
subject.add_swagger_documentation markdown: GrapeSwagger::Markdown::KramdownAdapter.new, info: { description: '_test_' }
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'parses markdown for a mounted-api' do
|
413
|
+
get '/swagger_doc/something.json'
|
414
|
+
expect(JSON.parse(last_response.body)['apis'][0]['operations'][0]['notes']).to eq("<p><em>test</em></p>\n")
|
415
|
+
end
|
416
|
+
|
417
|
+
it 'parses markdown for swagger info' do
|
418
|
+
get '/swagger_doc.json'
|
419
|
+
expect(JSON.parse(last_response.body)['info']).to eq('description' => "<p><em>test</em></p>\n")
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
context 'with class' do
|
424
|
+
before do
|
425
|
+
subject.add_swagger_documentation markdown: GrapeSwagger::Markdown::KramdownAdapter, info: { description: '_test_' }
|
426
|
+
end
|
427
|
+
|
428
|
+
it 'parses markdown for a mounted-api' do
|
429
|
+
get '/swagger_doc/something.json'
|
430
|
+
expect(JSON.parse(last_response.body)['apis'][0]['operations'][0]['notes']).to eq("<p><em>test</em></p>\n")
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'parses markdown for swagger info' do
|
434
|
+
get '/swagger_doc.json'
|
435
|
+
expect(JSON.parse(last_response.body)['info']).to eq('description' => "<p><em>test</em></p>\n")
|
436
|
+
end
|
387
437
|
end
|
388
438
|
end
|
389
439
|
|
390
|
-
context
|
440
|
+
context 'prefixed and versioned API' do
|
391
441
|
before :all do
|
392
442
|
class VersionedMountedApi < Grape::API
|
393
443
|
prefix 'api'
|
@@ -401,22 +451,24 @@ describe "options: " do
|
|
401
451
|
|
402
452
|
class SimpleApiWithVersion < Grape::API
|
403
453
|
mount VersionedMountedApi
|
404
|
-
add_swagger_documentation :
|
454
|
+
add_swagger_documentation api_version: 'v1'
|
405
455
|
end
|
406
456
|
end
|
407
457
|
|
408
|
-
def app
|
458
|
+
def app
|
459
|
+
SimpleApiWithVersion
|
460
|
+
end
|
409
461
|
|
410
|
-
it
|
462
|
+
it 'parses version and places it in the path' do
|
411
463
|
get '/swagger_doc/something.json'
|
412
464
|
|
413
|
-
JSON.parse(last_response.body)[
|
414
|
-
api[
|
465
|
+
JSON.parse(last_response.body)['apis'].each do |api|
|
466
|
+
expect(api['path']).to start_with '/api/v1/'
|
415
467
|
end
|
416
468
|
end
|
417
469
|
end
|
418
470
|
|
419
|
-
context
|
471
|
+
context 'protected API' do
|
420
472
|
before :all do
|
421
473
|
class ProtectedApi < Grape::API
|
422
474
|
desc 'This gets something.'
|
@@ -426,25 +478,27 @@ describe "options: " do
|
|
426
478
|
end
|
427
479
|
|
428
480
|
class SimpleApiWithProtection < Grape::API
|
429
|
-
mount ProtectedApi
|
481
|
+
mount ::ProtectedApi
|
430
482
|
add_swagger_documentation
|
431
483
|
end
|
432
484
|
end
|
433
485
|
|
434
|
-
def app
|
435
|
-
|
436
|
-
it "uses https schema in mount point" do
|
437
|
-
get '/swagger_doc.json', {}, 'rack.url_scheme' => 'https'
|
438
|
-
JSON.parse(last_response.body)["basePath"].should == "https://example.org:80"
|
486
|
+
def app
|
487
|
+
SimpleApiWithProtection
|
439
488
|
end
|
440
489
|
|
441
|
-
it "uses https schema in
|
490
|
+
# it "uses https schema in mount point" do
|
491
|
+
# get '/swagger_doc.json', {}, 'rack.url_scheme' => 'https'
|
492
|
+
# JSON.parse(last_response.body)["basePath"].should == "https://example.org:80"
|
493
|
+
# end
|
494
|
+
|
495
|
+
it 'uses https schema in endpoint doc' do
|
442
496
|
get '/swagger_doc/something.json', {}, 'rack.url_scheme' => 'https'
|
443
|
-
JSON.parse(last_response.body)[
|
497
|
+
expect(JSON.parse(last_response.body)['basePath']).to eq 'https://example.org:80'
|
444
498
|
end
|
445
499
|
end
|
446
500
|
|
447
|
-
context
|
501
|
+
context ':hide_format' do
|
448
502
|
before :all do
|
449
503
|
class HidePathsApi < Grape::API
|
450
504
|
desc 'This gets something.'
|
@@ -455,21 +509,23 @@ describe "options: " do
|
|
455
509
|
|
456
510
|
class SimpleApiWithHiddenPaths < Grape::API
|
457
511
|
mount ProtectedApi
|
458
|
-
add_swagger_documentation :
|
512
|
+
add_swagger_documentation hide_format: true
|
459
513
|
end
|
460
514
|
end
|
461
515
|
|
462
|
-
def app
|
516
|
+
def app
|
517
|
+
SimpleApiWithHiddenPaths
|
518
|
+
end
|
463
519
|
|
464
|
-
it
|
520
|
+
it 'has no formats' do
|
465
521
|
get '/swagger_doc/something.json'
|
466
|
-
JSON.parse(last_response.body)[
|
467
|
-
api[
|
522
|
+
JSON.parse(last_response.body)['apis'].each do |api|
|
523
|
+
expect(api['path']).to_not end_with '.{format}'
|
468
524
|
end
|
469
525
|
end
|
470
526
|
end
|
471
527
|
|
472
|
-
context
|
528
|
+
context 'multiple documentations' do
|
473
529
|
before :all do
|
474
530
|
class FirstApi < Grape::API
|
475
531
|
desc 'This is the first API'
|
@@ -495,40 +551,38 @@ describe "options: " do
|
|
495
551
|
end
|
496
552
|
end
|
497
553
|
|
498
|
-
def app
|
554
|
+
def app
|
555
|
+
SimpleApiWithMultipleMountedDocumentations
|
556
|
+
end
|
499
557
|
|
500
|
-
it
|
558
|
+
it 'retrieves the first swagger-documentation on /first/swagger_doc' do
|
501
559
|
get '/first/swagger_doc.json'
|
502
|
-
JSON.parse(last_response.body).
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
"apis" => [
|
510
|
-
{ "path" => "/first/swagger_doc/first.{format}" }
|
560
|
+
expect(JSON.parse(last_response.body)).to eq(
|
561
|
+
'apiVersion' => '0.1',
|
562
|
+
'swaggerVersion' => '1.2',
|
563
|
+
'info' => {},
|
564
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
565
|
+
'apis' => [
|
566
|
+
{ 'path' => '/first.{format}', 'description' => 'Operations about firsts' }
|
511
567
|
]
|
512
|
-
|
568
|
+
)
|
513
569
|
end
|
514
570
|
|
515
|
-
it
|
571
|
+
it 'retrieves the second swagger-documentation on /second/swagger_doc' do
|
516
572
|
get '/second/swagger_doc.json'
|
517
|
-
JSON.parse(last_response.body).
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
"apis" => [
|
525
|
-
{ "path" => "/second/swagger_doc/second.{format}" }
|
573
|
+
expect(JSON.parse(last_response.body)).to eq(
|
574
|
+
'apiVersion' => '0.1',
|
575
|
+
'swaggerVersion' => '1.2',
|
576
|
+
'info' => {},
|
577
|
+
'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
|
578
|
+
'apis' => [
|
579
|
+
{ 'path' => '/second.{format}', 'description' => 'Operations about seconds' }
|
526
580
|
]
|
527
|
-
|
581
|
+
)
|
528
582
|
end
|
529
583
|
end
|
530
584
|
|
531
|
-
context
|
585
|
+
context ':formatting' do
|
532
586
|
before :all do
|
533
587
|
class JSONDefaultFormatAPI < Grape::API
|
534
588
|
desc 'This gets something.'
|
@@ -543,13 +597,109 @@ describe "options: " do
|
|
543
597
|
end
|
544
598
|
end
|
545
599
|
|
546
|
-
def app
|
600
|
+
def app
|
601
|
+
SimpleJSONFormattedAPI
|
602
|
+
end
|
547
603
|
|
548
|
-
|
604
|
+
subject do
|
549
605
|
get '/swagger_doc/something'
|
606
|
+
last_response
|
607
|
+
end
|
608
|
+
|
609
|
+
it 'defaults to JSON format when none is specified' do
|
610
|
+
get '/swagger_doc/something'
|
611
|
+
expect(subject.headers['Content-Type']).to eq 'application/json'
|
612
|
+
expect(-> { JSON.parse(subject.body) }).to_not raise_error
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
context 'documented namespace description' do
|
617
|
+
before :all do
|
618
|
+
class NestedNamespaceWithDescAPI < Grape::API
|
619
|
+
namespace :nestedspace, desc: 'Description for nested space' do
|
620
|
+
desc 'Nested get'
|
621
|
+
get '/somethingelse' do
|
622
|
+
{ foo: 'bar' }
|
623
|
+
end
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
627
|
+
class NamespaceWithDescAPI < Grape::API
|
628
|
+
namespace :aspace, desc: 'Description for aspace' do
|
629
|
+
desc 'This gets something.'
|
630
|
+
get '/something' do
|
631
|
+
{ bla: 'something' }
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
635
|
+
mount NestedNamespaceWithDescAPI
|
636
|
+
|
637
|
+
add_swagger_documentation format: :json
|
638
|
+
end
|
639
|
+
get '/swagger_doc'
|
640
|
+
end
|
641
|
+
|
642
|
+
def app
|
643
|
+
NamespaceWithDescAPI
|
644
|
+
end
|
550
645
|
|
551
|
-
|
646
|
+
subject do
|
647
|
+
JSON.parse(last_response.body)['apis']
|
552
648
|
end
|
553
649
|
|
650
|
+
it 'shows the namespace description in the json spec' do
|
651
|
+
expect(subject[0]['description']).to eql('Description for aspace')
|
652
|
+
end
|
653
|
+
|
654
|
+
it 'shows the nested namespace description in the json spec' do
|
655
|
+
expect(subject[1]['description']).to eql('Description for nested space')
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
context 'override nickname' do
|
660
|
+
before :all do
|
661
|
+
class NicknameAPI < Grape::API
|
662
|
+
desc 'This gets something.', nickname: 'getSomething'
|
663
|
+
get '/something' do
|
664
|
+
{ bla: 'something' }
|
665
|
+
end
|
666
|
+
add_swagger_documentation
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
def app
|
671
|
+
NicknameAPI
|
672
|
+
end
|
673
|
+
|
674
|
+
it 'documents the user-specified nickname' do
|
675
|
+
get '/swagger_doc/something.json'
|
676
|
+
ret = JSON.parse(last_response.body)
|
677
|
+
expect(ret['apis'][0]['operations'][0]['nickname']).to eq 'getSomething'
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
context 'invalid name' do
|
682
|
+
subject do
|
683
|
+
Class.new(Grape::API) do
|
684
|
+
get 'hidden', hidden: true
|
685
|
+
add_swagger_documentation
|
686
|
+
end
|
687
|
+
end
|
688
|
+
|
689
|
+
def app
|
690
|
+
subject
|
691
|
+
end
|
692
|
+
|
693
|
+
it 'returns a 404 for an non-existent route' do
|
694
|
+
get '/swagger_doc/invalid.json'
|
695
|
+
expect(last_response.status).to eq 404
|
696
|
+
expect(JSON.parse(last_response.body)).to eq('error' => 'Not Found')
|
697
|
+
end
|
698
|
+
|
699
|
+
it 'returns a 404 for a hidden route' do
|
700
|
+
get '/swagger_doc/hidden.json'
|
701
|
+
expect(last_response.status).to eq 404
|
702
|
+
expect(JSON.parse(last_response.body)).to eq('error' => 'Not Found')
|
703
|
+
end
|
554
704
|
end
|
555
705
|
end
|