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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e20b96cce4f137604bc4133b23249fde90b242160469cd6ed347d2840bd5b74
4
- data.tar.gz: 5e6d17f9875b63983b186d920dc28cdc4a957f13bc9f511a61991dbc7196ce50
3
+ metadata.gz: ea7cb947847696a10190ade08cfbe8bf19364a4b5855d932abda009c672122c4
4
+ data.tar.gz: 8a9c2f4a2bff62b247b795b6082d825d9403382ef56626f93ed697b4b654dc54
5
5
  SHA512:
6
- metadata.gz: f2596bf6f153d0447fec637fc4c035fa2bc1d3806feebf2f71a9e6fcd9c950a40d7bbd02fa703ad11994a0b4969fb014a0342a4dc01a7c3224c6670d126ffb73
7
- data.tar.gz: 39e5bfb7503ae7ea188231768db59fd89b8ef41494edb18ec8bf3e1cc458fda5fcf6db381663e06681e2b4b476e454147a4494232c316901a88caf2955ea7e92
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-09-28 22:03:50 -0400 using RuboCop version 0.59.2.
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: 21
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.1
15
- - 2.4.4
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.7
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.7
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.0'
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
- gem 'rubocop', '~> 0.59', require: false
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 | <= 0.6.1 | >= 2.4.1 |
52
- 0.27.0 | 2.0 | >= 0.16.2 | >= 0.5.0 | >= 2.4.1 |
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 Grape
22
- class API
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
- version_for(options)
30
- options = { target_class: self }.merge(options)
31
- @target_class = options[:target_class]
32
- auth_wrapper = options[:endpoint_auth_wrapper] || Class.new
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
- use auth_wrapper if auth_wrapper.method_defined?(:before) && !middleware.flatten.include?(auth_wrapper)
32
+ route_match = route_match.match('\/([\w|-]*?)[\.\/\(]') || route_match.match('\/([\w|-]*)$')
33
+ next unless route_match
35
34
 
36
- documentation_class.setup(options)
37
- mount(documentation_class)
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
- @target_class.combined_routes = {}
40
- combine_routes(@target_class, documentation_class)
40
+ @target_class.combined_routes[resource].unshift route
41
+ end
42
+ end
41
43
 
42
- @target_class.combined_namespaces = {}
43
- combine_namespaces(@target_class)
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
- @target_class.combined_namespace_routes = {}
46
- @target_class.combined_namespace_identifiers = {}
47
- combine_namespace_routes(@target_class.combined_namespaces)
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
- exclusive_route_keys = @target_class.combined_routes.keys - @target_class.combined_namespaces.keys
50
- exclusive_route_keys.each do |key|
51
- @target_class.combined_namespace_routes[key] = @target_class.combined_routes[key]
52
- end
53
- documentation_class
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
- private
84
+ def extract_parent_route(name)
85
+ route_name = name.match(%r{^/?([^/]*).*$})[1]
86
+ return route_name unless route_name.include? ':'
57
87
 
58
- def version_for(options)
59
- options[:version] = version if version
60
- end
88
+ matches = name.match(/\/[a-z]+/)
89
+ matches.nil? ? route_name : matches[0].delete('/')
90
+ end
61
91
 
62
- def combine_routes(app, doc_klass)
63
- app.routes.each do |route|
64
- route_path = route.path
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
- route_match = route_match.match('\/([\w|-]*?)[\.\/\(]') || route_match.match('\/([\w|-]*)$')
69
- next unless route_match
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
- resource = route_match.captures.first
72
- resource = '/' if resource.empty?
73
- @target_class.combined_routes[resource] ||= []
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
- @target_class.combined_routes[resource].unshift route
77
- end
78
- end
105
+ route.path.start_with?(route_prefix, route_versioned_prefix)
106
+ end
107
+ end
79
108
 
