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
@@ -0,0 +1,23 @@
|
|
1
|
+
module GrapeSwagger
|
2
|
+
class Markdown
|
3
|
+
attr_reader :adapter
|
4
|
+
|
5
|
+
###
|
6
|
+
# Initializes the markdown class with an adapter.
|
7
|
+
# The adapter needs to implement the method markdown which will be called by this interface class.
|
8
|
+
# The adapters are responsible of loading the required markdown dependencies and throw errors.
|
9
|
+
###
|
10
|
+
def initialize(adapter)
|
11
|
+
adapter = adapter.new if adapter.is_a?(Class)
|
12
|
+
fail(ArgumentError, "The configured markdown adapter should implement the method #{ :markdown }") unless adapter.respond_to? :markdown
|
13
|
+
@adapter = adapter
|
14
|
+
end
|
15
|
+
|
16
|
+
###
|
17
|
+
# Calls markdown to the configured adapter.
|
18
|
+
###
|
19
|
+
def as_markdown(text)
|
20
|
+
@adapter.markdown(text)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module GrapeSwagger
|
2
|
+
class Markdown
|
3
|
+
class KramdownAdapter
|
4
|
+
attr_reader :options
|
5
|
+
|
6
|
+
###
|
7
|
+
# Initializes the kramdown adapter with options.
|
8
|
+
# See kramdown documentation what options can be passed.
|
9
|
+
# Default it uses Github flavoured markup as input and won't use coderay as converter for syntax highlighting.
|
10
|
+
# config: an hash of configuration options to be passed to the kramdown.
|
11
|
+
# usage:
|
12
|
+
# Add the kramdown gem to your gemfile or run:
|
13
|
+
# $ (sudo) gem install kramdown
|
14
|
+
#
|
15
|
+
# Then pass a new instance of GrapeSwagger::Markdown::KramdownAdapter as markdown option.
|
16
|
+
###
|
17
|
+
def initialize(config = {})
|
18
|
+
require 'kramdown'
|
19
|
+
defaults = {
|
20
|
+
input: 'GFM',
|
21
|
+
enable_coderay: false
|
22
|
+
}
|
23
|
+
@options = defaults.merge(config)
|
24
|
+
rescue LoadError
|
25
|
+
raise GrapeSwagger::Errors::MarkdownDependencyMissingError, 'kramdown'
|
26
|
+
end
|
27
|
+
|
28
|
+
###
|
29
|
+
# marks down the given text to html format.
|
30
|
+
# text: The text to be formatted.
|
31
|
+
###
|
32
|
+
def markdown(text)
|
33
|
+
Kramdown::Document.new(text, @options).to_html
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module GrapeSwagger
|
2
|
+
class Markdown
|
3
|
+
class RedcarpetAdapter
|
4
|
+
module RenderWithoutSyntaxHighlighter
|
5
|
+
require 'cgi'
|
6
|
+
|
7
|
+
def block_code(code, language)
|
8
|
+
language ||= 'text'
|
9
|
+
"<div class=\"code_highlight\"><pre><code class=\"highlight #{language}\">#{CGI.escapeHTML(code)}</code></pre></div>"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :extension_options
|
14
|
+
|
15
|
+
attr_reader :render_options
|
16
|
+
|
17
|
+
###
|
18
|
+
# Initializes the redcarpet adapter with markup options.
|
19
|
+
# See redcarpet documentation what options can be passed.
|
20
|
+
# Default it uses fenced_code_blocks, autolinks and rouge as syntax highlighter.
|
21
|
+
# To configure an highlighter add {highlighter: :value} to the extentions hash.
|
22
|
+
# Currently supported highlighters:
|
23
|
+
# :rouge
|
24
|
+
#
|
25
|
+
# extensions: an hash of configuration options to be passed to markdown.
|
26
|
+
# render_options: an hash of configuration options to be passed to renderer.
|
27
|
+
#
|
28
|
+
# usage:
|
29
|
+
# Add the redcarpet gem to your gemfile or run:
|
30
|
+
# $ (sudo) gem install redcarpet
|
31
|
+
# when you want to have rouge as syntax highlighter add rouge to the gemfile or run:
|
32
|
+
# $ (sudo) gem install rouge
|
33
|
+
#
|
34
|
+
# GrapeSwagger::Markdown::RedcarpetAdapter.new({highlighter: :none},{no_links: true}) # will use no syntax highlighter and won't render links.
|
35
|
+
###
|
36
|
+
def initialize(options = {})
|
37
|
+
require 'redcarpet'
|
38
|
+
extentions_defaults = {
|
39
|
+
fenced_code_blocks: true,
|
40
|
+
autolink: true
|
41
|
+
}
|
42
|
+
render_defaults = { highlighter: :rouge }
|
43
|
+
@extension_options = extentions_defaults.merge(options.fetch(:extensions, {}))
|
44
|
+
@render_options = render_defaults.merge(options.fetch(:render_options, {}))
|
45
|
+
@renderer = new_redcarpet_renderer(@render_options.delete(:highlighter)).new(@render_options)
|
46
|
+
@markdown = Redcarpet::Markdown.new(@renderer, @extension_options)
|
47
|
+
rescue LoadError
|
48
|
+
raise GrapeSwagger::Errors::MarkdownDependencyMissingError, 'redcarpet'
|
49
|
+
end
|
50
|
+
|
51
|
+
###
|
52
|
+
# Marks down the given text to html format.
|
53
|
+
###
|
54
|
+
def markdown(text)
|
55
|
+
@markdown.render(text)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
###
|
61
|
+
# Creates a new redcarpet renderer based on the highlighter given.
|
62
|
+
#
|
63
|
+
# render_options: options passed to the renderer.
|
64
|
+
#
|
65
|
+
# usage:
|
66
|
+
# new_redcarpet_renderer(:rouge) # uses rouge as highlighter.
|
67
|
+
# new_redcarpet_renderer # no highlight plugin
|
68
|
+
###
|
69
|
+
def new_redcarpet_renderer(syntax_highlighter = nil)
|
70
|
+
case syntax_highlighter
|
71
|
+
when :rouge
|
72
|
+
begin
|
73
|
+
Class.new(Redcarpet::Render::HTML) do
|
74
|
+
require 'rouge'
|
75
|
+
require 'rouge/plugins/redcarpet'
|
76
|
+
include Rouge::Plugins::Redcarpet
|
77
|
+
end
|
78
|
+
rescue LoadError
|
79
|
+
raise GrapeSwagger::Errors::MarkdownDependencyMissingError, 'rouge'
|
80
|
+
end
|
81
|
+
else
|
82
|
+
Class.new(Redcarpet::Render::HTML) do
|
83
|
+
include RenderWithoutSyntaxHighlighter
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'API Description' do
|
4
|
+
context 'with no additional options' do
|
5
|
+
subject do
|
6
|
+
Class.new(Grape::API) do
|
7
|
+
add_swagger_documentation
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'describes the API with defaults' do
|
12
|
+
routes = subject.endpoints.first.routes
|
13
|
+
expect(routes.count).to eq 2
|
14
|
+
expect(routes.first.route_description).to eq 'Swagger compatible API description'
|
15
|
+
expect(routes.first.route_params).to eq({})
|
16
|
+
expect(routes.last.route_description).to eq 'Swagger compatible API description for specific API'
|
17
|
+
expect(routes.last.route_params).to eq('name' => { desc: 'Resource name of mounted API', type: 'string', required: true })
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with additional options' do
|
22
|
+
subject do
|
23
|
+
Class.new(Grape::API) do
|
24
|
+
add_swagger_documentation \
|
25
|
+
api_documentation: { desc: 'First', params: { x: 1 }, xx: 11 },
|
26
|
+
specific_api_documentation: { desc: 'Second', params: { y: 42 }, yy: 4242 }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'describes the API with defaults' do
|
31
|
+
routes = subject.endpoints.first.routes
|
32
|
+
expect(routes.count).to eq 2
|
33
|
+
expect(routes.first.route_description).to eq 'First'
|
34
|
+
expect(routes.first.route_params).to eq(x: 1)
|
35
|
+
expect(routes.first.route_xx).to eq(11)
|
36
|
+
expect(routes.last.route_description).to eq 'Second'
|
37
|
+
expect(routes.last.route_params).to eq('name' => { desc: 'Resource name of mounted API', type: 'string', required: true }, y: 42)
|
38
|
+
expect(routes.last.route_yy).to eq(4242)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Global Models' do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
module Entities
|
7
|
+
module Some
|
8
|
+
class Thing < Grape::Entity
|
9
|
+
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
|
10
|
+
end
|
11
|
+
|
12
|
+
class CombinedThing < Grape::Entity
|
13
|
+
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
subject do
|
20
|
+
Class.new(Grape::API) do
|
21
|
+
desc 'This gets thing.', params: Entities::Some::Thing.documentation
|
22
|
+
get '/thing' do
|
23
|
+
thing = OpenStruct.new text: 'thing'
|
24
|
+
present thing, with: Entities::Some::Thing
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'This gets combined thing.',
|
28
|
+
params: Entities::Some::CombinedThing.documentation,
|
29
|
+
entity: Entities::Some::CombinedThing
|
30
|
+
get '/combined_thing' do
|
31
|
+
thing = OpenStruct.new text: 'thing'
|
32
|
+
present thing, with: Entities::Some::CombinedThing
|
33
|
+
end
|
34
|
+
|
35
|
+
add_swagger_documentation models: [Entities::Some::Thing]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def app
|
40
|
+
subject
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'includes models specified' do
|
44
|
+
get '/swagger_doc/thing.json'
|
45
|
+
json = JSON.parse(last_response.body)
|
46
|
+
expect(json['models']).to eq(
|
47
|
+
'Some::Thing' => {
|
48
|
+
'id' => 'Some::Thing',
|
49
|
+
'properties' => {
|
50
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' }
|
51
|
+
}
|
52
|
+
})
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'uses global models and route endpoint specific entities together' do
|
56
|
+
get '/swagger_doc/combined_thing.json'
|
57
|
+
json = JSON.parse(last_response.body)
|
58
|
+
|
59
|
+
expect(json['models']).to include(
|
60
|
+
'Some::Thing' => {
|
61
|
+
'id' => 'Some::Thing',
|
62
|
+
'properties' => {
|
63
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' }
|
64
|
+
}
|
65
|
+
})
|
66
|
+
|
67
|
+
expect(json['models']).to include(
|
68
|
+
'Some::CombinedThing' => {
|
69
|
+
'id' => 'Some::CombinedThing',
|
70
|
+
'properties' => {
|
71
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' }
|
72
|
+
}
|
73
|
+
})
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
data/spec/api_models_spec.rb
CHANGED
@@ -1,132 +1,229 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe 'API Models' do
|
4
4
|
|
5
5
|
before :all do
|
6
6
|
module Entities
|
7
7
|
class Something < Grape::Entity
|
8
|
-
expose :text, :
|
8
|
+
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Entities
|
13
|
+
class EnumValues < Grape::Entity
|
14
|
+
expose :gender, documentation: { type: 'string', desc: 'Content of something.', values: %w(Male Female) }
|
15
|
+
expose :number, documentation: { type: 'integer', desc: 'Content of something.', values: proc { [1, 2] } }
|
9
16
|
end
|
10
17
|
end
|
11
18
|
|
12
19
|
module Entities
|
13
20
|
module Some
|
14
21
|
class Thing < Grape::Entity
|
15
|
-
expose :text, :
|
22
|
+
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Entities
|
28
|
+
class ComposedOf < Grape::Entity
|
29
|
+
expose :part_text, documentation: { type: 'string', desc: 'Content of composedof.' }
|
30
|
+
end
|
31
|
+
|
32
|
+
class ComposedOfElse < Grape::Entity
|
33
|
+
def self.entity_name
|
34
|
+
'composed'
|
16
35
|
end
|
36
|
+
expose :part_text, documentation: { type: 'string', desc: 'Content of composedof else.' }
|
37
|
+
end
|
38
|
+
|
39
|
+
class SomeThingElse < Grape::Entity
|
40
|
+
expose :else_text, documentation: { type: 'string', desc: 'Content of something else.' }
|
41
|
+
expose :parts, using: Entities::ComposedOf, documentation: { type: 'ComposedOf',
|
42
|
+
is_array: true,
|
43
|
+
required: true }
|
44
|
+
|
45
|
+
expose :part, using: Entities::ComposedOfElse, documentation: { type: 'composes' }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module Entities
|
50
|
+
class AliasedThing < Grape::Entity
|
51
|
+
expose :something, as: :post, using: Entities::Something, documentation: { type: 'Something', desc: 'Reference to something.' }
|
17
52
|
end
|
18
53
|
end
|
54
|
+
end
|
19
55
|
|
20
|
-
|
56
|
+
def app
|
57
|
+
Class.new(Grape::API) do
|
21
58
|
format :json
|
22
|
-
desc 'This gets something.',
|
23
|
-
|
24
|
-
}
|
59
|
+
desc 'This gets something.', entity: Entities::Something
|
60
|
+
|
25
61
|
get '/something' do
|
26
62
|
something = OpenStruct.new text: 'something'
|
27
63
|
present something, with: Entities::Something
|
28
64
|
end
|
29
65
|
|
30
|
-
desc 'This gets thing.',
|
31
|
-
|
32
|
-
}
|
33
|
-
get "/thing" do
|
66
|
+
desc 'This gets thing.', entity: Entities::Some::Thing
|
67
|
+
get '/thing' do
|
34
68
|
thing = OpenStruct.new text: 'thing'
|
35
69
|
present thing, with: Entities::Some::Thing
|
36
70
|
end
|
71
|
+
|
72
|
+
desc 'This gets somthing else.', entity: Entities::SomeThingElse
|
73
|
+
get '/somethingelse' do
|
74
|
+
part = OpenStruct.new part_text: 'part thing'
|
75
|
+
thing = OpenStruct.new else_text: 'else thing', parts: [part], part: part
|
76
|
+
|
77
|
+
present thing, with: Entities::SomeThingElse
|
78
|
+
end
|
79
|
+
|
80
|
+
desc 'This tests the enum values in params and documentation.', entity: Entities::EnumValues, params: Entities::EnumValues.documentation
|
81
|
+
get '/enum_description_in_entity' do
|
82
|
+
|
83
|
+
enum_value = OpenStruct.new gender: 'Male', number: 1
|
84
|
+
|
85
|
+
present enum_value, with: Entities::EnumValues
|
86
|
+
end
|
87
|
+
|
88
|
+
desc 'This gets an aliased thing.', entity: Entities::AliasedThing
|
89
|
+
get '/aliasedthing' do
|
90
|
+
something = OpenStruct.new(something: OpenStruct.new(text: 'something'))
|
91
|
+
present something, with: Entities::AliasedThing
|
92
|
+
end
|
93
|
+
|
37
94
|
add_swagger_documentation
|
38
95
|
end
|
39
96
|
end
|
40
97
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
98
|
+
context 'swagger_doc' do
|
99
|
+
subject do
|
100
|
+
get '/swagger_doc'
|
101
|
+
JSON.parse(last_response.body)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'returns a swagger-compatible doc' do
|
105
|
+
expect(subject).to include(
|
106
|
+
'apiVersion' => '0.1',
|
107
|
+
'swaggerVersion' => '1.2',
|
108
|
+
'info' => {},
|
109
|
+
'produces' => ['application/json']
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'documents apis' do
|
114
|
+
expect(subject['apis']).to eq [
|
115
|
+
{ 'path' => '/something.{format}', 'description' => 'Operations about somethings' },
|
116
|
+
{ 'path' => '/thing.{format}', 'description' => 'Operations about things' },
|
117
|
+
{ 'path' => '/somethingelse.{format}', 'description' => 'Operations about somethingelses' },
|
118
|
+
{ 'path' => '/enum_description_in_entity.{format}', 'description' => 'Operations about enum_description_in_entities' },
|
119
|
+
{ 'path' => '/aliasedthing.{format}', 'description' => 'Operations about aliasedthings' },
|
120
|
+
{ 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
|
56
121
|
]
|
57
|
-
|
122
|
+
end
|
58
123
|
end
|
59
124
|
|
60
|
-
it
|
125
|
+
it 'returns type' do
|
61
126
|
get '/swagger_doc/something.json'
|
62
|
-
JSON.parse(last_response.body)
|
63
|
-
|
64
|
-
"swaggerVersion" => "1.2",
|
65
|
-
"basePath" => "http://example.org",
|
66
|
-
"resourcePath" => "",
|
67
|
-
"apis" => [{
|
68
|
-
"path" => "/something.{format}",
|
69
|
-
"operations" => [{
|
70
|
-
"produces" => [
|
71
|
-
"application/json"
|
72
|
-
],
|
73
|
-
"notes" => "",
|
74
|
-
"type" => "Something",
|
75
|
-
"summary" => "This gets something.",
|
76
|
-
"nickname" => "GET-something---format-",
|
77
|
-
"httpMethod" => "GET",
|
78
|
-
"parameters" => []
|
79
|
-
}]
|
80
|
-
}],
|
81
|
-
"models" => {
|
82
|
-
"Something" => {
|
83
|
-
"id" => "Something",
|
84
|
-
"name" => "Something",
|
85
|
-
"properties" => {
|
86
|
-
"text" => {
|
87
|
-
"type" => "string",
|
88
|
-
"description" => "Content of something."
|
89
|
-
}
|
90
|
-
}
|
91
|
-
}
|
92
|
-
}
|
93
|
-
}
|
127
|
+
result = JSON.parse(last_response.body)
|
128
|
+
expect(result['apis'].first['operations'].first['type']).to eq 'Something'
|
94
129
|
end
|
95
130
|
|
96
|
-
it
|
131
|
+
it 'includes nested type' do
|
97
132
|
get '/swagger_doc/thing.json'
|
98
|
-
JSON.parse(last_response.body)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
133
|
+
result = JSON.parse(last_response.body)
|
134
|
+
expect(result['apis'].first['operations'].first['type']).to eq 'Some::Thing'
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'includes entities which are only used as composition' do
|
138
|
+
get '/swagger_doc/somethingelse.json'
|
139
|
+
result = JSON.parse(last_response.body)
|
140
|
+
expect(result['apis']).to eq([{
|
141
|
+
'path' => '/somethingelse.{format}',
|
142
|
+
'operations' => [{
|
143
|
+
'notes' => '',
|
144
|
+
'type' => 'SomeThingElse',
|
145
|
+
'summary' => 'This gets somthing else.',
|
146
|
+
'nickname' => 'GET-somethingelse---format-',
|
147
|
+
'method' => 'GET',
|
148
|
+
'parameters' => []
|
149
|
+
}]
|
150
|
+
}])
|
151
|
+
|
152
|
+
expect(result['models']['SomeThingElse']).to include('id' => 'SomeThingElse',
|
153
|
+
'properties' => {
|
154
|
+
'else_text' => {
|
155
|
+
'type' => 'string',
|
156
|
+
'description' => 'Content of something else.'
|
157
|
+
},
|
158
|
+
'parts' => {
|
159
|
+
'type' => 'array',
|
160
|
+
'items' => { '$ref' => 'ComposedOf' }
|
161
|
+
},
|
162
|
+
'part' => { '$ref' => 'composes' }
|
163
|
+
},
|
164
|
+
'required' => ['parts']
|
165
|
+
|
166
|
+
)
|
167
|
+
|
168
|
+
expect(result['models']['ComposedOf']).to include(
|
169
|
+
'id' => 'ComposedOf',
|
170
|
+
'properties' => {
|
171
|
+
'part_text' => {
|
172
|
+
'type' => 'string',
|
173
|
+
'description' => 'Content of composedof.'
|
174
|
+
}
|
175
|
+
}
|
176
|
+
)
|
177
|
+
|
178
|
+
expect(result['models']['composed']).to include(
|
179
|
+
'id' => 'composed',
|
180
|
+
'properties' => {
|
181
|
+
'part_text' => {
|
182
|
+
'type' => 'string',
|
183
|
+
'description' => 'Content of composedof else.'
|
184
|
+
}
|
185
|
+
|
186
|
+
}
|
187
|
+
)
|
130
188
|
end
|
131
189
|
|
190
|
+
it 'includes enum values in params and documentation.' do
|
191
|
+
get '/swagger_doc/enum_description_in_entity.json'
|
192
|
+
result = JSON.parse(last_response.body)
|
193
|
+
expect(result['models']['EnumValues']).to eq(
|
194
|
+
'id' => 'EnumValues',
|
195
|
+
'properties' => {
|
196
|
+
'gender' => { 'type' => 'string', 'description' => 'Content of something.', 'enum' => %w(Male Female) },
|
197
|
+
'number' => { 'type' => 'integer', 'description' => 'Content of something.', 'enum' => [1, 2] }
|
198
|
+
}
|
199
|
+
)
|
200
|
+
|
201
|
+
expect(result['apis'][0]['operations'][0]).to include(
|
202
|
+
'parameters' =>
|
203
|
+
[
|
204
|
+
{ 'paramType' => 'query', 'name' => 'gender', 'description' => 'Content of something.', 'type' => 'string', 'required' => false, 'allowMultiple' => false, 'enum' => %w(Male Female) },
|
205
|
+
{ 'paramType' => 'query', 'name' => 'number', 'description' => 'Content of something.', 'type' => 'integer', 'required' => false, 'allowMultiple' => false, 'format' => 'int32', 'enum' => [1, 2] }
|
206
|
+
],
|
207
|
+
'type' => 'EnumValues'
|
208
|
+
)
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'includes referenced models in those with aliased references.' do
|
213
|
+
get '/swagger_doc/aliasedthing.json'
|
214
|
+
result = JSON.parse(last_response.body)
|
215
|
+
expect(result['models']['AliasedThing']).to eq(
|
216
|
+
'id' => 'AliasedThing',
|
217
|
+
'properties' => {
|
218
|
+
'post' => { '$ref' => 'Something', 'description' => 'Reference to something.' }
|
219
|
+
}
|
220
|
+
)
|
221
|
+
|
222
|
+
expect(result['models']['Something']).to eq(
|
223
|
+
'id' => 'Something',
|
224
|
+
'properties' => {
|
225
|
+
'text' => { 'type' => 'string', 'description' => 'Content of something.' }
|
226
|
+
}
|
227
|
+
)
|
228
|
+
end
|
132
229
|
end
|