openapi-ruby 3.1.0 → 3.1.1

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: e392a1235f97dc71aaf0ec1790ee0bd64c4bcbae412063af363af91e95cb608d
4
- data.tar.gz: 90f056e8bc51aa18d6de20a38ac706c079955567066e034d9408a8bd75b2f966
3
+ metadata.gz: 953f7f56ecdec3d8ee0f1f1261e49328e53d0aab5041b43f47a6e1138a2e880f
4
+ data.tar.gz: bec8a51340348604307f17791824d9327e7ceee7b58a8f35533ef7036c12156f
5
5
  SHA512:
6
- metadata.gz: bde611e9f9b188969e3bbc8a6f1062efe7738ebc15e7eef40079406cccd0eab35051c767db9abfbcba0eea1e91ec39a265f7654468f8478efef8462e63b67f42
7
- data.tar.gz: c02da938cd7edd9053fc89730916dbc31b87829fc945c36248269e6a77a569cf77ea07c14938550517a16909615ee926fc05b1b54bf848a3997ac7cfa1bf4c47
6
+ metadata.gz: c62b49da036fe1dbb27b3f7ce2937a044427ea89ded288bdab1c33dab6fc041e31c89ecb75fd2e2419731cd0f803428baed9ed5152cdf01d7cd77b42b004642e
7
+ data.tar.gz: 5e2bbbcf02c286120207fc06a9f86c66b2618c9766a78b4b94c215641d0c2a5173aa4c45705e4fd2e6ed909271c63000a65182d159f22f3d716a4742dcbc6bae
data/README.md CHANGED
@@ -63,7 +63,6 @@ OpenapiRuby.configure do |config|
63
63
  config.camelize_keys = true
64
64
  config.schema_output_dir = "swagger"
65
65
  config.schema_output_format = :yaml
66
- config.validate_responses_in_tests = true
67
66
 
68
67
  # Runtime middleware (disabled by default)
69
68
  config.request_validation = :disabled # :enabled, :disabled, :warn_only
@@ -20,9 +20,6 @@ OpenapiRuby.configure do |config|
20
20
  config.schema_output_dir = "swagger"
21
21
  config.schema_output_format = :yaml
22
22
 
23
- # Validate response bodies in tests against defined schemas
24
- config.validate_responses_in_tests = true
25
-
26
23
  # Runtime request/response validation middleware
27
24
  # Options: :disabled, :enabled, :warn_only
28
25
  config.request_validation = :disabled
@@ -87,7 +87,7 @@ module OpenapiRuby
87
87
  assert_equal expected_status, response.status,
88
88
  "Expected status #{expected_status}, got #{response.status}\nResponse body: #{response.body}"
89
89
 
90
- if OpenapiRuby.configuration.validate_responses_in_tests && response_ctx.schema_definition
90
+ if response_ctx.schema_definition
91
91
  validator = Testing::ResponseValidator.new
92
92
  body_data = parse_response_body
93
93
  errors = validator.validate(
@@ -144,6 +144,12 @@ module OpenapiRuby
144
144
  accept = resolve_let(:Accept)
145
145
  headers["Accept"] = accept || "application/json"
146
146
 
147
+ # Always append query params to the URL so the middleware sees them
148
+ # (Rails sends params as request body for non-GET methods).
149
+ if params.any?
150
+ path = "#{path}?#{Rack::Utils.build_nested_query(params)}"
151
+ end
152
+
147
153
  if body
148
154
  content_type = operation&.request_body_definition&.dig("content")&.keys&.first || "application/json"
149
155
  request_args = if content_type.include?("form-data") || content_type.include?("x-www-form-urlencoded")
@@ -154,13 +160,8 @@ module OpenapiRuby
154
160
  headers: headers.merge("Content-Type" => content_type)
155
161
  }
156
162
  end
