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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df4a6de7cd0c39993e11e3cee2e4f21a1bf7175d53d467530a2d5d2fb0de62ad
4
- data.tar.gz: 5845e6e3cc9368ff18a777155bb039aae5f8ad526444b9bf00ef5c3635ad732a
3
+ metadata.gz: 989468cbcebd005e6bf95724400366cfa1b80e7d395bb6d1255bc12c283a98b2
4
+ data.tar.gz: 949a822da86b5d6f3ead28cdd1262a093bcd8399875b1962f101c41634cc4c51
5
5
  SHA512:
6
- metadata.gz: '088948aa3b15b493d95d678e6d30d211bc3d942d27db9f6c340acdee76b43783352b830045d118b1d91f65be068248c4a829d5f0a06fe58cd4478b903b069a25'
7
- data.tar.gz: 60175ad736c79c12cfc14e1a9e810b57e0676a52ddc5b35fdb084fc6b0b8f0b1097080d6a367535287b982a71241b6675f6484252fce4a2b351972dead2664d5
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(example = nil)
73
- return super() if example.nil?
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
- metadata[:response][:content] =
76
- example.each_with_object({}) do |(mime, example_object), memo|
77
- memo[mime] = { example: example_object }
78
- end
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
- class ExtendedTypeAttribute < JSON::Schema::TypeV4Attribute
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
- template = (swagger_doc[:basePath] || '') + metadata[:path_item][:template]
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 rackified headers
158
- rackified_tuples = tuples.map do |pair|
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[rackified_tuples]
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[0]}\n" \
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.dig(:parameters)
58
- schema_param = value.dig(:parameters)&.find { |p| (p[:in] == :body || p[:in] == :formData) && p[:schema] }
59
- mime_list = value.dig(:consumes) || doc[:consumes]
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.dig(:consumes)
200
- value.delete(:produces) if is_hash && value.dig(:produces)
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
- # NOTE: rspec 2.x support
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.5.1
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-02-10 00:00:00.000000000 Z
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 rspecs. More about the OpenAPI initiative
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: []