rswag-specs 2.5.1 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|