157
- # Append query params to path when body is present
158
- if params.any?
159
- query_string = params.map { |k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join("&")
160
- path = "#{path}?#{query_string}"
161
- end
162
163
  else
163
- request_args = {params: params, headers: headers}
164
+ request_args = {headers: headers}
164
165
  end
165
166
 
166
167
  send(method.to_sym, path, **request_args)
@@ -177,6 +178,19 @@ module OpenapiRuby
177
178
  "Expected status #{expected_status}, got #{actual_status}\n" \
178
179
  "Response body: #{response.body}"
179
180
  end
181
+
182
+ if response_ctx.schema_definition
183
+ schema_name = find_in_metadata(metadata, :openapi_schema_name)
184
+ validator = Testing::ResponseValidator.new(OpenapiRuby::Adapters::RSpec.validation_document_for(schema_name))
185
+ errors = validator.validate(
186
+ response_body: parsed_response_body,
187
+ status_code: response.status,
188
+ response_context: response_ctx
189
+ )
190
+ unless errors.empty?
191
+ raise "Response body validation failed:\n#{errors.join("\n")}\nResponse body: #{response.body}"
192
+ end
193
+ end
180
194
  end
181
195
 
182
196
  private
@@ -269,6 +283,29 @@ module OpenapiRuby
269
283
  end
270
284
  end
271
285
 
286
+ # Build the OpenAPI document hash for a given schema name and cache it.
287
+ # Used by response body validation so $ref schemas can be resolved.
288
+ def self.validation_document_for(schema_name)
289
+ return nil unless schema_name
290
+
291
+ key = schema_name.to_sym
292
+ @validation_documents ||= {}
293
+ @validation_documents[key] ||= begin
294
+ config = OpenapiRuby.configuration
295
+ schema_config = config.schemas[key] || config.schemas[schema_name.to_s]
296
+ return nil unless schema_config
297
+
298
+ builder = OpenapiRuby::Core::DocumentBuilder.new(schema_config)
299
+ OpenapiRuby::DSL::MetadataStore.contexts_for(schema_name).each do |context|
300
+ builder.add_path(context.path_template, context.to_openapi)
301
+ end
302
+ scope = schema_config[:component_scope]
303
+ loader = OpenapiRuby::Components::Loader.new(scope: scope)
304
+ builder.merge_components(loader.to_openapi_hash)
305
+ builder.build.data
306
+ end
307
+ end
308
+
272
309
  def self.install!
273
310
  ::RSpec.configure do |config|
274
311
  config.extend ExampleGroupHelpers, type: :openapi
@@ -9,46 +9,51 @@ module OpenapiRuby
9
9
  # Components
10
10
  attr_accessor :component_paths
11
11
  attr_accessor :component_scope_paths
12
- attr_accessor :camelize_keys, :key_transform, :response_validation, :strict_query_params,
13
- :coerce_params, :error_handler, :schema_output_format, :validate_responses_in_tests, :ui_path, :ui_config, :coverage_report_path
14
- attr_accessor :strict_reference_validation
12
+
13
+ # Output / formatting
14
+ attr_accessor :camelize_keys, :schema_output_format, :schema_output_dir
15
15
  attr_accessor :auto_validation_error_response
16
16
  attr_accessor :validation_error_schema
17
17
 
18
18
  # Middleware (runtime validation)
19
- attr_accessor :request_validation
19
+ attr_accessor :request_validation, :response_validation, :coerce_params
20
20
 
21
- # Test / Generation
22
- attr_accessor :schema_output_dir
21
+ # OpenAPI meta-schema validation of generated specs and middleware-loaded
22
+ # documents. One of :disabled, :enabled (raise on errors), :warn_only
23
+ # (default, log warnings). Boolean values are accepted for backwards
24
+ # compatibility: `true` → :warn_only, `false` → :disabled.
25
+ attr_reader :strict_reference_validation
23
26
 
24
- # UI (optional)
25
- attr_accessor :ui_enabled
27
+ def strict_reference_validation=(value)
28
+ @strict_reference_validation = case value
29
+ when true, :warn_only then :warn_only
30
+ when false, :disabled then :disabled
31
+ when :enabled then :enabled
32
+ else
33
+ raise ConfigurationError,
34
+ "strict_reference_validation must be :disabled, :enabled, :warn_only, or a boolean"
35
+ end
36
+ end
26
37
 
27
- # Coverage
28
- attr_accessor :coverage_enabled
38
+ # UI (optional)
39
+ attr_accessor :ui_enabled, :ui_path, :ui_config
29
40
 
30
41
  def initialize
31
42
  @schemas = {}
32
43
  @component_paths = ["app/api_components"]
33
44
  @component_scope_paths = {}
34
45
  @camelize_keys = true
35
- @key_transform = nil
36
46
  @request_validation = :disabled
37
47
  @response_validation = :disabled
38
- @strict_query_params = false
39
48
  @coerce_params = true
40
- @error_handler = nil
41
49
  @schema_output_dir = "swagger"
42
50
  @schema_output_format = :yaml
43
- @validate_responses_in_tests = true
44
51
  @ui_enabled = false
45
52
  @ui_path = "/api-docs"
46
53
  @ui_config = {}
47
- @strict_reference_validation = true
54
+ @strict_reference_validation = :warn_only
48
55
  @auto_validation_error_response = true
49
56
  @validation_error_schema = nil
50
- @coverage_enabled = false
51
- @coverage_report_path = "tmp/openapi_coverage.json"
52
57
  end
53
58
 
54
59
  def validate!
@@ -23,7 +23,7 @@ module OpenapiRuby
23
23
 
24
24
  def write!
25
25
  document = build_document
26
- validate_document!(document) if OpenapiRuby.configuration.strict_reference_validation
26
+ validate_document!(document) unless OpenapiRuby.configuration.strict_reference_validation == :disabled
27
27
  output_path = File.join(output_dir, filename)
28
28
  FileUtils.mkdir_p(output_dir)
29
29
  File.write(output_path, format_output(document))
@@ -63,7 +63,12 @@ module OpenapiRuby
63
63
  return if errors.empty?
64
64
 
65
65
  error_messages = errors.first(10).map { |e| e["error"] || e.to_s }
66
- warn "[openapi_ruby] Generated schema '#{@schema_name}' has validation errors:\n#{error_messages.join("\n")}"
66
+ message = "[openapi_ruby] Generated schema '#{@schema_name}' has validation errors:\n#{error_messages.join("\n")}"
67
+ if OpenapiRuby.configuration.strict_reference_validation == :enabled
68
+ raise OpenapiRuby::ConfigurationError, message
69
+ else
70
+ warn message
71
+ end
67
72
  end
68
73
 
69
74
  def format_output(document)
@@ -3,7 +3,7 @@
3
3
  module OpenapiRuby
4
4
  module Middleware
5
5
  class SchemaResolver
6
- def initialize(spec_path: nil, document: nil, strict_reference_validation: true)
6
+ def initialize(spec_path: nil, document: nil, strict_reference_validation: :warn_only)
7
7
  @spec_path = spec_path
8
8
  @document = document
9
9
  @strict_reference_validation = strict_reference_validation
@@ -41,15 +41,19 @@ module OpenapiRuby
41
41
  private
42
42
 
43
43
  def validate_document!(doc)
44
- return unless @strict_reference_validation
44
+ return if @strict_reference_validation == :disabled
45
45
 
46
46
  schemer = JSONSchemer.openapi(doc)
47
47
  errors = schemer.validate.to_a
48
48
  return if errors.empty?
49
49
 
50
50
  error_messages = errors.first(5).map { |e| e["error"] || e.to_s }
51
- raise OpenapiRuby::ConfigurationError,
52
- "OpenAPI document validation failed:\n#{error_messages.join("\n")}"
51
+ message = "OpenAPI document validation failed:\n#{error_messages.join("\n")}"
52
+ if @strict_reference_validation == :enabled
53
+ raise OpenapiRuby::ConfigurationError, message
54
+ else
55
+ warn message
56
+ end
53
57
  end
54
58
 
55
59
  def load_document
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenapiRuby
4
- VERSION = "3.1.0"
4
+ VERSION = "3.1.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openapi-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Morten Hartvig