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/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
|