grape-swagger 0.31.1 → 0.32.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +9 -2
- data/.travis.yml +6 -6
- data/CHANGELOG.md +20 -0
- data/Gemfile +7 -2
- data/README.md +3 -2
- data/lib/grape-swagger.rb +122 -116
- data/lib/grape-swagger/doc_methods/parse_params.rb +1 -1
- data/lib/grape-swagger/endpoint.rb +15 -15
- data/lib/grape-swagger/instance.rb +7 -0
- data/lib/grape-swagger/version.rb +1 -1
- data/spec/lib/data_type_spec.rb +18 -22
- data/spec/lib/endpoint/params_parser_spec.rb +11 -9
- data/spec/lib/move_params_spec.rb +1 -1
- data/spec/support/model_parsers/entity_parser.rb +1 -1
- data/spec/support/model_parsers/mock_parser.rb +1 -1
- data/spec/support/model_parsers/representable_parser.rb +1 -1
- data/spec/swagger_v2/api_swagger_v2_headers_spec.rb +1 -1
- data/spec/swagger_v2/default_api_spec.rb +1 -1
- data/spec/swagger_v2/endpoint_versioned_path_spec.rb +69 -26
- data/spec/swagger_v2/grape-swagger_spec.rb +4 -4
- data/spec/swagger_v2/guarded_endpoint_spec.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea7cb947847696a10190ade08cfbe8bf19364a4b5855d932abda009c672122c4
|
4
|
+
data.tar.gz: 8a9c2f4a2bff62b247b795b6082d825d9403382ef56626f93ed697b4b654dc54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45dfe914ee2225ab36174fd182563a56aaf8cfb78f9aaccdc8a4070e47acb41e0010f31c283d6bef76819a296539457da5095191e17e181d0acf4271f743bcf0
|
7
|
+
data.tar.gz: 0ab65509589c8537b7f77810dd76be2fb50e092796570a333704a9b06893e8a5756988465214752df3b0a2093a731e33e10b229b7c879568e28d2f247a79dd68
|
data/.rubocop_todo.yml
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2018-
|
3
|
+
# on 2018-11-04 01:12:26 +0100 using RuboCop version 0.60.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: Include.
|
11
|
+
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
|
12
|
+
Bundler/DuplicatedGem:
|
13
|
+
Exclude:
|
14
|
+
- 'Gemfile'
|
15
|
+
|
9
16
|
# Offense count: 1
|
10
17
|
# Configuration parameters: Include.
|
11
18
|
# Include: **/*.gemspec
|
@@ -35,6 +42,6 @@ Style/ClassVars:
|
|
35
42
|
Exclude:
|
36
43
|
- 'lib/grape-swagger/doc_methods.rb'
|
37
44
|
|
38
|
-
# Offense count:
|
45
|
+
# Offense count: 22
|
39
46
|
Style/Documentation:
|
40
47
|
Enabled: false
|
data/.travis.yml
CHANGED
@@ -11,22 +11,22 @@ after_success:
|
|
11
11
|
- bundle exec danger
|
12
12
|
|
13
13
|
rvm:
|
14
|
-
- 2.5
|
15
|
-
- 2.
|
14
|
+
- 2.4.5
|
15
|
+
- 2.5.3
|
16
|
+
- 2.6.0-preview2
|
16
17
|
env:
|
17
18
|
- MODEL_PARSER=grape-swagger-entity
|
18
19
|
- MODEL_PARSER=grape-swagger-representable
|
19
|
-
- GRAPE_VERSION=0.17.0
|
20
|
-
- GRAPE_VERSION=0.18.0
|
21
20
|
- GRAPE_VERSION=0.19.2
|
22
21
|
- GRAPE_VERSION=1.0.3
|
22
|
+
- GRAPE_VERSION=1.2.0
|
23
23
|
- GRAPE_VERSION=HEAD
|
24
24
|
|
25
25
|
matrix:
|
26
26
|
fast_finish: true
|
27
27
|
|
28
28
|
include:
|
29
|
-
- rvm: 2.3.
|
29
|
+
- rvm: 2.3.8
|
30
30
|
env:
|
31
31
|
- rvm: ruby-head
|
32
32
|
env:
|
@@ -34,6 +34,6 @@ matrix:
|
|
34
34
|
env:
|
35
35
|
|
36
36
|
allow_failures:
|
37
|
-
- rvm: 2.3.
|
37
|
+
- rvm: 2.3.8
|
38
38
|
- rvm: ruby-head
|
39
39
|
- rvm: jruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
### Next
|
2
|
+
|
3
|
+
#### Features
|
4
|
+
|
5
|
+
* Your contribution here.
|
6
|
+
|
7
|
+
#### Fixes
|
8
|
+
|
9
|
+
* Your contribution here.
|
10
|
+
|
11
|
+
### 0.32.0 (November 26, 2018)
|
12
|
+
|
13
|
+
#### Features
|
14
|
+
|
15
|
+
* [#717](https://github.com/ruby-grape/grape-swagger/pull/717): Adds support for grape >= 1.2 - [@myxoh](https://github.com/myxoh).
|
16
|
+
|
17
|
+
#### Fixes
|
18
|
+
|
19
|
+
* [#720](https://github.com/ruby-grape/grape-swagger/pull/720): Fix: corrected `termsOfService` field name in additional info - [@dblock](https://github.com/dblock).
|
20
|
+
|
1
21
|
### 0.31.1 (October 23, 2018)
|
2
22
|
|
3
23
|
#### Features
|
data/Gemfile
CHANGED
@@ -6,7 +6,7 @@ ruby RUBY_VERSION
|
|
6
6
|
|
7
7
|
gemspec
|
8
8
|
|
9
|
-
gem 'grape', case version = ENV['GRAPE_VERSION'] || '~> 1.
|
9
|
+
gem 'grape', case version = ENV['GRAPE_VERSION'] || '~> 1.2'
|
10
10
|
when 'HEAD'
|
11
11
|
{ git: 'https://github.com/ruby-grape/grape' }
|
12
12
|
else
|
@@ -26,7 +26,12 @@ group :development, :test do
|
|
26
26
|
gem 'rake'
|
27
27
|
gem 'rdoc'
|
28
28
|
gem 'rspec', '~> 3.0'
|
29
|
-
|
29
|
+
# TODO: change back after 2.6.0 release and updated rubocop version
|
30
|
+
if RUBY_VERSION == '2.6.0'
|
31
|
+
gem 'rubocop', git: 'https://github.com/rubocop-hq/rubocop.git', require: false
|
32
|
+
else
|
33
|
+
gem 'rubocop', '~> 0.60', require: false
|
34
|
+
end
|
30
35
|
end
|
31
36
|
|
32
37
|
group :test do
|
data/README.md
CHANGED
@@ -48,8 +48,9 @@ grape-swagger | swagger spec | grape | grape-entity | represen
|
|
48
48
|
0.10.5 | 1.2 | >= 0.10.0 ... <= 0.14.0 | < 0.5.0 | n/a |
|
49
49
|
0.11.0 | 1.2 | >= 0.16.2 | < 0.5.0 | n/a |
|
50
50
|
0.25.2 | 2.0 | >= 0.14.0 ... <= 0.18.0 | <= 0.6.0 | >= 2.4.1 |
|
51
|
-
0.26.0 | 2.0 | >= 0.16.2
|
52
|
-
0.27.0 | 2.0 | >= 0.16.2
|
51
|
+
0.26.0 | 2.0 | >= 0.16.2 <= 1.1.0 | <= 0.6.1 | >= 2.4.1 |
|
52
|
+
0.27.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | >= 0.5.0 | >= 2.4.1 |
|
53
|
+
0.32.0 | 2.0 | >= 0.16.2 | >= 0.5.0 | >= 2.4.1 |
|
53
54
|
|
54
55
|
|
55
56
|
## Swagger-Spec <a name="swagger-spec"></a>
|
data/lib/grape-swagger.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'grape'
|
4
4
|
|
5
|
+
require 'grape-swagger/instance'
|
6
|
+
|
5
7
|
require 'grape-swagger/version'
|
6
8
|
require 'grape-swagger/endpoint'
|
7
9
|
require 'grape-swagger/errors'
|
@@ -18,148 +20,152 @@ module GrapeSwagger
|
|
18
20
|
autoload :Rake, 'grape-swagger/rake/oapi_tasks'
|
19
21
|
end
|
20
22
|
|
21
|
-
module
|
22
|
-
|
23
|
-
class << self
|
24
|
-
attr_accessor :combined_routes, :combined_namespaces, :combined_namespace_routes, :combined_namespace_identifiers
|
25
|
-
|
26
|
-
def add_swagger_documentation(options = {})
|
27
|
-
documentation_class = create_documentation_class
|
23
|
+
module SwaggerRouting
|
24
|
+
private
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
def combine_routes(app, doc_klass)
|
27
|
+
app.routes.each do |route|
|
28
|
+
route_path = route.path
|
29
|
+
route_match = route_path.split(/^.*?#{route.prefix.to_s}/).last
|
30
|
+
next unless route_match
|
33
31
|
|
34
|
-
|
32
|
+
route_match = route_match.match('\/([\w|-]*?)[\.\/\(]') || route_match.match('\/([\w|-]*)$')
|
33
|
+
next unless route_match
|
35
34
|
|
36
|
-
|
37
|
-
|
35
|
+
resource = route_match.captures.first
|
36
|
+
resource = '/' if resource.empty?
|
37
|
+
@target_class.combined_routes[resource] ||= []
|
38
|
+
next if doc_klass.hide_documentation_path && route.path.match(/#{doc_klass.mount_path}($|\/|\(\.)/)
|
38
39
|
|
39
|
-
|
40
|
-
|
40
|
+
@target_class.combined_routes[resource].unshift route
|
41
|
+
end
|
42
|
+
end
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
+
def determine_namespaced_routes(name, parent_route)
|
45
|
+
if parent_route.nil?
|
46
|
+
@target_class.combined_routes.values.flatten
|
47
|
+
else
|
48
|
+
parent_route.reject do |route|
|
49
|
+
!route_path_start_with?(route, name) || !route_instance_variable_equals?(route, name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
44
53
|
|
45
|
-
|
46
|
-
|
47
|
-
|
54
|
+
def combine_namespace_routes(namespaces)
|
55
|
+
# iterate over each single namespace
|
56
|
+
namespaces.each_key do |name, _|
|
57
|
+
# get the parent route for the namespace
|
58
|
+
parent_route_name = extract_parent_route(name)
|
59
|
+
parent_route = @target_class.combined_routes[parent_route_name]
|
60
|
+
# fetch all routes that are within the current namespace
|
61
|
+
namespace_routes = determine_namespaced_routes(name, parent_route)
|
62
|
+
|
63
|
+
# default case when not explicitly specified or nested == true
|
64
|
+
standalone_namespaces = namespaces.reject do |_, ns|
|
65
|
+
!ns.options.key?(:swagger) ||
|
66
|
+
!ns.options[:swagger].key?(:nested) ||
|
67
|
+
ns.options[:swagger][:nested] != false
|
68
|
+
end
|
48
69
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
70
|
+
parent_standalone_namespaces = standalone_namespaces.select { |ns_name, _| name.start_with?(ns_name) }
|
71
|
+
# add only to the main route
|
72
|
+
# if the namespace is not within any other namespace appearing as standalone resource
|
73
|
+
# rubocop:disable Style/Next
|
74
|
+
if parent_standalone_namespaces.empty?
|
75
|
+
# default option, append namespace methods to parent route
|
76
|
+
parent_route = @target_class.combined_namespace_routes.key?(parent_route_name)
|
77
|
+
@target_class.combined_namespace_routes[parent_route_name] = [] unless parent_route
|
78
|
+
@target_class.combined_namespace_routes[parent_route_name].push(*namespace_routes)
|
54
79
|
end
|
80
|
+
# rubocop:enable Style/Next
|
81
|
+
end
|
82
|
+
end
|
55
83
|
|
56
|
-
|
84
|
+
def extract_parent_route(name)
|
85
|
+
route_name = name.match(%r{^/?([^/]*).*$})[1]
|
86
|
+
return route_name unless route_name.include? ':'
|
57
87
|
|
58
|
-
|
59
|
-
|
60
|
-
|
88
|
+
matches = name.match(/\/[a-z]+/)
|
89
|
+
matches.nil? ? route_name : matches[0].delete('/')
|
90
|
+
end
|
61
91
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
route_match = route_path.split(/^.*?#{route.prefix.to_s}/).last
|
66
|
-
next unless route_match
|
92
|
+
def route_instance_variable(route)
|
93
|
+
route.instance_variable_get(:@options)[:namespace]
|
94
|
+
end
|
67
95
|
|
68
|
-
|
69
|
-
|
96
|
+
def route_instance_variable_equals?(route, name)
|
97
|
+
route_instance_variable(route) == "/#{name}" ||
|
98
|
+
route_instance_variable(route) == "/:version/#{name}"
|
99
|
+
end
|
70
100
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
next if doc_klass.hide_documentation_path && route.path.match(/#{doc_klass.mount_path}($|\/|\(\.)/)
|
101
|
+
def route_path_start_with?(route, name)
|
102
|
+
route_prefix = route.prefix ? "/#{route.prefix}/#{name}" : "/#{name}"
|
103
|
+
route_versioned_prefix = route.prefix ? "/#{route.prefix}/:version/#{name}" : "/:version/#{name}"
|
75
104
|
|
76
|
-
|
77
|
-
|
78
|
-
|
105
|
+
route.path.start_with?(route_prefix, route_versioned_prefix)
|
106
|
+
end
|
107
|
+
end
|
79
108
|
|
80
|
-
|
81
|
-
|
82
|
-
|
109
|
+
module SwaggerDocumentationAdder
|
110
|
+
attr_accessor :combined_namespaces, :combined_namespace_identifiers
|
111
|
+
attr_accessor :combined_routes, :combined_namespace_routes
|
112
|
+
include SwaggerRouting
|
83
113
|
|
84
|
-
|
85
|
-
|
86
|
-
mount_path = (endpoint.namespace_stackable(:mount_path) || []).join('/')
|
87
|
-
full_namespace = (mount_path + endpoint.namespace).sub(/\/{2,}/, '/').sub(/^\//, '')
|
88
|
-
@target_class.combined_namespaces[full_namespace] = ns if ns
|
114
|
+
def add_swagger_documentation(options = {})
|
115
|
+
documentation_class = create_documentation_class
|
89
116
|
|
90
|
-
|
91
|
-
|
92
|
-
|
117
|
+
version_for(options)
|
118
|
+
options = { target_class: self }.merge(options)
|
119
|
+
@target_class = options[:target_class]
|
120
|
+
auth_wrapper = options[:endpoint_auth_wrapper] || Class.new
|
93
121
|
|
94
|
-
|
95
|
-
if parent_route.nil?
|
96
|
-
@target_class.combined_routes.values.flatten
|
97
|
-
else
|
98
|
-
parent_route.reject do |route|
|
99
|
-
!route_path_start_with?(route, name) || !route_instance_variable_equals?(route, name)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
122
|
+
use auth_wrapper if auth_wrapper.method_defined?(:before) && !middleware.flatten.include?(auth_wrapper)
|
103
123
|
|
104
|
-
|
105
|
-
|
106
|
-
namespaces.each_key do |name, _|
|
107
|
-
# get the parent route for the namespace
|
108
|
-
parent_route_name = extract_parent_route(name)
|
109
|
-
parent_route = @target_class.combined_routes[parent_route_name]
|
110
|
-
# fetch all routes that are within the current namespace
|
111
|
-
namespace_routes = determine_namespaced_routes(name, parent_route)
|
112
|
-
|
113
|
-
# default case when not explicitly specified or nested == true
|
114
|
-
standalone_namespaces = namespaces.reject do |_, ns|
|
115
|
-
!ns.options.key?(:swagger) ||
|
116
|
-
!ns.options[:swagger].key?(:nested) ||
|
117
|
-
ns.options[:swagger][:nested] != false
|
118
|
-
end
|
119
|
-
|
120
|
-
parent_standalone_namespaces = standalone_namespaces.select { |ns_name, _| name.start_with?(ns_name) }
|
121
|
-
# add only to the main route
|
122
|
-
# if the namespace is not within any other namespace appearing as standalone resource
|
123
|
-
# rubocop:disable Style/Next
|
124
|
-
if parent_standalone_namespaces.empty?
|
125
|
-
# default option, append namespace methods to parent route
|
126
|
-
parent_route = @target_class.combined_namespace_routes.key?(parent_route_name)
|
127
|
-
@target_class.combined_namespace_routes[parent_route_name] = [] unless parent_route
|
128
|
-
@target_class.combined_namespace_routes[parent_route_name].push(*namespace_routes)
|
129
|
-
end
|
130
|
-
# rubocop:enable Style/Next
|
131
|
-
end
|
132
|
-
end
|
124
|
+
documentation_class.setup(options)
|
125
|
+
mount(documentation_class)
|
133
126
|
|
134
|
-
|
135
|
-
|
136
|
-
return route_name unless route_name.include? ':'
|
127
|
+
@target_class.combined_routes = {}
|
128
|
+
combine_routes(@target_class, documentation_class)
|
137
129
|
|
138
|
-
|
139
|
-
|
140
|
-
end
|
130
|
+
@target_class.combined_namespaces = {}
|
131
|
+
combine_namespaces(@target_class)
|
141
132
|
|
142
|
-
|
143
|
-
|
144
|
-
|
133
|
+
@target_class.combined_namespace_routes = {}
|
134
|
+
@target_class.combined_namespace_identifiers = {}
|
135
|
+
combine_namespace_routes(@target_class.combined_namespaces)
|
145
136
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
137
|
+
exclusive_route_keys = @target_class.combined_routes.keys - @target_class.combined_namespaces.keys
|
138
|
+
exclusive_route_keys.each do |key|
|
139
|
+
@target_class.combined_namespace_routes[key] = @target_class.combined_routes[key]
|
140
|
+
end
|
141
|
+
documentation_class
|
142
|
+
end
|
150
143
|
|
151
|
-
|
152
|
-
route_prefix = route.prefix ? "/#{route.prefix}/#{name}" : "/#{name}"
|
153
|
-
route_versioned_prefix = route.prefix ? "/#{route.prefix}/:version/#{name}" : "/:version/#{name}"
|
144
|
+
private
|
154
145
|
|
155
|
-
|
156
|
-
|
146
|
+
def version_for(options)
|
147
|
+
options[:version] = version if version
|
148
|
+
end
|
157
149
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
150
|
+
def combine_namespaces(app)
|
151
|
+
app.endpoints.each do |endpoint|
|
152
|
+
ns = endpoint.namespace_stackable(:namespace).last
|
153
|
+
|
154
|
+
# use the full namespace here (not the latest level only)
|
155
|
+
# and strip leading slash
|
156
|
+
mount_path = (endpoint.namespace_stackable(:mount_path) || []).join('/')
|
157
|
+
full_namespace = (mount_path + endpoint.namespace).sub(/\/{2,}/, '/').sub(/^\//, '')
|
158
|
+
@target_class.combined_namespaces[full_namespace] = ns if ns
|
159
|
+
|
160
|
+
combine_namespaces(endpoint.options[:app]) if endpoint.options[:app]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def create_documentation_class
|
165
|
+
Class.new(GrapeInstance) do
|
166
|
+
extend GrapeSwagger::DocMethods
|
163
167
|
end
|
164
168
|
end
|
165
169
|
end
|
170
|
+
|
171
|
+
GrapeInstance.extend(SwaggerDocumentationAdder)
|
@@ -25,15 +25,15 @@ module Grape
|
|
25
25
|
# required keys for SwaggerObject
|
26
26
|
def swagger_object(target_class, request, options)
|
27
27
|
object = {
|
28
|
-
info:
|
29
|
-
swagger:
|
30
|
-
produces:
|
31
|
-
authorizations:
|
28
|
+
info: info_object(options[:info].merge(version: options[:doc_version])),
|
29
|
+
swagger: '2.0',
|
30
|
+
produces: content_types_for(target_class),
|
31
|
+
authorizations: options[:authorizations],
|
32
32
|
securityDefinitions: options[:security_definitions],
|
33
|
-
security:
|
34
|
-
host:
|
35
|
-
basePath:
|
36
|
-
schemes:
|
33
|
+
security: options[:security],
|
34
|
+
host: GrapeSwagger::DocMethods::OptionalObject.build(:host, options, request),
|
35
|
+
basePath: GrapeSwagger::DocMethods::OptionalObject.build(:base_path, options, request),
|
36
|
+
schemes: options[:schemes].is_a?(String) ? [options[:schemes]] : options[:schemes]
|
37
37
|
}
|
38
38
|
|
39
39
|
GrapeSwagger::DocMethods::Extensions.add_extensions_to_root(options, object)
|
@@ -43,12 +43,12 @@ module Grape
|
|
43
43
|
# building info object
|
44
44
|
def info_object(infos)
|
45
45
|
result = {
|
46
|
-
title:
|
47
|
-
description:
|
48
|
-
|
49
|
-
contact:
|
50
|
-
license:
|
51
|
-
version:
|
46
|
+
title: infos[:title] || 'API title',
|
47
|
+
description: infos[:description],
|
48
|
+
termsOfService: infos[:terms_of_service_url],
|
49
|
+
contact: contact_object(infos),
|
50
|
+
license: license_object(infos),
|
51
|
+
version: infos[:version]
|
52
52
|
}
|
53
53
|
|
54
54
|
GrapeSwagger::DocMethods::Extensions.add_extensions_to_info(infos, result)
|
@@ -61,7 +61,7 @@ module Grape
|
|
61
61
|
def license_object(infos)
|
62
62
|
{
|
63
63
|
name: infos.delete(:license),
|
64
|
-
url:
|
64
|
+
url: infos.delete(:license_url)
|
65
65
|
}.delete_if { |_, value| value.blank? }
|
66
66
|
end
|
67
67
|
|
data/spec/lib/data_type_spec.rb
CHANGED
@@ -3,15 +3,6 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe GrapeSwagger::DocMethods::DataType do
|
6
|
-
before do
|
7
|
-
stub_const 'MyEntity', Class.new
|
8
|
-
MyEntity.class_eval do
|
9
|
-
def self.entity_name
|
10
|
-
'MyInteger'
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
6
|
subject { described_class.call(value) }
|
16
7
|
|
17
8
|
describe 'standards' do
|
@@ -26,78 +17,83 @@ describe GrapeSwagger::DocMethods::DataType do
|
|
26
17
|
describe 'Hash' do
|
27
18
|
let(:value) { { type: Hash } }
|
28
19
|
|
29
|
-
it {
|
20
|
+
it { is_expected.to eq 'object' }
|
30
21
|
end
|
31
22
|
|
32
23
|
describe 'Multi types in a string' do
|
33
24
|
let(:value) { { type: '[String, Integer]' } }
|
34
25
|
|
35
|
-
it {
|
26
|
+
it { is_expected.to eq 'string' }
|
36
27
|
end
|
37
28
|
|
38
29
|
describe 'Multi types in a string stating with A' do
|
39
30
|
let(:value) { { type: '[Apple, Orange]' } }
|
40
31
|
|
41
|
-
it {
|
32
|
+
it { is_expected.to eq 'Apple' }
|
42
33
|
end
|
43
34
|
|
44
35
|
describe 'Multi types in array' do
|
45
36
|
let(:value) { { type: [String, Integer] } }
|
46
37
|
|
47
|
-
it {
|
38
|
+
it { is_expected.to eq 'string' }
|
48
39
|
end
|
49
40
|
|
50
41
|
describe 'Types in array with entity_name' do
|
42
|
+
before do
|
43
|
+
stub_const 'MyEntity', Class.new
|
44
|
+
allow(MyEntity).to receive(:entity_name).and_return 'MyInteger'
|
45
|
+
end
|
46
|
+
|
51
47
|
let(:value) { { type: '[MyEntity]' } }
|
52
48
|
|
53
|
-
it {
|
49
|
+
it { is_expected.to eq 'MyInteger' }
|
54
50
|
end
|
55
51
|
|
56
52
|
describe 'Rack::Multipart::UploadedFile' do
|
57
53
|
let(:value) { { type: Rack::Multipart::UploadedFile } }
|
58
54
|
|
59
|
-
it {
|
55
|
+
it { is_expected.to eq 'file' }
|
60
56
|
end
|
61
57
|
|
62
58
|
describe 'Virtus::Attribute::Boolean' do
|
63
59
|
let(:value) { { type: Virtus::Attribute::Boolean } }
|
64
60
|
|
65
|
-
it {
|
61
|
+
it { is_expected.to eq 'boolean' }
|
66
62
|
end
|
67
63
|
|
68
64
|
describe 'BigDecimal' do
|
69
65
|
let(:value) { { type: BigDecimal } }
|
70
66
|
|
71
|
-
it {
|
67
|
+
it { is_expected.to eq 'double' }
|
72
68
|
end
|
73
69
|
|
74
70
|
describe 'DateTime' do
|
75
71
|
let(:value) { { type: DateTime } }
|
76
72
|
|
77
|
-
it {
|
73
|
+
it { is_expected.to eq 'dateTime' }
|
78
74
|
end
|
79
75
|
|
80
76
|
describe 'Numeric' do
|
81
77
|
let(:value) { { type: Numeric } }
|
82
78
|
|
83
|
-
it {
|
79
|
+
it { is_expected.to eq 'long' }
|
84
80
|
end
|
85
81
|
|
86
82
|
describe 'Symbol' do
|
87
83
|
let(:value) { { type: Symbol } }
|
88
84
|
|
89
|
-
it {
|
85
|
+
it { is_expected.to eq 'string' }
|
90
86
|
end
|
91
87
|
|
92
88
|
describe '[String]' do
|
93
89
|
let(:value) { { type: '[String]' } }
|
94
90
|
|
95
|
-
it {
|
91
|
+
it { is_expected.to eq('string') }
|
96
92
|
end
|
97
93
|
|
98
94
|
describe '[Integer]' do
|
99
95
|
let(:value) { { type: '[Integer]' } }
|
100
96
|
|
101
|
-
it {
|
97
|
+
it { is_expected.to eq('integer') }
|
102
98
|
end
|
103
99
|
end
|
@@ -9,18 +9,20 @@ describe GrapeSwagger::Endpoint::ParamsParser do
|
|
9
9
|
let(:parser) { described_class.new(params, settings) }
|
10
10
|
|
11
11
|
describe '#parse_request_params' do
|
12
|
+
subject(:parse_request_params) { parser.parse_request_params }
|
13
|
+
|
12
14
|
context 'when param is of array type' do
|
13
15
|
let(:params) { [['param_1', { type: 'Array[String]' }]] }
|
14
16
|
|
15
17
|
it 'adds is_array option' do
|
16
|
-
expect(
|
18
|
+
expect(parse_request_params['param_1']).to eq(type: 'Array[String]', is_array: true)
|
17
19
|
end
|
18
20
|
|
19
21
|
context 'and array_use_braces setting set to true' do
|
20
22
|
let(:settings) { { array_use_braces: true } }
|
21
23
|
|
22
24
|
it 'adds braces to the param key' do
|
23
|
-
expect(
|
25
|
+
expect(parse_request_params.keys.first).to eq 'param_1[]'
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
@@ -29,7 +31,7 @@ describe GrapeSwagger::Endpoint::ParamsParser do
|
|
29
31
|
let(:params) { [['param_1', { type: 'String' }]] }
|
30
32
|
|
31
33
|
it 'does not change options' do
|
32
|
-
expect(
|
34
|
+
expect(parse_request_params['param_1']).to eq(type: 'String')
|
33
35
|
end
|
34
36
|
|
35
37
|
context 'and array_use_braces setting set to true' do
|
@@ -45,18 +47,18 @@ describe GrapeSwagger::Endpoint::ParamsParser do
|
|
45
47
|
let(:params) { [['param_1', { type: 'Array' }], ['param_1[param_2]', { type: 'String' }]] }
|
46
48
|
|
47
49
|
it 'skips root parameter' do
|
48
|
-
|
50
|
+
is_expected.not_to have_key 'param_1'
|
49
51
|
end
|
50
52
|
|
51
53
|
it 'adds is_array option to the nested param' do
|
52
|
-
expect(
|
54
|
+
expect(parse_request_params['param_1[param_2]']).to eq(type: 'String', is_array: true)
|
53
55
|
end
|
54
56
|
|
55
57
|
context 'and array_use_braces setting set to true' do
|
56
58
|
let(:settings) { { array_use_braces: true } }
|
57
59
|
|
58
60
|
it 'adds braces to the param key' do
|
59
|
-
expect(
|
61
|
+
expect(parse_request_params.keys.first).to eq 'param_1[][param_2]'
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
@@ -65,18 +67,18 @@ describe GrapeSwagger::Endpoint::ParamsParser do
|
|
65
67
|
let(:params) { [['param_1', { type: 'Hash' }], ['param_1[param_2]', { type: 'String' }]] }
|
66
68
|
|
67
69
|
it 'skips root parameter' do
|
68
|
-
|
70
|
+
is_expected.not_to have_key 'param_1'
|
69
71
|
end
|
70
72
|
|
71
73
|
it 'does not change options to the nested param' do
|
72
|
-
expect(
|
74
|
+
expect(parse_request_params['param_1[param_2]']).to eq(type: 'String')
|
73
75
|
end
|
74
76
|
|
75
77
|
context 'and array_use_braces setting set to true' do
|
76
78
|
let(:settings) { { array_use_braces: true } }
|
77
79
|
|
78
80
|
it 'does not add braces to the param key' do
|
79
|
-
expect(
|
81
|
+
expect(parse_request_params.keys.first).to eq 'param_1[param_2]'
|
80
82
|
end
|
81
83
|
end
|
82
84
|
end
|
@@ -189,7 +189,7 @@ RSpec.shared_context 'entity swagger example' do
|
|
189
189
|
'info' => {
|
190
190
|
'title' => 'The API title to be displayed on the API homepage.',
|
191
191
|
'description' => 'A description of the API.',
|
192
|
-
'
|
192
|
+
'termsOfService' => 'www.The-URL-of-the-terms-and-service.com',
|
193
193
|
'contact' => { 'name' => 'Contact name', 'email' => 'Contact@email.com', 'url' => 'Contact URL' },
|
194
194
|
'license' => { 'name' => 'The name of the license.', 'url' => 'www.The-URL-of-the-license.org' },
|
195
195
|
'version' => '0.0.1'
|
@@ -181,7 +181,7 @@ RSpec.shared_context 'mock swagger example' do
|
|
181
181
|
'info' => {
|
182
182
|
'title' => 'The API title to be displayed on the API homepage.',
|
183
183
|
'description' => 'A description of the API.',
|
184
|
-
'
|
184
|
+
'termsOfService' => 'www.The-URL-of-the-terms-and-service.com',
|
185
185
|
'contact' => { 'name' => 'Contact name', 'email' => 'Contact@email.com', 'url' => 'Contact URL' },
|
186
186
|
'license' => { 'name' => 'The name of the license.', 'url' => 'www.The-URL-of-the-license.org' },
|
187
187
|
'version' => '0.0.1'
|
@@ -261,7 +261,7 @@ RSpec.shared_context 'representable swagger example' do
|
|
261
261
|
'info' => {
|
262
262
|
'title' => 'The API title to be displayed on the API homepage.',
|
263
263
|
'description' => 'A description of the API.',
|
264
|
-
'
|
264
|
+
'termsOfService' => 'www.The-URL-of-the-terms-and-service.com',
|
265
265
|
'contact' => { 'name' => 'Contact name', 'email' => 'Contact@email.com', 'url' => 'Contact URL' },
|
266
266
|
'license' => { 'name' => 'The name of the license.', 'url' => 'www.The-URL-of-the-license.org' },
|
267
267
|
'version' => '0.0.1'
|
@@ -12,7 +12,7 @@ describe 'headers' do
|
|
12
12
|
|
13
13
|
desc 'This returns something',
|
14
14
|
failure: [{ code: 400, model: Entities::ApiError }],
|
15
|
-
headers:
|
15
|
+
headers: {
|
16
16
|
'X-Rate-Limit-Limit' => {
|
17
17
|
'description' => 'The number of allowed requests in the current period',
|
18
18
|
'type' => 'integer'
|
@@ -128,7 +128,7 @@ describe 'Default API' do
|
|
128
128
|
end
|
129
129
|
|
130
130
|
it 'documents the terms of service url' do
|
131
|
-
expect(subject['
|
131
|
+
expect(subject['termsOfService']).to eql('http://terms.com')
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'documents the contact email' do
|
@@ -3,52 +3,95 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe 'Grape::Endpoint#path_and_definitions' do
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
context 'when mounting an API once' do
|
7
|
+
let(:item) do
|
8
|
+
Class.new(Grape::API) do
|
9
|
+
version 'v1', using: :path
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
resource :item do
|
12
|
+
get '/'
|
13
|
+
end
|
12
14
|
end
|
13
15
|
end
|
14
|
-
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
let(:api) do
|
18
|
+
item_api = item
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
Class.new(Grape::API) do
|
21
|
+
mount item_api
|
22
|
+
add_swagger_documentation add_version: true
|
23
|
+
end
|
22
24
|
end
|
23
|
-
end
|
24
25
|
|
25
|
-
|
26
|
-
|
26
|
+
let(:options) { { add_version: true } }
|
27
|
+
let(:target_routes) { api.combined_namespace_routes }
|
27
28
|
|
28
|
-
|
29
|
+
subject { api.endpoints[0].path_and_definition_objects(target_routes, options) }
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
it 'is returning a versioned path' do
|
32
|
+
expect(subject[0].keys[0]).to eq '/v1/item'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'tags the endpoint with the resource name' do
|
36
|
+
expect(subject.first['/v1/item'][:get][:tags]).to eq ['item']
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when custom tags are specified' do
|
40
|
+
let(:item) do
|
41
|
+
Class.new(Grape::API) do
|
42
|
+
version 'v1', using: :path
|
43
|
+
|
44
|
+
resource :item do
|
45
|
+
desc 'Item description', tags: ['special-item']
|
46
|
+
get '/'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
33
50
|
|
34
|
-
|
35
|
-
|
51
|
+
it 'tags the endpoint with the custom tags' do
|
52
|
+
expect(subject.first['/v1/item'][:get][:tags]).to eq ['special-item']
|
53
|
+
end
|
54
|
+
end
|
36
55
|
end
|
37
56
|
|
38
|
-
context 'when
|
57
|
+
context 'when mounting an API more than once', if: GrapeVersion.satisfy?('>= 1.2.0') do
|
39
58
|
let(:item) do
|
40
59
|
Class.new(Grape::API) do
|
41
|
-
version 'v1', using: :path
|
42
|
-
|
43
60
|
resource :item do
|
44
|
-
desc 'Item description', tags: ['
|
61
|
+
desc 'Item description', tags: [configuration[:tag] || 'item']
|
45
62
|
get '/'
|
46
63
|
end
|
47
64
|
end
|
48
65
|
end
|
49
66
|
|
50
|
-
|
51
|
-
|
67
|
+
let(:api) do
|
68
|
+
item_api = item
|
69
|
+
Class.new(Grape::API) do
|
70
|
+
version 'v1', using: :path do
|
71
|
+
mount item_api
|
72
|
+
end
|
73
|
+
|
74
|
+
version 'v2', using: :path do
|
75
|
+
mount item_api, with: { tag: 'special-item' }
|
76
|
+
end
|
77
|
+
|
78
|
+
add_swagger_documentation add_version: true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
let(:options) { { add_version: true } }
|
83
|
+
let(:target_routes) { api.combined_namespace_routes }
|
84
|
+
|
85
|
+
subject { api.endpoints[0].path_and_definition_objects(target_routes, options) }
|
86
|
+
|
87
|
+
it 'retrieves both apis respecting their configured tags' do
|
88
|
+
expect(subject.first['/v1/item'][:get][:tags]).to eq ['item']
|
89
|
+
expect(subject.first['/v2/item'][:get][:tags]).to eq ['special-item']
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'retrieves both apis with descriptions' do
|
93
|
+
expect(subject.first['/v1/item'][:get][:description]).to eq 'Item description'
|
94
|
+
expect(subject.first['/v2/item'][:get][:description]).to eq 'Item description'
|
52
95
|
end
|
53
96
|
end
|
54
97
|
end
|
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe GrapeInstance do
|
6
6
|
it 'added combined-routes' do
|
7
|
-
expect(
|
7
|
+
expect(described_class).to respond_to :combined_routes
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'added add_swagger_documentation' do
|
11
|
-
expect(
|
11
|
+
expect(described_class).to respond_to :add_swagger_documentation
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'added combined-namespaces' do
|
15
|
-
expect(
|
15
|
+
expect(described_class).to respond_to :combined_namespaces
|
16
16
|
end
|
17
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grape-swagger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.32.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Vandecasteele
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grape
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- lib/grape-swagger/endpoint.rb
|
73
73
|
- lib/grape-swagger/endpoint/params_parser.rb
|
74
74
|
- lib/grape-swagger/errors.rb
|
75
|
+
- lib/grape-swagger/instance.rb
|
75
76
|
- lib/grape-swagger/model_parsers.rb
|
76
77
|
- lib/grape-swagger/rake/oapi_tasks.rb
|
77
78
|
- lib/grape-swagger/version.rb
|
@@ -189,7 +190,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
189
190
|
version: '0'
|
190
191
|
requirements: []
|
191
192
|
rubyforge_project:
|
192
|
-
rubygems_version: 2.7.
|
193
|
+
rubygems_version: 2.7.8
|
193
194
|
signing_key:
|
194
195
|
specification_version: 4
|
195
196
|
summary: Add auto generated documentation to your Grape API that can be displayed
|