rswag-specs 2.8.0 → 2.9.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: cfedb2177ee21788aa710db72fbc573230a51c84877bd90edff99b8a1fc9967c
4
- data.tar.gz: 842d0dba7c2dcd4aa59ec015928c825da6ef1cf892859e492589d540b003c181
3
+ metadata.gz: fa8f8005ed229944c19cb2e33e09eaebb95b8e32b9bef505a5e6b64b237bcbdc
4
+ data.tar.gz: 7eebf43807f0252c3168e08283b716c3dd9356f5d79fde1fcfc275377b5bc522
5
5
  SHA512:
6
- metadata.gz: 5640b7930547aa45a3b2662f8fad08508063d1c9726c2f72d6e2f15f6eab32408472e7645230b30a5eec74ae223cfae5e87e9d26311cc609aa543c90d8234aef
7
- data.tar.gz: 98e797ce8b1babf942ba387cffbe6eec52994047543c669b9293631bc08bfc1695b9d3c1ca572f3ec9357e7649bf601f0df81bf28590ee605b501f7546aae8f1
6
+ metadata.gz: e99187485ac197dad84d0f28b9bdec67c0e11b10efb5f2561a939e48852a6fc28505d2c92feb49a2969dd6a5a7919279986a05d9c3d09db2dc15581b085908ed
7
+ data.tar.gz: 1da746e08c42864094b13f36b72587f1d05b55922106ac1888accf16ac1bfae84c5fafb28dfa5952c47b477742b592bfff915743842523104f28e416859c1889
@@ -6,13 +6,14 @@ require 'rails/generators'
6
6
  module Rspec
7
7
  class SwaggerGenerator < ::Rails::Generators::NamedBase
8
8
  source_root File.expand_path('templates', __dir__)
9
+ class_option :spec_path, type: :string, default: 'requests'
9
10
 
10
11
  def setup
11
12
  @routes = Rswag::RouteParser.new(controller_path).routes
12
13
  end
13
14
 
14
15
  def create_spec_file
15
- template 'spec.rb', File.join('spec', 'requests', "#{controller_path}_spec.rb")
16
+ template 'spec.rb', File.join('spec', options['spec_path'], "#{controller_path}_spec.rb")
16
17
  end
17
18
 
18
19
  private
@@ -55,6 +55,10 @@ module Rswag
55
55
  doc = get_swagger_doc(name)
56
56
  doc[:openapi] || doc[:swagger]
57
57
  end
58
+
59
+ def swagger_strict_schema_validation
60
+ @swagger_strict_schema_validation ||= (@rspec_config.swagger_strict_schema_validation || false)
61
+ end
58
62
  end
59
63
 
60
64
  class ConfigurationError < StandardError; end
@@ -56,16 +56,16 @@ module Rswag
56
56
  end
57
57
 
58
58
 
59
- def request_body_example(value:, summary: nil, name: nil)
60
- if metadata.key?(:operation)
59
+ def request_body_example(value:, summary: nil, name: nil)
60
+ if metadata.key?(:operation)
61
61
  metadata[:operation][:request_examples] ||= []
62
- example = { value: value }
63
- example[:summary] = summary if summary
62
+ example = { value: value }
63
+ example[:summary] = summary if summary
64
64
  # We need the examples to have a unique name for a set of examples, so just make the name the length if one isn't provided.
65
65
  example[:name] = name || metadata[:operation][:request_examples].length()
66
66
  metadata[:operation][:request_examples] << example
67
- end
68
- end
67
+ end
68
+ end
69
69
 
70
70
  def response(code, description, metadata = {}, &block)
71
71
  metadata[:response] = { code: code, description: description }
@@ -115,14 +115,22 @@ module Rswag
115
115
  )
116
116
  end
117
117
 
118
- def run_test!(&block)
118
+ #
119
+ # Perform request and assert response matches swagger definitions
120
+ #
121
+ # @param options [Hash] options to pass to the `it` method
122
+ # @param &block [Proc] you can make additional assertions within that block
123
+ # @return [void]
124
+ def run_test!(**options, &block)
125
+ options[:rswag] = true unless options.key?(:rswag)
126
+
119
127
  if RSPEC_VERSION < 3
120
128
  ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: Support for RSpec 2.X will be dropped in v3.0')
121
129
  before do
122
130
  submit_request(example.metadata)
123
131
  end