80
- def combine_namespaces(app)
81
- app.endpoints.each do |endpoint|
82
- ns = endpoint.namespace_stackable(:namespace).last
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
- # use the full namespace here (not the latest level only)
85
- # and strip leading slash
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
- combine_namespaces(endpoint.options[:app]) if endpoint.options[:app]
91
- end
92
- end
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
- def determine_namespaced_routes(name, parent_route)
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
- def combine_namespace_routes(namespaces)
105
- # iterate over each single namespace
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
- def extract_parent_route(name)
135
- route_name = name.match(%r{^/?([^/]*).*$})[1]
136
- return route_name unless route_name.include? ':'
127
+ @target_class.combined_routes = {}
128
+ combine_routes(@target_class, documentation_class)
137
129
 
138
- matches = name.match(/\/[a-z]+/)
139
- matches.nil? ? route_name : matches[0].delete('/')
140
- end
130
+ @target_class.combined_namespaces = {}
131
+ combine_namespaces(@target_class)
141
132
 
142
- def route_instance_variable(route)
143
- route.instance_variable_get(:@options)[:namespace]
144
- end
133
+ @target_class.combined_namespace_routes = {}
134
+ @target_class.combined_namespace_identifiers = {}
135
+ combine_namespace_routes(@target_class.combined_namespaces)
145
136
 
146
- def route_instance_variable_equals?(route, name)
147
- route_instance_variable(route) == "/#{name}" ||
148
- route_instance_variable(route) == "/:version/#{name}"
149
- end
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
- def route_path_start_with?(route, name)
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
- route.path.start_with?(route_prefix, route_versioned_prefix)
156
- end
146
+ def version_for(options)
147
+ options[:version] = version if version
148
+ end
157
149
 
158
- def create_documentation_class
159
- Class.new(Grape::API) do
160
- extend GrapeSwagger::DocMethods
161
- end
162
- end
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)
@@ -14,7 +14,7 @@ module GrapeSwagger
14
14
 
15
15
  # required properties
16
16
  @parsed_param = {
17
- in: param_type(value_type),
17
+ in: param_type(value_type),
18
18
  name: settings[:full_name] || param
19
19
  }
20
20
 
@@ -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: info_object(options[:info].merge(version: options[:doc_version])),
29
- swagger: '2.0',
30
- produces: content_types_for(target_class),
31
- authorizations: options[: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: 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]
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: infos[:title] || 'API title',
47
- description: infos[:description],
48
- termsOfServiceUrl: infos[:terms_of_service_url],
49
- contact: contact_object(infos),
50
- license: license_object(infos),
51
- version: infos[: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: infos.delete(:license_url)
64
+ url: infos.delete(:license_url)
65
65
  }.delete_if { |_, value| value.blank? }
66
66
  end
67
67
 
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ GrapeInstance = if defined? Grape::API::Instance
4
+ Grape::API::Instance
5
+ else
6
+ Grape::API
7
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrapeSwagger
4
- VERSION = '0.31.1'
4
+ VERSION = '0.32.0'
5
5
  end
@@ -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 { expect(subject).to eql 'object' }
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 { expect(subject).to eql 'string' }
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 { expect(subject).to eql 'Apple' }
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 { expect(subject).to eql 'string' }
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 { expect(subject).to eql 'MyInteger' }
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 { expect(subject).to eql 'file' }
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 { expect(subject).to eql 'boolean' }
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 { expect(subject).to eql 'double' }
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 { expect(subject).to eql 'dateTime' }
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 { expect(subject).to eql 'long' }
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 { expect(subject).to eql 'string' }
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 { expect(subject).to eq('string') }
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 { expect(subject).to eq('integer') }
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(parser.parse_request_params).to eq('param_1' => { type: 'Array[String]', is_array: true })
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(parser.parse_request_params.keys.first).to eq 'param_1[]'
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(parser.parse_request_params).to eq('param_1' => { type: 'String' })
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
- expect(parser.parse_request_params).not_to have_key 'param_1'
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(parser.parse_request_params).to eq('param_1[param_2]' => { type: 'String', is_array: true })
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(parser.parse_request_params.keys.first).to eq 'param_1[][param_2]'
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
- expect(parser.parse_request_params).not_to have_key 'param_1'
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(parser.parse_request_params).to eq('param_1[param_2]' => { type: 'String' })
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(parser.parse_request_params.keys.first).to eq 'param_1[param_2]'
81
+ expect(parse_request_params.keys.first).to eq 'param_1[param_2]'
80
82
  end
