rspec-openapi 0.10.0 → 0.11.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 +4 -4
- data/.github/workflows/codeql-analysis.yml +3 -3
- data/.github/workflows/rubocop.yml +1 -1
- data/.github/workflows/test.yml +2 -0
- data/.rubocop_todo.yml +18 -8
- data/CHANGELOG.md +10 -0
- data/lib/rspec/openapi/result_recorder.rb +16 -9
- data/lib/rspec/openapi/schema_cleaner.rb +30 -7
- data/lib/rspec/openapi/schema_sorter.rb +35 -0
- data/lib/rspec/openapi/version.rb +1 -1
- data/lib/rspec/openapi.rb +6 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a48ebba5d2201f35bb94f47d5bd649444bb9c58ae1f0ef91f57e315553f9ef2
|
4
|
+
data.tar.gz: 71d4dec68449c2e14b4d3ce7058622b7c56629bee2814e04b1f16e5e817a7bf2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c984f5dbd1a4587a9d34686c50e06a832051215f5e22abc8a96781ecebe57e0bdddabeef093db06f5bea23f58e70322a7574168f621e8765721ab2c2cf19c48
|
7
|
+
data.tar.gz: 2877daab4753106d04275e3189b8a8e648b7268a6c6d7e422e94d5bfb230064a2e875e73531abe6930bfa6c8b7cdefe7d06ee512cdcb4e22adb618915349514b
|
@@ -28,12 +28,12 @@ jobs:
|
|
28
28
|
uses: actions/checkout@v4
|
29
29
|
|
30
30
|
- name: Initialize CodeQL
|
31
|
-
uses: github/codeql-action/init@
|
31
|
+
uses: github/codeql-action/init@v3
|
32
32
|
with:
|
33
33
|
languages: ${{ matrix.language }}
|
34
34
|
|
35
35
|
- name: Autobuild
|
36
|
-
uses: github/codeql-action/autobuild@
|
36
|
+
uses: github/codeql-action/autobuild@v3
|
37
37
|
|
38
38
|
- name: Perform CodeQL Analysis
|
39
|
-
uses: github/codeql-action/analyze@
|
39
|
+
uses: github/codeql-action/analyze@v3
|
data/.github/workflows/test.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -1,25 +1,35 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2024-01-13 11:12:43 UTC using RuboCop version 1.50.2.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count:
|
9
|
+
# Offense count: 9
|
10
10
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
11
11
|
Metrics/AbcSize:
|
12
|
-
Max:
|
12
|
+
Max: 48
|
13
|
+
|
14
|
+
# Offense count: 2
|
15
|
+
# Configuration parameters: CountComments, CountAsOne.
|
16
|
+
Metrics/ClassLength:
|
17
|
+
Max: 192
|
13
18
|
|
14
|
-
# Offense count:
|
19
|
+
# Offense count: 5
|
15
20
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
16
21
|
Metrics/CyclomaticComplexity:
|
17
|
-
Max:
|
22
|
+
Max: 13
|
18
23
|
|
19
|
-
# Offense count:
|
24
|
+
# Offense count: 16
|
20
25
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
21
26
|
Metrics/MethodLength:
|
22
|
-
Max:
|
27
|
+
Max: 31
|
28
|
+
|
29
|
+
# Offense count: 1
|
30
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
31
|
+
Metrics/PerceivedComplexity:
|
32
|
+
Max: 13
|
23
33
|
|
24
34
|
# Offense count: 1
|
25
35
|
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
@@ -29,7 +39,7 @@ Naming/VariableNumber:
|
|
29
39
|
Exclude:
|
30
40
|
- 'spec/integration_tests/roda_test.rb'
|
31
41
|
|
32
|
-
# Offense count:
|
42
|
+
# Offense count: 6
|
33
43
|
# Configuration parameters: AllowedConstants.
|
34
44
|
Style/Documentation:
|
35
45
|
Exclude:
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## v0.11.0
|
2
|
+
|
3
|
+
## What's Changed
|
4
|
+
- feat: Allow path-based config overrides
|
5
|
+
[#162](https://github.com/exoego/rspec-openapi/pull/162)
|
6
|
+
- enhancement: Sort HTTP methods, response status codes, and contents lexicographically
|
7
|
+
[#163](https://github.com/exoego/rspec-openapi/pull/163)
|
8
|
+
- enhancement: Remove parameters that conflict with security schemas
|
9
|
+
[#166](https://github.com/exoego/rspec-openapi/pull/166)
|
10
|
+
|
1
11
|
## v0.10.0
|
2
12
|
- bugfix: Merge parameter data to preserve description in manually edited Openapi spec
|
3
13
|
[#149](https://github.com/exoego/rspec-openapi/pull/149)
|
@@ -7,26 +7,33 @@ class RSpec::OpenAPI::ResultRecorder
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def record_results!
|
10
|
-
title = RSpec::OpenAPI.title
|
11
10
|
@path_records.each do |path, records|
|
11
|
+
# Look for a path-specific config file and run it.
|
12
|
+
config_file = File.join(File.dirname(path), RSpec::OpenAPI.config_filename)
|
13
|
+
begin
|
14
|
+
require config_file if File.exist?(config_file)
|
15
|
+
rescue StandardError => e
|
16
|
+
puts "WARNING: Unable to load #{config_file}: #{e}"
|
17
|
+
end
|
18
|
+
|
19
|
+
title = RSpec::OpenAPI.title
|
12
20
|
RSpec::OpenAPI::SchemaFile.new(path).edit do |spec|
|
13
21
|
schema = RSpec::OpenAPI::DefaultSchema.build(title)
|
14
22
|
schema[:info].merge!(RSpec::OpenAPI.info)
|
15
23
|
RSpec::OpenAPI::SchemaMerger.merge!(spec, schema)
|
16
24
|
new_from_zero = {}
|
17
25
|
records.each do |record|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@error_records[e] = record # Avoid failing the build
|
24
|
-
end
|
26
|
+
record_schema = RSpec::OpenAPI::SchemaBuilder.build(record)
|
27
|
+
RSpec::OpenAPI::SchemaMerger.merge!(spec, record_schema)
|
28
|
+
RSpec::OpenAPI::SchemaMerger.merge!(new_from_zero, record_schema)
|
29
|
+
rescue StandardError, NotImplementedError => e # e.g. SchemaBuilder raises a NotImplementedError
|
30
|
+
@error_records[e] = record # Avoid failing the build
|
25
31
|
end
|
32
|
+
RSpec::OpenAPI::SchemaCleaner.cleanup_conflicting_security_parameters!(spec)
|
26
33
|
RSpec::OpenAPI::SchemaCleaner.cleanup!(spec, new_from_zero)
|
27
34
|
RSpec::OpenAPI::ComponentsUpdater.update!(spec, new_from_zero)
|
28
35
|
RSpec::OpenAPI::SchemaCleaner.cleanup_empty_required_array!(spec)
|
29
|
-
RSpec::OpenAPI::
|
36
|
+
RSpec::OpenAPI::SchemaSorter.deep_sort!(spec)
|
30
37
|
end
|
31
38
|
end
|
32
39
|
end
|
@@ -39,6 +39,24 @@ class << RSpec::OpenAPI::SchemaCleaner = Object.new
|
|
39
39
|
base
|
40
40
|
end
|
41
41
|
|
42
|
+
def cleanup_conflicting_security_parameters!(base)
|
43
|
+
security_schemes = base.dig('components', 'securitySchemes') || {}
|
44
|
+
|
45
|
+
return if security_schemes.empty?
|
46
|
+
|
47
|
+
paths_to_security_definitions = RSpec::OpenAPI::HashHelper.matched_paths_deeply_nested(base, 'paths', 'security')
|
48
|
+
|
49
|
+
paths_to_security_definitions.each do |path|
|
50
|
+
parent_path_definition = base.dig(*path.take(path.length - 1))
|
51
|
+
|
52
|
+
security_schemes.each do |security_scheme_name, security_scheme|
|
53
|
+
remove_parameters_conflicting_with_security_sceheme!(
|
54
|
+
parent_path_definition, security_scheme, security_scheme_name,
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
42
60
|
def cleanup_empty_required_array!(base)
|
43
61
|
paths_to_objects = [
|
44
62
|
*RSpec::OpenAPI::HashHelper.matched_paths_deeply_nested(base, 'components.schemas', 'properties'),
|
@@ -51,15 +69,20 @@ class << RSpec::OpenAPI::SchemaCleaner = Object.new
|
|
51
69
|
end
|
52
70
|
end
|
53
71
|
|
54
|
-
# Sort "paths" lexicographically to make the order more predictable
|
55
|
-
#
|
56
|
-
# @param [Hash] #
|
57
|
-
def sort_paths!(spec)
|
58
|
-
spec['paths'] = spec['paths']&.entries&.sort_by! { |path, _| path }.to_h
|
59
|
-
end
|
60
|
-
|
61
72
|
private
|
62
73
|
|
74
|
+
def remove_parameters_conflicting_with_security_sceheme!(path_definition, security_scheme, security_scheme_name)
|
75
|
+
return unless path_definition['security']
|
76
|
+
return unless path_definition['parameters']
|
77
|
+
return unless path_definition.dig('security', 0).keys.include?(security_scheme_name)
|
78
|
+
|
79
|
+
path_definition['parameters'].reject! do |parameter|
|
80
|
+
parameter['in'] == security_scheme['in'] && # same location (ie. header)
|
81
|
+
parameter['name'] == security_scheme['name'] # same name (ie. AUTHORIZATION)
|
82
|
+
end
|
83
|
+
path_definition.delete('parameters') if path_definition['parameters'].empty?
|
84
|
+
end
|
85
|
+
|
63
86
|
def cleanup_array!(base, spec, selector, fields_for_identity = [])
|
64
87
|
marshal = lambda do |obj|
|
65
88
|
Marshal.dump(slice(obj, fields_for_identity))
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class << RSpec::OpenAPI::SchemaSorter = Object.new
|
4
|
+
# Sort some unpredictably ordered properties in a lexicographical manner to make the order more predictable.
|
5
|
+
#
|
6
|
+
# @param [Hash|Array]
|
7
|
+
def deep_sort!(spec)
|
8
|
+
# paths
|
9
|
+
deep_sort_by_selector!(spec, 'paths')
|
10
|
+
|
11
|
+
# methods
|
12
|
+
deep_sort_by_selector!(spec, 'paths.*')
|
13
|
+
|
14
|
+
# response status code
|
15
|
+
deep_sort_by_selector!(spec, 'paths.*.*.responses')
|
16
|
+
|
17
|
+
# content-type
|
18
|
+
deep_sort_by_selector!(spec, 'paths.*.*.responses.*.content')
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# @param [Hash] base
|
24
|
+
# @param [String] selector
|
25
|
+
def deep_sort_by_selector!(base, selector)
|
26
|
+
RSpec::OpenAPI::HashHelper.matched_paths(base, selector).each do |paths|
|
27
|
+
deep_sort_hash!(base.dig(*paths))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def deep_sort_hash!(hash)
|
32
|
+
sorted = hash.entries.sort_by { |k, _| k }.to_h
|
33
|
+
hash.replace(sorted)
|
34
|
+
end
|
35
|
+
end
|
data/lib/rspec/openapi.rb
CHANGED
@@ -9,6 +9,7 @@ require 'rspec/openapi/schema_builder'
|
|
9
9
|
require 'rspec/openapi/schema_file'
|
10
10
|
require 'rspec/openapi/schema_merger'
|
11
11
|
require 'rspec/openapi/schema_cleaner'
|
12
|
+
require 'rspec/openapi/schema_sorter'
|
12
13
|
|
13
14
|
require 'rspec/openapi/minitest_hooks' if Object.const_defined?('Minitest')
|
14
15
|
require 'rspec/openapi/rspec_hooks' if ENV['OPENAPI'] && Object.const_defined?('RSpec')
|
@@ -31,6 +32,9 @@ module RSpec::OpenAPI
|
|
31
32
|
@path_records = Hash.new { |h, k| h[k] = [] }
|
32
33
|
@ignored_path_params = %i[controller action format]
|
33
34
|
|
35
|
+
# This is the configuraion override file name we look for within each path.
|
36
|
+
@config_filename = 'rspec_openapi.rb'
|
37
|
+
|
34
38
|
class << self
|
35
39
|
attr_accessor :path,
|
36
40
|
:title,
|
@@ -48,5 +52,7 @@ module RSpec::OpenAPI
|
|
48
52
|
:response_headers,
|
49
53
|
:path_records,
|
50
54
|
:ignored_path_params
|
55
|
+
|
56
|
+
attr_reader :config_filename
|
51
57
|
end
|
52
58
|
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.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takashi Kokubun
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-01-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- lib/rspec/openapi/schema_cleaner.rb
|
77
77
|
- lib/rspec/openapi/schema_file.rb
|
78
78
|
- lib/rspec/openapi/schema_merger.rb
|
79
|
+
- lib/rspec/openapi/schema_sorter.rb
|
79
80
|
- lib/rspec/openapi/version.rb
|
80
81
|
- rspec-openapi.gemspec
|
81
82
|
- scripts/rspec
|