124
132
 
125
- it "returns a #{metadata[:response][:code]} response", rswag: true do
133
+ it "returns a #{metadata[:response][:code]} response", **options do
126
134
  assert_response_matches_metadata(metadata)
127
135
  block.call(response) if block_given?
128
136
  end
@@ -131,7 +139,7 @@ module Rswag
131
139
  submit_request(example.metadata)
132
140
  end
133
141
 
134
- it "returns a #{metadata[:response][:code]} response", rswag: true do |example|
142
+ it "returns a #{metadata[:response][:code]} response", **options do |example|
135
143
  assert_response_matches_metadata(example.metadata, &block)
136
144
  example.instance_exec(response, &block) if block_given?
137
145
  end
@@ -34,7 +34,7 @@ module Rswag
34
34
  (operation_params + path_item_params + security_params)
35
35
  .map { |p| p['$ref'] ? resolve_parameter(p['$ref'], swagger_doc) : p }
36
36
  .uniq { |p| p[:name] }
37
- .reject { |p| p[:required] == false && !example.respond_to?(p[:name]) }
37
+ .reject { |p| p[:required] == false && !example.respond_to?(extract_getter(p)) }
38
38
  end
39
39
 
40
40
  def derive_security_params(metadata, swagger_doc)
@@ -106,7 +106,7 @@ module Rswag
106
106
  server = swagger_doc[:servers].first
107
107
  variables = {}
108
108
  server.fetch(:variables, {}).each_pair { |k,v| variables[k] = v[use_server] }
109
- base_path = server[:url].gsub(/\{(.*?)\}/) { |name| variables[name.to_sym] }
109
+ base_path = server[:url].gsub(/\{(.*?)\}/) { variables[$1.to_sym] }
110
110
  URI(base_path).path
111
111
  end
112
112
 
@@ -126,16 +126,16 @@ module Rswag
126
126
 
127
127
  request[:path] = template.tap do |path_template|
128
128
  parameters.select { |p| p[:in] == :path }.each do |p|
129
- unless example.respond_to?(p[:name])
129
+ unless example.respond_to?(extract_getter(p))
130
130
  raise ArgumentError.new("`#{p[:name].to_s}` parameter key present, but not defined within example group"\
131
131
  "(i. e `it` or `let` block)")
132
132
  end
133
- path_template.gsub!("{#{p[:name]}}", example.send(p[:name]).to_s)
133
+ path_template.gsub!("{#{p[:name]}}", example.send(extract_getter(p)).to_s)
134
134
  end
135
135
 
136
136
  parameters.select { |p| p[:in] == :query }.each_with_index do |p, i|
137
137
  path_template.concat(i.zero? ? '?' : '&')
138
- path_template.concat(build_query_string_part(p, example.send(p[:name]), swagger_doc))
138
+ path_template.concat(build_query_string_part(p, example.send(extract_getter(p)), swagger_doc))
139
139
  end
140
140
  end
141
141
  end
@@ -197,7 +197,7 @@ module Rswag
197
197
  def add_headers(request, metadata, swagger_doc, parameters, example)
198
198
  tuples = parameters
199
199
  .select { |p| p[:in] == :header }
200
- .map { |p| [p[:name], example.send(p[:name]).to_s] }
200
+ .map { |p| [p[:name], example.send(extract_getter(p)).to_s] }
201
201
 
202
202
  # Accept header
203
203
  produces = metadata[:operation][:produces] || swagger_doc[:produces]
@@ -255,7 +255,7 @@ module Rswag
255
255
  # PROS: simple to implement, CONS: serialization/deserialization is bypassed in test
256
256
  tuples = parameters
257
257
  .select { |p| p[:in] == :formData }
258
- .map { |p| [p[:name], example.send(p[:name])] }
258
+ .map { |p| [p[:name], example.send(extract_getter(p))] }
259
259
  Hash[tuples]
260
260
  end
261
261
 
@@ -272,6 +272,10 @@ module Rswag
272
272
  def doc_version(doc)
273
273
  doc[:openapi] || doc[:swagger] || '3'
274
274
  end
275
+
276
+ def extract_getter(parameter)
277
+ parameter[:getter] || parameter[:name]
278
+ end
275
279
  end
276
280
 
277
281
  class MissingParameterError < StandardError
@@ -62,7 +62,9 @@ module Rswag
62
62
  .merge('$schema' => 'http://tempuri.org/rswag/specs/extended_schema')
