rspec-openapi 0.4.1 → 0.4.4
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/CHANGELOG.md +15 -0
- data/README.md +22 -14
- data/lib/rspec/openapi/hooks.rb +16 -14
- data/lib/rspec/openapi/record_builder.rb +5 -3
- data/lib/rspec/openapi/schema_merger.rb +8 -4
- data/lib/rspec/openapi/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78fd09cf0ef8419c47bd5b9f8f225260b83f700fcfcb23a2515c50e341832961
|
4
|
+
data.tar.gz: f1895433af3d0a5ee6b065f1e4bbc92bdd4707749480a95b307b685132206bc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae459f44e0471afec512959b999b47fa23b3144efd9272d140a47af6a65ec4f40c234b1f317d197610952263225e247505f8febca1901fe094ebd74b5c8e27b4
|
7
|
+
data.tar.gz: a74f8c5a3121ecbff640c40eccd0f420ae2869b676fdb592411c13e7fddfbfb13fd31c96b9d1ea1e73578c9007c3e78f34dda9bcb820ae4f67b9db5d209fbad7
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## v0.4.4
|
2
|
+
|
3
|
+
- De-duplicate parameters by a combination of `name` and `in`
|
4
|
+
[#39](https://github.com/k0kubun/rspec-openapi/pull/39)
|
5
|
+
|
6
|
+
## v0.4.3
|
7
|
+
|
8
|
+
* Allow customizing `schema`, `description`, and `tags` through `:openapi` metadata
|
9
|
+
[#36](https://github.com/k0kubun/rspec-openapi/pull/36)
|
10
|
+
|
11
|
+
## v0.4.2
|
12
|
+
|
13
|
+
* Allow using Proc as `RSpec::OpenAPI.path`
|
14
|
+
[#35](https://github.com/k0kubun/rspec-openapi/pull/35)
|
15
|
+
|
1
16
|
## v0.4.1
|
2
17
|
|
3
18
|
* Add `RSpec::OpenAPI.example_types` to hook types other than `type: :request`.
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ gem 'rspec-openapi', group: :test
|
|
24
24
|
Run rspec with OPENAPI=1 to generate `doc/openapi.yaml` for your request specs.
|
25
25
|
|
26
26
|
```bash
|
27
|
-
$ OPENAPI=1 rspec
|
27
|
+
$ OPENAPI=1 bundle exec rspec
|
28
28
|
```
|
29
29
|
|
30
30
|
### Example
|
@@ -111,6 +111,15 @@ RSpec::OpenAPI.path = 'doc/schema.yaml'
|
|
111
111
|
# Change the output type to JSON
|
112
112
|
RSpec::OpenAPI.path = 'doc/schema.json'
|
113
113
|
|
114
|
+
# Or generate multiple partial schema files, given an RSpec example
|
115
|
+
RSpec::OpenAPI.path = -> (example) {
|
116
|
+
case example.file_path
|
117
|
+
when %r[spec/requests/api/v1/] then 'doc/openapi/v1.yaml'
|
118
|
+
when %r[spec/requests/api/v2/] then 'doc/openapi/v2.yaml'
|
119
|
+
else 'doc/openapi.yaml'
|
120
|
+
end
|
121
|
+
}
|
122
|
+
|
114
123
|
# Disable generating `example`
|
115
124
|
RSpec::OpenAPI.enable_example = false
|
116
125
|
|
@@ -163,22 +172,21 @@ RSpec.describe '/resources', type: :request do
|
|
163
172
|
end
|
164
173
|
```
|
165
174
|
|
166
|
-
##
|
175
|
+
## Customizations
|
167
176
|
|
168
|
-
|
177
|
+
Some examples' attributes can be overwritten via RSpec metadata options. Example:
|
169
178
|
|
170
|
-
|
171
|
-
|
172
|
-
|
179
|
+
```rb
|
180
|
+
describe 'GET /api/v1/posts', openapi: {
|
181
|
+
summary: 'list all posts',
|
182
|
+
description: 'list all posts ordered by pub_date',
|
183
|
+
tags: %w[v1 posts],
|
184
|
+
} do
|
185
|
+
# ...
|
186
|
+
end
|
187
|
+
```
|
173
188
|
|
174
|
-
|
175
|
-
* Give up, or at least make the feature optional?
|
176
|
-
* Running all to detect obsoleted endpoints is sometimes not realistic anyway.
|
177
|
-
* Intelligent merges
|
178
|
-
* To maintain both automated changes and manual edits, the schema merge needs to be intelligent.
|
179
|
-
* We'll just deep-reverse-merge schema for now, but if there's a $ref for example, modifications
|
180
|
-
there should be rerouted to the referenced object.
|
181
|
-
* A type could be an array of all possible types when merged.
|
189
|
+
**NOTE**: `description` key will override also the one provided by `RSpec::OpenAPI.description_builder` method.
|
182
190
|
|
183
191
|
## Links
|
184
192
|
|
data/lib/rspec/openapi/hooks.rb
CHANGED
@@ -5,34 +5,36 @@ require 'rspec/openapi/schema_builder'
|
|
5
5
|
require 'rspec/openapi/schema_file'
|
6
6
|
require 'rspec/openapi/schema_merger'
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
path_records = Hash.new { |h, k| h[k] = [] }
|
9
|
+
error_records = {}
|
10
10
|
|
11
11
|
RSpec.configuration.after(:each) do |example|
|
12
12
|
if RSpec::OpenAPI.example_types.include?(example.metadata[:type]) && example.metadata[:openapi] != false
|
13
|
+
path = RSpec::OpenAPI.path.yield_self { |path| path.is_a?(Proc) ? path.call(example) : path }
|
13
14
|
record = RSpec::OpenAPI::RecordBuilder.build(self, example: example)
|
14
|
-
|
15
|
+
path_records[path] << record if record
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
19
|
RSpec.configuration.after(:suite) do
|
19
20
|
title = File.basename(Dir.pwd)
|
20
|
-
|
21
|
-
RSpec::OpenAPI::
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
|
21
|
+
path_records.each do |path, records|
|
22
|
+
RSpec::OpenAPI::SchemaFile.new(path).edit do |spec|
|
23
|
+
RSpec::OpenAPI::SchemaMerger.reverse_merge!(spec, RSpec::OpenAPI::DefaultSchema.build(title))
|
24
|
+
records.each do |record|
|
25
|
+
begin
|
26
|
+
RSpec::OpenAPI::SchemaMerger.reverse_merge!(spec, RSpec::OpenAPI::SchemaBuilder.build(record))
|
27
|
+
rescue StandardError, NotImplementedError => e # e.g. SchemaBuilder raises a NotImplementedError
|
28
|
+
error_records[e] = record # Avoid failing the build
|
29
|
+
end
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
31
|
-
if
|
33
|
+
if error_records.any?
|
32
34
|
error_message = <<~EOS
|
33
|
-
RSpec::OpenAPI got errors building #{
|
35
|
+
RSpec::OpenAPI got errors building #{error_records.size} requests
|
34
36
|
|
35
|
-
#{
|
37
|
+
#{error_records.map {|e, record| "#{e.inspect}: #{record.inspect}" }.join("\n")}
|
36
38
|
EOS
|
37
39
|
colorizer = ::RSpec::Core::Formatters::ConsoleCodes
|
38
40
|
RSpec.configuration.reporter.message colorizer.wrap(error_message, :failure)
|
@@ -40,6 +40,8 @@ class << RSpec::OpenAPI::RecordBuilder = Object.new
|
|
40
40
|
headers_arr << [header, header_value] if header_value
|
41
41
|
end
|
42
42
|
|
43
|
+
metadata_options = example.metadata[:openapi] || {}
|
44
|
+
|
43
45
|
RSpec::OpenAPI::Record.new(
|
44
46
|
method: request.request_method,
|
45
47
|
path: path,
|
@@ -48,9 +50,9 @@ class << RSpec::OpenAPI::RecordBuilder = Object.new
|
|
48
50
|
request_params: raw_request_params(request),
|
49
51
|
request_content_type: request.media_type,
|
50
52
|
request_headers: request_headers,
|
51
|
-
summary: summary,
|
52
|
-
tags: tags,
|
53
|
-
description: RSpec::OpenAPI.description_builder.call(example),
|
53
|
+
summary: metadata_options[:summary] || summary,
|
54
|
+
tags: metadata_options[:tags] || tags,
|
55
|
+
description: metadata_options[:description] || RSpec::OpenAPI.description_builder.call(example),
|
54
56
|
status: response.status,
|
55
57
|
response_body: response_body,
|
56
58
|
response_content_type: response.media_type,
|
@@ -21,9 +21,12 @@ class << RSpec::OpenAPI::SchemaMerger = Object.new
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
# Not doing `base.replace(deep_merge(base, spec))` to preserve key orders
|
24
|
+
# Not doing `base.replace(deep_merge(base, spec))` to preserve key orders.
|
25
|
+
# Also this needs to be aware of OpenAPI details unlike an ordinary deep_reverse_merge
|
26
|
+
# because a Hash-like structure may be an array whose Hash elements have a key name.
|
27
|
+
#
|
25
28
|
# TODO: Perform more intelligent merges like rerouting edits / merging types
|
26
|
-
# Should we probably force-merge `summary` regardless of manual modifications?
|
29
|
+
# TODO: Should we probably force-merge `summary` regardless of manual modifications?
|
27
30
|
def deep_reverse_merge!(base, spec)
|
28
31
|
spec.each do |key, value|
|
29
32
|
if base[key].is_a?(Hash) && value.is_a?(Hash)
|
@@ -31,9 +34,10 @@ class << RSpec::OpenAPI::SchemaMerger = Object.new
|
|
31
34
|
elsif !base.key?(key)
|
32
35
|
base[key] = value
|
33
36
|
elsif base[key].is_a?(Array) && value.is_a?(Array)
|
34
|
-
if
|
35
|
-
|
37
|
+
# parameters need to be merged as if `name` and `in` were the Hash keys.
|
38
|
+
if key == 'parameters'
|
36
39
|
base[key] |= value
|
40
|
+
base[key].uniq! { |param| param.slice('name', 'in') }
|
37
41
|
end
|
38
42
|
else
|
39
43
|
# no-op
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-openapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takashi Kokubun
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -90,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
90
|
- !ruby/object:Gem::Version
|
91
91
|
version: '0'
|
92
92
|
requirements: []
|
93
|
-
rubygems_version: 3.
|
93
|
+
rubygems_version: 3.3.7
|
94
94
|
signing_key:
|
95
95
|
specification_version: 4
|
96
96
|
summary: Generate OpenAPI schema from RSpec request specs
|