rspec-openapi 0.9.0 → 0.10.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/dependabot.yml +8 -0
- data/.github/workflows/codeql-analysis.yml +1 -1
- data/.github/workflows/rubocop.yml +1 -1
- data/.github/workflows/test.yml +6 -1
- data/.simplecov_spawn.rb +1 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +1 -1
- data/README.md +18 -3
- data/lib/rspec/openapi/record_builder.rb +3 -3
- data/lib/rspec/openapi/result_recorder.rb +2 -1
- data/lib/rspec/openapi/schema_builder.rb +1 -0
- data/lib/rspec/openapi/schema_cleaner.rb +7 -0
- data/lib/rspec/openapi/schema_merger.rb +22 -10
- data/lib/rspec/openapi/version.rb +1 -1
- data/lib/rspec/openapi.rb +9 -1
- data/scripts/rspec_with_simplecov +1 -2
- 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: 9749f7a6121a78737336bd436f5fda8b20381a82f4cb507f42667bf3d38a2a4b
|
4
|
+
data.tar.gz: ff0bc4a559323f1285d282ab786b5666c950b8ad0b9585fa749cf1f2b0f3613e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e412c58158ffaa1518640e3082ef04c41d50ec43de94ef032c866ebbec2468775d4ea3b2c976294f14ce6b8570b3e86df7248f17877c491efa9fc31e5a8819a
|
7
|
+
data.tar.gz: 65d7308f7d552d9ac299a6d3330933283c237345b477de260a2e2af24210268f2e41350619cec83f145f028a7374b197281cbd9752d1cb2aa3baa696f8240739
|
data/.github/workflows/test.yml
CHANGED
@@ -31,9 +31,14 @@ jobs:
|
|
31
31
|
RAILS_VERSION: ${{ matrix.rails == '' && '6.1.6' || matrix.rails }}
|
32
32
|
COVERAGE: ${{ matrix.coverage || '' }}
|
33
33
|
steps:
|
34
|
-
- uses: actions/checkout@
|
34
|
+
- uses: actions/checkout@v4
|
35
35
|
- name: bundle install
|
36
36
|
run: bundle install -j$(nproc) --retry 3
|
37
|
+
- name: install simplecov-fork only for minitest with coverage
|
38
|
+
run: |
|
39
|
+
gem install specific_install
|
40
|
+
gem specific_install https://github.com/exoego/simplecov.git branch-fix
|
41
|
+
if: matrix.coverage == 'coverage'
|
37
42
|
- run: bundle exec rspec
|
38
43
|
timeout-minutes: 1
|
39
44
|
- name: Upload coverage reports
|
data/.simplecov_spawn.rb
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## v0.10.0
|
2
|
+
- bugfix: Merge parameter data to preserve description in manually edited Openapi spec
|
3
|
+
[#149](https://github.com/exoego/rspec-openapi/pull/149)
|
4
|
+
- feat: Add ability to configure which path params to ignore
|
5
|
+
[#150](https://github.com/exoego/rspec-openapi/pull/150)
|
6
|
+
- feat: Add custom title
|
7
|
+
[#147](https://github.com/exoego/rspec-openapi/pull/147)
|
8
|
+
- feat: Add ability to define custom summary and tags builders
|
9
|
+
[#148](https://github.com/exoego/rspec-openapi/pull/148)
|
10
|
+
- enhancement: Sort paths lexicographically so the order of paths is more stable and predictable
|
11
|
+
[#155](https://github.com/exoego/rspec-openapi/pull/155)
|
12
|
+
- enhancement: requestBody should not merge requestBody from error examples
|
13
|
+
[#154](https://github.com/exoego/rspec-openapi/pull/154)
|
14
|
+
|
1
15
|
## v0.9.0
|
2
16
|
- bugfix: Fix engine path resolution
|
3
17
|
[#113](https://github.com/exoego/rspec-openapi/pull/113)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# rspec-openapi  [](https://codecov.io/gh/exoego/rspec-openapi)
|
1
|
+
# rspec-openapi [](https://badge.fury.io/rb/rspec-openapi) [](https://github.com/exoego/rspec-openapi/actions/workflows/test.yml) [](https://codecov.io/gh/exoego/rspec-openapi)
|
2
2
|
|
3
3
|
Generate OpenAPI schema from RSpec request specs.
|
4
4
|
|
@@ -122,6 +122,8 @@ RSpec::OpenAPI.path = -> (example) {
|
|
122
122
|
end
|
123
123
|
}
|
124
124
|
|
125
|
+
RSpec::OpenAPI.title = 'OpenAPI Documentation'
|
126
|
+
|
125
127
|
# Disable generating `example`
|
126
128
|
RSpec::OpenAPI.enable_example = false
|
127
129
|
|
@@ -167,8 +169,21 @@ EOS
|
|
167
169
|
# Generate a custom description, given an RSpec example
|
168
170
|
RSpec::OpenAPI.description_builder = -> (example) { example.description }
|
169
171
|
|
172
|
+
# Generate a custom summary, given an RSpec example
|
173
|
+
# This example uses the summary from the example_group.
|
174
|
+
RSpec::OpenAPI.summary_builder = ->(example) { example.metadata.dig(:example_group, :openapi, :summary) }
|
175
|
+
|
176
|
+
# Generate a custom tags, given an RSpec example
|
177
|
+
# This example uses the tags from the parent_example_group
|
178
|
+
RSpec::OpenAPI.tags_builder = -> (example) { example.metadata.dig(:example_group, :parent_example_group, :openapi, :tags) }
|
179
|
+
|
170
180
|
# Change the example type(s) that will generate schema
|
171
181
|
RSpec::OpenAPI.example_types = %i[request]
|
182
|
+
|
183
|
+
# Configure which path params to ignore
|
184
|
+
# :controller and :action always exist. :format is added when routes is configured as such.
|
185
|
+
RSpec::OpenAPI.ignored_path_params = %i[controller action format]
|
186
|
+
|
172
187
|
```
|
173
188
|
|
174
189
|
### Can I use rspec-openapi with `$ref` to minimize duplication of schema?
|
@@ -199,7 +214,7 @@ paths:
|
|
199
214
|
application/json:
|
200
215
|
schema:
|
201
216
|
$ref: "#/components/schemas/User"
|
202
|
-
# Note) #/components/
|
217
|
+
# Note) #/components/schemas is not needed to be defined.
|
203
218
|
```
|
204
219
|
|
205
220
|
3. Then, re-run rspec-openapi. It will generate `#/components/schemas` with the referenced schema (`User` for example) newly-generated or updated.
|
@@ -278,7 +293,7 @@ If you find a room for improvement, open an issue.
|
|
278
293
|
|
279
294
|
### How can I add information which can't be generated from RSpec?
|
280
295
|
|
281
|
-
rspec-openapi tries to
|
296
|
+
rspec-openapi tries to preserve manual modifications as much as possible when generating specs.
|
282
297
|
You can directly edit `doc/openapi.yaml` as you like without spoiling the automatic generation capability.
|
283
298
|
|
284
299
|
### Can I exclude specific specs from OpenAPI generation?
|
@@ -62,8 +62,8 @@ class << RSpec::OpenAPI::RecordBuilder = Object.new
|
|
62
62
|
|
63
63
|
def extract_request_attributes(request, example)
|
64
64
|
metadata = example.metadata[:openapi] || {}
|
65
|
-
summary = metadata[:summary]
|
66
|
-
tags = metadata[:tags]
|
65
|
+
summary = metadata[:summary] || RSpec::OpenAPI.summary_builder.call(example)
|
66
|
+
tags = metadata[:tags] || RSpec::OpenAPI.tags_builder.call(example)
|
67
67
|
operation_id = metadata[:operation_id]
|
68
68
|
required_request_params = metadata[:required_request_params] || []
|
69
69
|
security = metadata[:security]
|
@@ -83,7 +83,7 @@ class << RSpec::OpenAPI::RecordBuilder = Object.new
|
|
83
83
|
tags ||= [route.requirements[:controller]&.classify].compact
|
84
84
|
# :controller and :action always exist. :format is added when routes is configured as such.
|
85
85
|
# TODO: Use .except(:controller, :action, :format) when we drop support for Ruby 2.x
|
86
|
-
raw_path_params = raw_path_params.slice(*(raw_path_params.keys -
|
86
|
+
raw_path_params = raw_path_params.slice(*(raw_path_params.keys - RSpec::OpenAPI.ignored_path_params))
|
87
87
|
end
|
88
88
|
summary ||= "#{request.method} #{path}"
|
89
89
|
[path, summary, tags, operation_id, required_request_params, raw_path_params, description, security]
|
@@ -7,7 +7,7 @@ class RSpec::OpenAPI::ResultRecorder
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def record_results!
|
10
|
-
title =
|
10
|
+
title = RSpec::OpenAPI.title
|
11
11
|
@path_records.each do |path, records|
|
12
12
|
RSpec::OpenAPI::SchemaFile.new(path).edit do |spec|
|
13
13
|
schema = RSpec::OpenAPI::DefaultSchema.build(title)
|
@@ -26,6 +26,7 @@ class RSpec::OpenAPI::ResultRecorder
|
|
26
26
|
RSpec::OpenAPI::SchemaCleaner.cleanup!(spec, new_from_zero)
|
27
27
|
RSpec::OpenAPI::ComponentsUpdater.update!(spec, new_from_zero)
|
28
28
|
RSpec::OpenAPI::SchemaCleaner.cleanup_empty_required_array!(spec)
|
29
|
+
RSpec::OpenAPI::SchemaCleaner.sort_paths!(spec)
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -51,6 +51,13 @@ class << RSpec::OpenAPI::SchemaCleaner = Object.new
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
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
|
+
|
54
61
|
private
|
55
62
|
|
56
63
|
def cleanup_array!(base, spec, selector, fields_for_identity = [])
|
@@ -43,16 +43,28 @@ class << RSpec::OpenAPI::SchemaMerger = Object.new
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def merge_arrays(base, key, value)
|
46
|
-
case key
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
46
|
+
base[key] = case key
|
47
|
+
when 'parameters'
|
48
|
+
merge_parameters(base, key, value)
|
49
|
+
when 'required'
|
50
|
+
# Preserve properties that appears in all test cases
|
51
|
+
value & base[key]
|
52
|
+
else
|
53
|
+
# last one wins
|
54
|
+
value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def merge_parameters(base, key, value)
|
59
|
+
all_parameters = value | base[key]
|
60
|
+
|
61
|
+
unique_base_parameters = base[key].index_by { |parameter| [parameter['name'], parameter['in']] }
|
62
|
+
all_parameters = all_parameters.map do |parameter|
|
63
|
+
base_parameter = unique_base_parameters[[parameter['name'], parameter['in']]] || {}
|
64
|
+
base_parameter ? base_parameter.merge(parameter) : parameter
|
56
65
|
end
|
66
|
+
|
67
|
+
all_parameters.uniq! { |param| param.slice('name', 'in') }
|
68
|
+
base[key] = all_parameters
|
57
69
|
end
|
58
70
|
end
|
data/lib/rspec/openapi.rb
CHANGED
@@ -15,9 +15,12 @@ require 'rspec/openapi/rspec_hooks' if ENV['OPENAPI'] && Object.const_defined?('
|
|
15
15
|
|
16
16
|
module RSpec::OpenAPI
|
17
17
|
@path = 'doc/openapi.yaml'
|
18
|
+
@title = File.basename(Dir.pwd)
|
18
19
|
@comment = nil
|
19
20
|
@enable_example = true
|
20
21
|
@description_builder = ->(example) { example.description }
|
22
|
+
@summary_builder = ->(example) { example.metadata[:summary] }
|
23
|
+
@tags_builder = ->(example) { example.metadata[:tags] }
|
21
24
|
@info = {}
|
22
25
|
@application_version = '1.0.0'
|
23
26
|
@request_headers = []
|
@@ -26,12 +29,16 @@ module RSpec::OpenAPI
|
|
26
29
|
@example_types = %i[request]
|
27
30
|
@response_headers = []
|
28
31
|
@path_records = Hash.new { |h, k| h[k] = [] }
|
32
|
+
@ignored_path_params = %i[controller action format]
|
29
33
|
|
30
34
|
class << self
|
31
35
|
attr_accessor :path,
|
36
|
+
:title,
|
32
37
|
:comment,
|
33
38
|
:enable_example,
|
34
39
|
:description_builder,
|
40
|
+
:summary_builder,
|
41
|
+
:tags_builder,
|
35
42
|
:info,
|
36
43
|
:application_version,
|
37
44
|
:request_headers,
|
@@ -39,6 +46,7 @@ module RSpec::OpenAPI
|
|
39
46
|
:security_schemes,
|
40
47
|
:example_types,
|
41
48
|
:response_headers,
|
42
|
-
:path_records
|
49
|
+
:path_records,
|
50
|
+
:ignored_path_params
|
43
51
|
end
|
44
52
|
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.10.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: 2023-
|
12
|
+
date: 2023-12-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -47,6 +47,7 @@ executables: []
|
|
47
47
|
extensions: []
|
48
48
|
extra_rdoc_files: []
|
49
49
|
files:
|
50
|
+
- ".github/dependabot.yml"
|
50
51
|
- ".github/workflows/codeql-analysis.yml"
|
51
52
|
- ".github/workflows/rubocop.yml"
|
52
53
|
- ".github/workflows/test.yml"
|