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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3032d3fed3b9bdc2b2a8512db3d1645679163539106650c1ad05069a15ab59cd
4
- data.tar.gz: d1d3e85b467226a857b30bfe95b5643a1a37df2c0a925e509bdd893ae3017177
3
+ metadata.gz: 78fd09cf0ef8419c47bd5b9f8f225260b83f700fcfcb23a2515c50e341832961
4
+ data.tar.gz: f1895433af3d0a5ee6b065f1e4bbc92bdd4707749480a95b307b685132206bc3
5
5
  SHA512:
6
- metadata.gz: 0c65c74db1ada24cf360545bda34830ca82d9cbd11b6e862a0563f9fc2bf244d65a96ec74e8223c182d1a2bff72b237e30c5884c2818576f9c142585d177351b
7
- data.tar.gz: 397cfcddeaf3c1f683b9a1cd75960bf7d61e24adfcc9988bea2533c7a781acd42f43178b2ffb45deb5b3e821090f979d18af041a078f9ca3c2c7cd124cb4aff2
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
- ## Project status
175
+ ## Customizations
167
176
 
168
- Beta
177
+ Some examples' attributes can be overwritten via RSpec metadata options. Example:
169
178
 
170
- Basic features are there, and some people are already using this.
171
-
172
- ### Other missing features with notes
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
- * Delete obsoleted endpoints
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
 
@@ -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
- records = []
9
- records_errors = []
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
- records << record if record
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
- RSpec::OpenAPI::SchemaFile.new(RSpec::OpenAPI.path).edit do |spec|
21
- RSpec::OpenAPI::SchemaMerger.reverse_merge!(spec, RSpec::OpenAPI::DefaultSchema.build(title))
22
- records.each do |record|
23
- begin
24
- RSpec::OpenAPI::SchemaMerger.reverse_merge!(spec, RSpec::OpenAPI::SchemaBuilder.build(record))
25
- rescue StandardError, NotImplementedError => e # e.g. SchemaBuilder raises a NotImplementedError
26
- # NOTE: Don't fail the build
27
- records_errors << [e, record]
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 records_errors.any?
33
+ if error_records.any?
32
34
  error_message = <<~EOS
33
- RSpec::OpenAPI got errors building #{records_errors.size} requests
35
+ RSpec::OpenAPI got errors building #{error_records.size} requests
34
36
 
35
- #{records_errors.map {|e, record| "#{e.inspect}: #{record.inspect}" }.join("\n")}
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 key == "parameters"
35
- # merge arrays
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
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module OpenAPI
3
- VERSION = '0.4.1'
3
+ VERSION = '0.4.4'
4
4
  end
5
5
  end
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.1
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: 2021-11-22 00:00:00.000000000 Z
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.1.2
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