rswag-specs 2.5.1 → 2.7.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 +4 -4
- data/lib/rswag/specs/example_group_helpers.rb +34 -9
- data/lib/rswag/specs/extended_schema.rb +1 -4
- data/lib/rswag/specs/request_factory.rb +65 -6
- data/lib/rswag/specs/response_validator.rb +1 -1
- data/lib/rswag/specs/swagger_formatter.rb +9 -7
- data/lib/tasks/rswag-specs_tasks.rake +7 -2
- metadata +40 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 989468cbcebd005e6bf95724400366cfa1b80e7d395bb6d1255bc12c283a98b2
|
4
|
+
data.tar.gz: 949a822da86b5d6f3ead28cdd1262a093bcd8399875b1962f101c41634cc4c51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4cb982b39359a8f69dd5ebf18287a2b4941349a202751d10f936b81014fce8ec99a24886e5de63c4fb1d4aba653893cf4ebff9f425f547be99b1ac3910e53ad
|
7
|
+
data.tar.gz: 1064a439e5b8652c40a77eddd6d0837ea908780750187879bb8bdb11af67656ea6882a8a251bb8627001c7857ebad94c378d68432c1101e2e19647b5c7c29ae5
|
@@ -1,8 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_support'
|
4
|
+
|
3
5
|
module Rswag
|
4
6
|
module Specs
|
5
7
|
module ExampleGroupHelpers
|
8
|
+
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: Support for Ruby 2.6 will be dropped in v3.0') if RUBY_VERSION.start_with? '2.6'
|
9
|
+
|
6
10
|
def path(template, metadata = {}, &block)
|
7
11
|
metadata[:path_item] = { template: template }
|
8
12
|
describe(template, metadata, &block)
|
@@ -69,23 +73,44 @@ module Rswag
|
|
69
73
|
# NOTE: Similar to 'description', 'examples' need to handle the case when
|
70
74
|
# being invoked with no params to avoid overriding 'examples' method of
|
71
75
|
# rspec-core ExampleGroup
|
72
|
-
def examples(
|
73
|
-
return super() if
|
76
|
+
def examples(examples = nil)
|
77
|
+
return super() if examples.nil?
|
78
|
+
# should we add a deprecation warning?
|
79
|
+
examples.each_with_index do |(mime, example_object), index|
|
80
|
+
example(mime, "example_#{index}", example_object)
|
81
|
+
end
|
82
|
+
end
|
74
83
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
84
|
+
def example(mime, name, value, summary=nil, description=nil)
|
85
|
+
# Todo - move initialization of metadata somewhere else.
|
86
|
+
if metadata[:response][:content].blank?
|
87
|
+
metadata[:response][:content] = {}
|
88
|
+
end
|
89
|
+
|
90
|
+
if metadata[:response][:content][mime].blank?
|
91
|
+
metadata[:response][:content][mime] = {}
|
92
|
+
metadata[:response][:content][mime][:examples] = {}
|
93
|
+
end
|
94
|
+
|
95
|
+
example_object = {
|
96
|
+
value: value,
|
97
|
+
summary: summary,
|
98
|
+
description: description
|
99
|
+
}.select { |_, v| v.present? }
|
100
|
+
# TODO, issue a warning if example is being overridden with the same key
|
101
|
+
metadata[:response][:content][mime][:examples].merge!(
|
102
|
+
{ name.to_sym => example_object }
|
103
|
+
)
|
79
104
|
end
|
80
105
|
|
81
106
|
def run_test!(&block)
|
82
|
-
# NOTE: rspec 2.x support
|
83
107
|
if RSPEC_VERSION < 3
|
108
|
+
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: Support for RSpec 2.X will be dropped in v3.0')
|
84
109
|
before do
|
85
110
|
submit_request(example.metadata)
|
86
111
|
end
|
87
112
|
|
88
|
-
it "returns a #{metadata[:response][:code]} response" do
|
113
|
+
it "returns a #{metadata[:response][:code]} response", rswag: true do
|
89
114
|
assert_response_matches_metadata(metadata)
|
90
115
|
block.call(response) if block_given?
|
91
116
|
end
|
@@ -94,7 +119,7 @@ module Rswag
|
|
94
119
|
submit_request(example.metadata)
|
95
120
|
end
|
96
121
|
|
97
|
-
it "returns a #{metadata[:response][:code]} response" do |example|
|
122
|
+
it "returns a #{metadata[:response][:code]} response", rswag: true do |example|
|
98
123
|
assert_response_matches_metadata(example.metadata, &block)
|
99
124
|
example.instance_exec(response, &block) if block_given?
|
100
125
|
end
|
@@ -7,14 +7,11 @@ module Rswag
|
|
7
7
|
class ExtendedSchema < JSON::Schema::Draft4
|
8
8
|
def initialize
|
9
9
|
super
|
10
|
-
@attributes['type'] = ExtendedTypeAttribute
|
11
10
|
@uri = URI.parse('http://tempuri.org/rswag/specs/extended_schema')
|
12
11
|
@names = ['http://tempuri.org/rswag/specs/extended_schema']
|
13
12
|
end
|
14
|
-
end
|
15
13
|
|
16
|
-
|
17
|
-
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
14
|
+
def validate(current_schema, data, *)
|
18
15
|
return if data.nil? && (current_schema.schema['nullable'] == true || current_schema.schema['x-nullable'] == true)
|
19
16
|
|
20
17
|
super
|
@@ -101,23 +101,82 @@ module Rswag
|
|
101
101
|
request[:verb] = metadata[:operation][:verb]
|
102
102
|
end
|
103
103
|
|
104
|
+
def base_path_from_servers(swagger_doc, use_server = :default)
|
105
|
+
return '' if swagger_doc[:servers].nil? || swagger_doc[:servers].empty?
|
106
|
+
server = swagger_doc[:servers].first
|
107
|
+
variables = {}
|
108
|
+
server.fetch(:variables, {}).each_pair { |k,v| variables[k] = v[use_server] }
|
109
|
+
base_path = server[:url].gsub(/\{(.*?)\}/) { |name| variables[name.to_sym] }
|
110
|
+
URI(base_path).path
|
111
|
+
end
|
112
|
+
|
104
113
|
def add_path(request, metadata, swagger_doc, parameters, example)
|
105
|
-
|
114
|
+
open_api_3_doc = doc_version(swagger_doc).start_with?('3')
|
115
|
+
uses_base_path = swagger_doc[:basePath].present?
|
116
|
+
|
117
|
+
if open_api_3_doc && uses_base_path
|
118
|
+
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: basePath is replaced in OpenAPI3! Update your swagger_helper.rb')
|
119
|
+
end
|
120
|
+
|
121
|
+
if uses_base_path
|
122
|
+
template = (swagger_doc[:basePath] || '') + metadata[:path_item][:template]
|
123
|
+
else # OpenAPI 3
|
124
|
+
template = base_path_from_servers(swagger_doc) + metadata[:path_item][:template]
|
125
|
+
end
|
106
126
|
|
107
127
|
request[:path] = template.tap do |path_template|
|
108
128
|
parameters.select { |p| p[:in] == :path }.each do |p|
|
129
|
+
unless example.respond_to?(p[:name])
|
130
|
+
raise ArgumentError.new("`#{p[:name].to_s}` parameter key present, but not defined within example group"\
|
131
|
+
"(i. e `it` or `let` block)")
|
132
|
+
end
|
109
133
|
path_template.gsub!("{#{p[:name]}}", example.send(p[:name]).to_s)
|
110
134
|
end
|
111
135
|
|
112
136
|
parameters.select { |p| p[:in] == :query }.each_with_index do |p, i|
|
113
137
|
path_template.concat(i.zero? ? '?' : '&')
|
114
|
-
path_template.concat(build_query_string_part(p, example.send(p[:name])))
|
138
|
+
path_template.concat(build_query_string_part(p, example.send(p[:name]), swagger_doc))
|
115
139
|
end
|
116
140
|
end
|
117
141
|
end
|
118
142
|
|
119
|
-
def build_query_string_part(param, value)
|
143
|
+
def build_query_string_part(param, value, swagger_doc)
|
120
144
|
name = param[:name]
|
145
|
+
|
146
|
+
# OAS 3: https://swagger.io/docs/specification/serialization/
|
147
|
+
if swagger_doc && doc_version(swagger_doc).start_with?('3') && param[:schema]
|
148
|
+
style = param[:style]&.to_sym || :form
|
149
|
+
explode = param[:explode].nil? ? true : param[:explode]
|
150
|
+
|
151
|
+
case param[:schema][:type].to_sym
|
152
|
+
when :object
|
153
|
+
case style
|
154
|
+
when :deepObject
|
155
|
+
return { name => value }.to_query
|
156
|
+
when :form
|
157
|
+
if explode
|
158
|
+
return value.to_query
|
159
|
+
else
|
160
|
+
return "#{CGI.escape(name.to_s)}=" + value.to_a.flatten.map{|v| CGI.escape(v.to_s) }.join(',')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
when :array
|
164
|
+
case explode
|
165
|
+
when true
|
166
|
+
return value.to_a.flatten.map{|v| "#{CGI.escape(name.to_s)}=#{CGI.escape(v.to_s)}"}.join('&')
|
167
|
+
else
|
168
|
+
separator = case style
|
169
|
+
when :form then ','
|
170
|
+
when :spaceDelimited then '%20'
|
171
|
+
when :pipeDelimited then '|'
|
172
|
+
end
|
173
|
+
return "#{CGI.escape(name.to_s)}=" + value.to_a.flatten.map{|v| CGI.escape(v.to_s) }.join(separator)
|
174
|
+
end
|
175
|
+
else
|
176
|
+
return "#{name}=#{value}"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
121
180
|
type = param[:type] || param.dig(:schema, :type)
|
122
181
|
return "#{name}=#{value}" unless type&.to_sym == :array
|
123
182
|
|
@@ -154,8 +213,8 @@ module Rswag
|
|
154
213
|
tuples << ['Content-Type', content_type]
|
155
214
|
end
|
156
215
|
|
157
|
-
# Rails test infrastructure requires
|
158
|
-
|
216
|
+
# Rails test infrastructure requires rack-formatted headers
|
217
|
+
rack_formatted_tuples = tuples.map do |pair|
|
159
218
|
[
|
160
219
|
case pair[0]
|
161
220
|
when 'Accept' then 'HTTP_ACCEPT'
|
@@ -167,7 +226,7 @@ module Rswag
|
|
167
226
|
]
|
168
227
|
end
|
169
228
|
|
170
|
-
request[:headers] = Hash[
|
229
|
+
request[:headers] = Hash[rack_formatted_tuples]
|
171
230
|
end
|
172
231
|
|
173
232
|
def add_payload(request, parameters, example)
|
@@ -53,7 +53,7 @@ module Rswag
|
|
53
53
|
return unless errors.any?
|
54
54
|
|
55
55
|
raise UnexpectedResponse,
|
56
|
-
"Expected response body to match schema: #{errors
|
56
|
+
"Expected response body to match schema: #{errors.join("\n")}\n" \
|
57
57
|
"Response body: #{JSON.pretty_generate(JSON.parse(body))}"
|
58
58
|
end
|
59
59
|
|
@@ -7,10 +7,12 @@ require 'swagger_helper'
|
|
7
7
|
module Rswag
|
8
8
|
module Specs
|
9
9
|
class SwaggerFormatter < ::RSpec::Core::Formatters::BaseTextFormatter
|
10
|
+
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: Support for Ruby 2.6 will be dropped in v3.0') if RUBY_VERSION.start_with? '2.6'
|
10
11
|
|
11
|
-
# NOTE: rspec 2.x support
|
12
12
|
if RSPEC_VERSION > 2
|
13
13
|
::RSpec::Core::Formatters.register self, :example_group_finished, :stop
|
14
|
+
else
|
15
|
+
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: Support for RSpec 2.X will be dropped in v3.0')
|
14
16
|
end
|
15
17
|
|
16
18
|
def initialize(output, config = Rswag::Specs.config)
|
@@ -21,7 +23,6 @@ module Rswag
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def example_group_finished(notification)
|
24
|
-
# NOTE: rspec 2.x support
|
25
26
|
metadata = if RSPEC_VERSION > 2
|
26
27
|
notification.group.metadata
|
27
28
|
else
|
@@ -54,12 +55,13 @@ module Rswag
|
|
54
55
|
doc[:paths]&.each_pair do |_k, v|
|
55
56
|
v.each_pair do |_verb, value|
|
56
57
|
is_hash = value.is_a?(Hash)
|
57
|
-
if is_hash && value
|
58
|
-
schema_param = value
|
59
|
-
mime_list = value
|
58
|
+
if is_hash && value[:parameters]
|
59
|
+
schema_param = value[:parameters]&.find { |p| (p[:in] == :body || p[:in] == :formData) && p[:schema] }
|
60
|
+
mime_list = value[:consumes] || doc[:consumes]
|
60
61
|
if value && schema_param && mime_list
|
61
62
|
value[:requestBody] = { content: {} } unless value.dig(:requestBody, :content)
|
62
63
|
value[:requestBody][:required] = true if schema_param[:required]
|
64
|
+
value[:requestBody][:description] = schema_param[:description] if schema_param[:description]
|
63
65
|
mime_list.each do |mime|
|
64
66
|
value[:requestBody][:content][mime] = { schema: schema_param[:schema] }
|
65
67
|
end
|
@@ -196,8 +198,8 @@ module Rswag
|
|
196
198
|
|
197
199
|
def remove_invalid_operation_keys!(value)
|
198
200
|
is_hash = value.is_a?(Hash)
|
199
|
-
value.delete(:consumes) if is_hash && value
|
200
|
-
value.delete(:produces) if is_hash && value
|
201
|
+
value.delete(:consumes) if is_hash && value[:consumes]
|
202
|
+
value.delete(:produces) if is_hash && value[:produces]
|
201
203
|
end
|
202
204
|
end
|
203
205
|
end
|
@@ -11,10 +11,15 @@ namespace :rswag do
|
|
11
11
|
'spec/requests/**/*_spec.rb, spec/api/**/*_spec.rb, spec/integration/**/*_spec.rb'
|
12
12
|
)
|
13
13
|
|
14
|
-
|
14
|
+
additional_rspec_opts = ENV.fetch(
|
15
|
+
'ADDITIONAL_RSPEC_OPTS',
|
16
|
+
''
|
17
|
+
)
|
18
|
+
|
15
19
|
if Rswag::Specs::RSPEC_VERSION > 2 && Rswag::Specs.config.swagger_dry_run
|
16
|
-
t.rspec_opts = ['--format Rswag::Specs::SwaggerFormatter', '--dry-run', '--order defined']
|
20
|
+
t.rspec_opts = ['--format Rswag::Specs::SwaggerFormatter', '--dry-run', '--order defined'] << additional_rspec_opts
|
17
21
|
else
|
22
|
+
ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: Support for RSpec 2.X will be dropped in v3.0')
|
18
23
|
t.rspec_opts = ['--format Rswag::Specs::SwaggerFormatter', '--order defined']
|
19
24
|
end
|
20
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rswag-specs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richie Morris
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-10-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -56,19 +56,53 @@ dependencies:
|
|
56
56
|
name: json-schema
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '2.2'
|
62
|
+
- - "<"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '4.0'
|
62
65
|
type: :runtime
|
63
66
|
prerelease: false
|
64
67
|
version_requirements: !ruby/object:Gem::Requirement
|
65
68
|
requirements:
|
66
|
-
- - "
|
69
|
+
- - ">="
|
67
70
|
- !ruby/object:Gem::Version
|
68
71
|
version: '2.2'
|
72
|
+
- - "<"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '4.0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rspec-core
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.14'
|
82
|
+
type: :runtime
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '2.14'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: simplecov
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 0.21.2
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - '='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 0.21.2
|
69
103
|
description: 'Simplify API integration testing with a succinct rspec DSL and generate
|
70
|
-
OpenAPI specification files directly from your
|
71
|
-
here: http://spec.openapis.org/'
|
104
|
+
OpenAPI specification files directly from your rspec tests. More about the OpenAPI
|
105
|
+
initiative here: http://spec.openapis.org/'
|
72
106
|
email:
|
73
107
|
- domaindrivendev@gmail.com
|
74
108
|
executables: []
|