63
63
  .merge(schemas)
64
64
 
65
- errors = JSON::Validator.fully_validate(validation_schema, body)
65
+ validation_options = validation_options_from(metadata)
66
+
67
+ errors = JSON::Validator.fully_validate(validation_schema, body, validation_options)
66
68
  return unless errors.any?
67
69
 
68
70
  raise UnexpectedResponse,
@@ -70,6 +72,15 @@ module Rswag
70
72
  "Response body: #{JSON.pretty_generate(JSON.parse(body))}"
71
73
  end
72
74
 
75
+ def validation_options_from(metadata)
76
+ is_strict = !!metadata.fetch(
77
+ :swagger_strict_schema_validation,
78
+ @config.swagger_strict_schema_validation
79
+ )
80
+
81
+ { strict: is_strict }
82
+ end
83
+
73
84
  def definitions_or_component_schemas(swagger_doc, version)
74
85
  if version.start_with?('2')
75
86
  swagger_doc.slice(:definitions)
@@ -58,6 +58,7 @@ module Rswag
58
58
  if is_hash && value[:parameters]
59
59
  schema_param = value[:parameters]&.find { |p| (p[:in] == :body || p[:in] == :formData) && p[:schema] }
60
60
  mime_list = value[:consumes] || doc[:consumes]
61
+
61
62
  if value && schema_param && mime_list
62
63
  value[:requestBody] = { content: {} } unless value.dig(:requestBody, :content)
63
64
  value[:requestBody][:required] = true if schema_param[:required]
@@ -147,7 +148,7 @@ module Rswag
147
148
 
148
149
  target_node[:content] ||= {}
149
150
  mime_list.each do |mime_type|
150
- # TODO upgrade to have content-type specific schema
151
+ # TODO: upgrade to have content-type specific schema
151
152
  (target_node[:content][mime_type] ||= {}).merge!(schema: schema)
152
153
  end
153
154
  end
@@ -207,10 +208,12 @@ module Rswag
207
208
  end
208
209
 
209
210
  def remove_invalid_operation_keys!(value)
210
- is_hash = value.is_a?(Hash)
211
- value.delete(:consumes) if is_hash && value[:consumes]
212
- value.delete(:produces) if is_hash && value[:produces]
213
- value.delete(:request_examples) if is_hash && value[:request_examples]
211
+ return unless value.is_a?(Hash)
212
+
213
+ value.delete(:consumes) if value[:consumes]
214
+ value.delete(:produces) if value[:produces]
215
+ value.delete(:request_examples) if value[:request_examples]
216
+ value[:parameters].each { |p| p.delete(:getter) } if value[:parameters]
214
217
  end
215
218
  end
216
219
  end
data/lib/rswag/specs.rb CHANGED
@@ -14,6 +14,7 @@ module Rswag
14
14
  c.add_setting :swagger_docs
15
15
  c.add_setting :swagger_dry_run
16
16
  c.add_setting :swagger_format
17
+ c.add_setting :swagger_strict_schema_validation
17
18
  c.extend ExampleGroupHelpers, type: :request
18
19
  c.include ExampleHelpers, type: :request
19
20
  end
@@ -16,11 +16,13 @@ namespace :rswag do
16
16
  ''
17
17
  )
18
18
 
19
+ t.rspec_opts = [additional_rspec_opts]
20
+
19
21
  if Rswag::Specs::RSPEC_VERSION > 2 && Rswag::Specs.config.swagger_dry_run
20
- t.rspec_opts = ['--format Rswag::Specs::SwaggerFormatter', '--dry-run', '--order defined'] << additional_rspec_opts
22
+ t.rspec_opts += ['--format Rswag::Specs::SwaggerFormatter', '--dry-run', '--order defined']
21
23
  else
22
24
  ActiveSupport::Deprecation.warn('Rswag::Specs: WARNING: Support for RSpec 2.X will be dropped in v3.0')
23
- t.rspec_opts = ['--format Rswag::Specs::SwaggerFormatter', '--order defined']
25
+ t.rspec_opts += ['--format Rswag::Specs::SwaggerFormatter', '--order defined']
24
26
  end
25
27
  end
26
28
  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.8.0
4
+ version: 2.9.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-11-16 00:00:00.000000000 Z
13
+ date: 2023-04-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport