rspec-openapi 0.25.0 → 0.25.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: 65e97b91c81a4798c7907d907174d8c7efe874ad26dd3d630db2c86db97f913d
4
- data.tar.gz: a593eaf58214a7bc5578f3cee065d263d7b494507727ac05c60111d01b0a2a7d
3
+ metadata.gz: fdb09465b214320cfd32bf020363827d17c3346d48cb7e724effc99df6bdf722
4
+ data.tar.gz: 9947b0df4b2af301473ff89cd52cd035d8a4cb129bd83f8aacef2fc4df107cd5
5
5
  SHA512:
6
- metadata.gz: 3e88fae82f5452b748d2ade83adc141fff0e888946c48ec3219999012bd75a7162e678d89af1e1ccb584e14250739715e0ffd53ec1b1ff101080ca2abd44ba82
7
- data.tar.gz: e49fdd879b02d43fe0f8ac4ef2d443b7a0366c5f133d5012f771be380c706b9fa28597f6bd6e6e111bee599bee26e5ae71f8dec262e4bf6070c679790e42d654
6
+ metadata.gz: f17329553b8d2a02b196faba4ac592826557acb79648f364994614759e762608241d1310be6080873703af3b7f45d111db3509302f9ec22270c6c3c849bbd180
7
+ data.tar.gz: dd616bc6570e99d2b6439d4003bcadcdc9881613c6f4ba0428191ceef2c7c73dd185c5e385ea6c8af271f98d5c67d3e597062052d2c3bd7c59d1c0f6e75f0deb
@@ -4,7 +4,7 @@ on:
4
4
  workflow_dispatch:
5
5
  inputs:
6
6
  version:
7
- description: 'Version to release (e.g. 0.25.1 or 0.26.0)'
7
+ description: 'Version to release (e.g. 0.25.2 or 0.26.0)'
8
8
  required: true
9
9
 
10
10
  jobs:
@@ -42,7 +42,7 @@ jobs:
42
42
  - run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
43
43
  name: codecov-action@v4 workaround
44
44
  - name: Upload coverage reports
45
- uses: codecov/codecov-action@v5
45
+ uses: codecov/codecov-action@v6
46
46
  if: matrix.coverage == 'coverage'
47
47
  with:
48
48
  fail_ci_if_error: true
@@ -3,6 +3,8 @@
3
3
  require_relative 'hash_helper'
4
4
 
5
5
  class << RSpec::OpenAPI::ComponentsUpdater = Object.new
6
+ SCHEMA_REF_PREFIX = '#/components/schemas/'
7
+
6
8
  # @param [Hash] base
7
9
  # @param [Hash] fresh
8
10
  def update!(base, fresh)
@@ -30,7 +32,7 @@ class << RSpec::OpenAPI::ComponentsUpdater = Object.new
30
32
  # Skip if the property using $ref is not found in the parent schema. The property may be removed.
31
33
  next if nested_schema.nil?
32
34
 
33
- schema_name = base.dig(*paths)&.gsub('#/components/schemas/', '')&.to_sym
35
+ schema_name = extract_schema_name(base.dig(*paths))&.to_sym
34
36
  fresh_schemas[schema_name] ||= {}
35
37
  RSpec::OpenAPI::SchemaMerger.merge!(fresh_schemas[schema_name], nested_schema)
36
38
  end
@@ -44,8 +46,8 @@ class << RSpec::OpenAPI::ComponentsUpdater = Object.new
44
46
  def build_fresh_schemas(references, base, fresh)
45
47
  references.inject({}) do |acc, paths|
46
48
  ref_link = dig_schema(base, paths)[:$ref]
47
- schema_name = ref_link.to_s.gsub('#/components/schemas/', '')
48
- schema_body = dig_schema(fresh, paths.reject { |path| path.is_a?(Integer) })
49
+ schema_name = extract_schema_name(ref_link)
50
+ schema_body = dig_schema(fresh, paths.grep_v(Integer))
49
51
 
50
52
  RSpec::OpenAPI::SchemaMerger.merge!(acc, { schema_name => schema_body })
51
53
  end
@@ -81,18 +83,29 @@ class << RSpec::OpenAPI::ComponentsUpdater = Object.new
81
83
  # Reject already-generated schemas to reduce unnecessary loop
82
84
  nested_refs.reject do |paths|
83
85
  ref_link = base.dig(*paths)
84
- schema_name = ref_link.gsub('#/components/schemas/', '')
86
+ schema_name = extract_schema_name(ref_link)
85
87
  generated_names.include?(schema_name)
86
88
  end
87
89
  end
88
90
 
89
91
  def find_one_of_refs(base, paths)
90
- dig_schema(base, paths)&.dig(:oneOf)&.map&.with_index do |schema, index|
91
- paths + [index] if schema&.dig(:$ref)&.start_with?('#/components/schemas/')
92
- end&.compact
92
+ one_of = dig_schema(base, paths)&.dig(:oneOf)
93
+ return unless one_of
94
+
95
+ one_of.each_with_index.filter_map do |schema, index|
96
+ paths + [index] if schema_ref?(schema&.dig(:$ref))
97
+ end
93
98
  end
94
99
 
95
100
  def find_object_refs(base, paths)
96
- [paths] if dig_schema(base, paths)&.dig(:$ref)&.start_with?('#/components/schemas/')
101
+ [paths] if schema_ref?(dig_schema(base, paths)&.dig(:$ref))
102
+ end
103
+
104
+ def extract_schema_name(ref_link)
105
+ ref_link&.delete_prefix(SCHEMA_REF_PREFIX)
106
+ end
107
+
108
+ def schema_ref?(ref_link)
109
+ ref_link&.start_with?(SCHEMA_REF_PREFIX)
97
110
  end
98
111
  end
@@ -38,13 +38,11 @@ end
38
38
  InspectorAnalyzer = Inspector.new
39
39
 
40
40
  # Add default parameter to load inspector before test cases run
41
- module InspectorAnalyzerPrepender
41
+ Hanami::Slice::ClassMethods.prepend(Module.new do
42
42
  def router(inspector: InspectorAnalyzer)
43
43
  super
44
44
  end
45
- end
46
-
47
- Hanami::Slice::ClassMethods.prepend(InspectorAnalyzerPrepender)
45
+ end)
48
46
 
49
47
  # Extractor for hanami
50
48
  class << RSpec::OpenAPI::Extractors::Hanami = Object.new
@@ -63,11 +61,11 @@ class << RSpec::OpenAPI::Extractors::Hanami = Object.new
63
61
 
64
62
  raw_path_params = route.params
65
63
 
66
- result = InspectorAnalyzer.call(request.method, add_id(path, route))
64
+ result = InspectorAnalyzer.call(request.method, replace_path_params(path, route, '/:%{key}'))
67
65
 
68
66
  summary ||= result[:summary]
69
67
  tags ||= result[:tags]
70
- path = add_openapi_id(path, route)
68
+ path = replace_path_params(path, route, '/{%{key}}')
71
69
 
72
70
  raw_path_params = raw_path_params.slice(*(raw_path_params.keys - RSpec::OpenAPI.ignored_path_params))
73
71
 
@@ -101,21 +99,11 @@ class << RSpec::OpenAPI::Extractors::Hanami = Object.new
101
99
 
102
100
  private
103
101
 
104
- def add_id(path, route)
105
- return path if route.params.empty?
106
-
107
- route.params.each_pair do |key, value|
108
- path = path.sub("/#{value}", "/:#{key}")
109
- end
110
-
111
- path
112
- end
113
-
114
- def add_openapi_id(path, route)
102
+ def replace_path_params(path, route, format)
115
103
  return path if route.params.empty?
116
104
 
117
105
  route.params.each_pair do |key, value|
118
- path = path.sub("/#{value}", "/{#{key}}")
106
+ path = path.sub("/#{value}", format % { key: key })
119
107
  end
120
108
 
121
109
  path
@@ -12,8 +12,9 @@ class << RSpec::OpenAPI::RecordBuilder = Object.new
12
12
  return if request.nil?
13
13
 
14
14
  title = RSpec::OpenAPI.title.then { |t| t.is_a?(Proc) ? t.call(example) : t }
15
- path, summary, tags, operation_id, required_request_params, raw_path_params, description, security, deprecated,
16
- formats, example_mode, example_key, example_name, response_enum, request_enum = extractor.request_attributes(request, example)
15
+ path, summary, tags, operation_id, required_request_params, raw_path_params,
16
+ description, security, deprecated, formats, example_mode, example_key,
17
+ example_name, response_enum, request_enum = extractor.request_attributes(request, example)
17
18
 
18
19
  return if RSpec::OpenAPI.ignored_paths.any? { |ignored_path| path.match?(ignored_path) }
19
20
 
@@ -270,8 +270,8 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
270
270
  enum_hash = context == :request ? record.request_enum : record.response_enum
271
271
  return nil unless enum_hash
272
272
 
273
- # Try both string and symbol keys
274
- enum_hash[path.to_s] || enum_hash[path.to_sym]
273
+ # Keys are already normalized to strings by SharedExtractor.normalize_enum
274
+ enum_hash[path.to_s]
275
275
  end
276
276
 
277
277
  # Convert an always-String param to an appropriate type
@@ -319,14 +319,13 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
319
319
  content_type&.sub(/;.+\z/, '')
320
320
  end
321
321
 
322
- def normalize_content_disposition(content_disposition)
323
- content_disposition&.sub(/;.+\z/, '')
324
- end
322
+ # Same logic as normalize_content_type – strips header parameters after ';'
323
+ alias normalize_content_disposition normalize_content_type
325
324
 
326
325
  def build_array_items_schema(array, record: nil, path: nil, context: nil)
327
326
  return {} if array.empty?
328
327
  return build_property(array.first, record: record, path: path, context: context) if array.size == 1
329
- return build_property(array.first, record: record, path: path, context: context) unless array.all? { |item| item.is_a?(Hash) }
328
+ return build_property(array.first, record: record, path: path, context: context) unless array.all?(Hash)
330
329
 
331
330
  all_schemas = array.map { |item| build_property(item, record: record, path: path, context: context) }
332
331
  merged_schema = all_schemas.first.dup
@@ -70,6 +70,8 @@ class << RSpec::OpenAPI::SchemaCleaner = Object.new
70
70
  ]
71
71
  paths_to_objects.each do |path|
72
72
  parent = base.dig(*path.take(path.length - 1))
73
+ next unless parent
74
+
73
75
  # "required" array must not be present if empty
74
76
  parent.delete(:required) if parent[:required] && parent[:required].empty?
75
77
  end
@@ -9,6 +9,8 @@ class << RSpec::OpenAPI::SchemaMerger = Object.new
9
9
  merge_schema!(base, spec)
10
10
  end
11
11
 
12
+ SIMILARITY_THRESHOLD = 0.5
13
+
12
14
  private
13
15
 
14
16
  # Not doing `base.replace(deep_merge(base, spec))` to preserve key orders.
@@ -121,13 +123,11 @@ class << RSpec::OpenAPI::SchemaMerger = Object.new
121
123
  end
122
124
 
123
125
  def build_unique_params(base, key)
124
- base[key].each_with_object({}) do |parameter, hash|
125
- hash[[parameter[:name], parameter[:in]]] = parameter
126
+ base[key].to_h do |parameter|
127
+ [[parameter[:name], parameter[:in]], parameter]
126
128
  end
127
129
  end
128
130
 
129
- SIMILARITY_THRESHOLD = 0.5
130
-
131
131
  # Normalize example/examples fields when there's a conflict
132
132
  # OpenAPI spec doesn't allow both example and examples in the same object
133
133
  def normalize_example_fields!(base, spec)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module OpenAPI
5
- VERSION = '0.25.0'
5
+ VERSION = '0.25.1'
6
6
  end
7
7
  end
data/lib/rspec/openapi.rb CHANGED
@@ -33,7 +33,7 @@ module RSpec::OpenAPI
33
33
  @comment = nil
34
34
  @enable_example = true
35
35
  @enable_example_summary = true
36
- @description_builder = ->(example) { example.description }
36
+ @description_builder = :description.to_proc
37
37
  @example_name_builder = :description.to_proc
38
38
  @summary_builder = ->(example) { example.metadata[:summary] }
39
39
  @tags_builder = ->(example) { example.metadata[:tags] }
@@ -31,5 +31,4 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency 'actionpack', '>= 5.2.0'
32
32
  spec.add_dependency 'rails-dom-testing'
33
33
  spec.add_dependency 'rspec-core'
34
- spec.metadata['rubygems_mfa_required'] = 'true'
35
34
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-openapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.25.0
4
+ version: 0.25.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Takashi Kokubun
@@ -112,7 +112,7 @@ licenses:
112
112
  metadata:
113
113
  homepage_uri: https://github.com/exoego/rspec-openapi
114
114
  source_code_uri: https://github.com/exoego/rspec-openapi
115
- changelog_uri: https://github.com/exoego/rspec-openapi/releases/tag/v0.25.0
115
+ changelog_uri: https://github.com/exoego/rspec-openapi/releases/tag/v0.25.1
116
116
  rubygems_mfa_required: 'true'
117
117
  rdoc_options: []
118
118
  require_paths:
@@ -128,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
128
  - !ruby/object:Gem::Version
129
129
  version: '0'
130
130
  requirements: []
131
- rubygems_version: 4.0.3
131
+ rubygems_version: 4.0.6
132
132
  specification_version: 4
133
133
  summary: Generate OpenAPI schema from RSpec request specs
134
134
  test_files: []