81
83
  end
82
84
  end
@@ -597,7 +597,7 @@ describe GrapeSwagger::DocMethods::MoveParams do
597
597
  let(:definition) do
598
598
  {
599
599
  type: 'array',
600
- items: {
600
+ items: {
601
601
  type: 'object',
602
602
  properties: {
603
603
  description: 'Test description'
@@ -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
- 'termsOfServiceUrl' => 'www.The-URL-of-the-terms-and-service.com',
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
- 'termsOfServiceUrl' => 'www.The-URL-of-the-terms-and-service.com',
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
- 'termsOfServiceUrl' => 'www.The-URL-of-the-terms-and-service.com',
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['termsOfServiceUrl']).to eql('http://terms.com')
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
- let(:item) do
7
- Class.new(Grape::API) do
8
- version 'v1', using: :path
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
- resource :item do
11
- get '/'
11
+ resource :item do
12
+ get '/'
13
+ end
12
14
  end
13
15
  end
14
- end
15
16
 
16
- let(:api) do
17
- item_api = item
17
+ let(:api) do
18
+ item_api = item
18
19
 
19
- Class.new(Grape::API) do
20
- mount item_api
21
- add_swagger_documentation add_version: true
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
- let(:options) { { add_version: true } }
26
- let(:target_routes) { api.combined_namespace_routes }
26
+ let(:options) { { add_version: true } }
27
+ let(:target_routes) { api.combined_namespace_routes }
27
28
 
28
- subject { api.endpoints[0].path_and_definition_objects(target_routes, options) }
29
+ subject { api.endpoints[0].path_and_definition_objects(target_routes, options) }
29
30
 
30
- it 'is returning a versioned path' do
31
- expect(subject[0].keys[0]).to eq '/v1/item'
32
- end
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
- it 'tags the endpoint with the resource name' do
35
- expect(subject.first['/v1/item'][:get][:tags]).to eq ['item']
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 custom tags are specified' do
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: ['special-item']
61
+ desc 'Item description', tags: [configuration[:tag] || 'item']
45
62
  get '/'
46
63
  end
47
64
  end
48
65
  end
49
66
 
50
- it 'tags the endpoint with the custom tags' do
51
- expect(subject.first['/v1/item'][:get][:tags]).to eq ['special-item']
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 Grape::API do
5
+ describe GrapeInstance do
6
6
  it 'added combined-routes' do
7
- expect(Grape::API).to respond_to :combined_routes
7
+ expect(described_class).to respond_to :combined_routes
8
8
  end
9
9
 
10
10
  it 'added add_swagger_documentation' do
11
- expect(Grape::API).to respond_to :add_swagger_documentation
11
+ expect(described_class).to respond_to :add_swagger_documentation
12
12
  end
13
13
 
14
14
  it 'added combined-namespaces' do
15
- expect(Grape::API).to respond_to :combined_namespaces
15
+ expect(described_class).to respond_to :combined_namespaces
16
16
  end
17
17
  end
@@ -41,7 +41,7 @@ module Extension
41
41
  description[:auth] = { scopes: scopes }
42
42
  end
43
43
 
44
- Grape::API.extend self
44
+ GrapeInstance.extend self
45
45
  end
46
46
 
47
47
  describe 'a guarded api endpoint' do
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.31.1
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-10-23 00:00:00.000000000 Z
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.6
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