rspec-openapi 0.3.13 → 0.3.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2d47641978a7e3644aefc735a5ff71495bd12ab22d3371ff386d5733226afea
4
- data.tar.gz: ccd481a8593efa2a9d0db0cc10a7bb751df1cefac913b44aa93cdc70e7309d0b
3
+ metadata.gz: cd7d2eb0e69e2e60405a7d71d10acd3b2edf2d4db0358297a900200a0a69012e
4
+ data.tar.gz: 577545384d404ba11382ab4425e0bd40abeeb3e58db922e82d923f0d6d6ae8e9
5
5
  SHA512:
6
- metadata.gz: '097a157b4b7c17a1bef1aeb949d41507e09aa72f43dba5158b4a50b0659e44470b59e29d4609d24f04f4936a43e867a4e85834c0cdaa6ddde1096d304d194530'
7
- data.tar.gz: eb1a0c743fb8b64edf56d5a67165ef77afc6c0b48317c0bdfcda7449b1322591fd1c0539b9c4c5992efbab26c6fb3928ec156bcfa137200dce4535b35e0d85b6
6
+ metadata.gz: 5f60ee2cf93946405e3e151786965b3a0f68e53ad147a6d7613f59f46f834efd9a641d0f878943af934879d2f5e27e8c8d4cd55dac5288d62a85dc2b77009ddb
7
+ data.tar.gz: 7dc56150dfb4a8a5b526d7ec626b4ebc9c0680878cd1f976213490a489a598dfe2a285f01029e5a17cdbbe0d8b492fe79a2e51148ac24df94d532c404b0231fd
@@ -0,0 +1 @@
1
+ github: k0kubun
data/CHANGELOG.md CHANGED
@@ -1,3 +1,30 @@
1
+ ## v0.3.18
2
+
3
+ * Support nested query parameters
4
+ [#29](https://github.com/k0kubun/rspec-openapi/pull/29)
5
+
6
+ ## v0.3.17
7
+
8
+ * Rescue NotImplementedError in the after suite hook as well
9
+ [#28](https://github.com/k0kubun/rspec-openapi/pull/28)
10
+
11
+ ## v0.3.16
12
+
13
+ * Use `media_type` instead of `content_type` for Rails 6.1
14
+ [#26](https://github.com/k0kubun/rspec-openapi/pull/26)
15
+ * Avoid crashing the after suite hook when it fails to build schema
16
+ [#27](https://github.com/k0kubun/rspec-openapi/pull/27)
17
+
18
+ ## v0.3.15
19
+
20
+ * Fix an error when Content-Disposition header is inline
21
+ [#24](https://github.com/k0kubun/rspec-openapi/pull/24)
22
+
23
+ ## v0.3.14
24
+
25
+ * Avoid an error when an application calls `request.body.read`
26
+ [#20](https://github.com/k0kubun/rspec-openapi/pull/20)
27
+
1
28
  ## v0.3.13
2
29
 
3
30
  * Avoid crashing when there's no request made in a spec
@@ -6,6 +6,7 @@ require 'rspec/openapi/schema_file'
6
6
  require 'rspec/openapi/schema_merger'
7
7
 
8
8
  records = []
9
+ records_errors = []
9
10
 
10
11
  RSpec.configuration.after(:each) do |example|
11
12
  if example.metadata[:type] == :request && example.metadata[:openapi] != false
@@ -19,7 +20,21 @@ RSpec.configuration.after(:suite) do
19
20
  RSpec::OpenAPI::SchemaFile.new(RSpec::OpenAPI.path).edit do |spec|
20
21
  RSpec::OpenAPI::SchemaMerger.reverse_merge!(spec, RSpec::OpenAPI::DefaultSchema.build(title))
21
22
  records.each do |record|
22
- RSpec::OpenAPI::SchemaMerger.reverse_merge!(spec, RSpec::OpenAPI::SchemaBuilder.build(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]
28
+ end
23
29
  end
24
30
  end
31
+ if records_errors.any?
32
+ error_message = <<~EOS
33
+ RSpec::OpenAPI got errors building #{records_errors.size} requests
34
+
35
+ #{records_errors.map {|e, record| "#{e.inspect}: #{record.inspect}" }.join("\n")}
36
+ EOS
37
+ colorizer = ::RSpec::Core::Formatters::ConsoleCodes
38
+ RSpec.configuration.reporter.message colorizer.wrap(error_message, :failure)
39
+ end
25
40
  end
@@ -11,5 +11,6 @@ RSpec::OpenAPI::Record = Struct.new(
11
11
  :status, # @param [Integer] - 200
12
12
  :response_body, # @param [Object] - {"status" => "ok"}
13
13
  :response_content_type, # @param [String] - "application/json"
14
+ :response_content_disposition, # @param [String] - "inline"
14
15
  keyword_init: true,
15
16
  )
@@ -8,6 +8,7 @@ class << RSpec::OpenAPI::RecordBuilder = Object.new
8
8
  def build(context, example:)
9
9
  if rack_test?(context)
10
10
  request = ActionDispatch::Request.new(context.last_request.env)
11
+ request.body.rewind if request.body.respond_to?(:rewind)
11
12
  response = ActionDispatch::TestResponse.new(*context.last_response.to_a)
12
13
  else
13
14
  request = context.request
@@ -39,13 +40,14 @@ class << RSpec::OpenAPI::RecordBuilder = Object.new
39
40
  path_params: raw_path_params(request),
40
41
  query_params: request.query_parameters,
41
42
  request_params: raw_request_params(request),
42
- request_content_type: request.content_type,
43
+ request_content_type: request.media_type,
43
44
  summary: summary,
44
45
  tags: tags,
45
46
  description: RSpec::OpenAPI.description_builder.call(example),
46
47
  status: response.status,
47
48
  response_body: response_body,
48
- response_content_type: response.content_type,
49
+ response_content_type: response.media_type,
50
+ response_content_disposition: response.header["Content-Disposition"],
49
51
  ).freeze
50
52
  end
51
53
 
@@ -7,10 +7,11 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
7
7
  }
8
8
 
9
9
  if record.response_body
10
+ disposition = normalize_content_disposition(record.response_content_disposition)
10
11
  response[:content] = {
11
12
  normalize_content_type(record.response_content_type) => {
12
- schema: build_property(record.response_body),
13
- example: (record.response_body if example_enabled?),
13
+ schema: build_property(record.response_body, disposition: disposition),
14
+ example: response_example(record, disposition: disposition),
14
15
  }.compact,
15
16
  }
16
17
  end
@@ -34,6 +35,12 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
34
35
 
35
36
  private
36
37
 
38
+ def response_example(record, disposition:)
39
+ return nil if !example_enabled? || disposition
40
+
41
+ record.response_body
42
+ end
43
+
37
44
  def example_enabled?
38
45
  RSpec::OpenAPI.enable_example
39
46
  end
@@ -43,7 +50,7 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
43
50
 
44
51
  record.path_params.each do |key, value|
45
52
  parameters << {
46
- name: key.to_s,
53
+ name: build_parameter_name(key, value),
47
54
  in: 'path',
48
55
  required: true,
49
56
  schema: build_property(try_cast(value)),
@@ -53,7 +60,7 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
53
60
 
54
61
  record.query_params.each do |key, value|
55
62
  parameters << {
56
- name: key.to_s,
63
+ name: build_parameter_name(key, value),
57
64
  in: 'query',
58
65
  schema: build_property(try_cast(value)),
59
66
  example: (try_cast(value) if example_enabled?),
@@ -64,6 +71,16 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
64
71
  parameters
65
72
  end
66
73
 
74
+ def build_parameter_name(key, value)
75
+ key = key.to_s
76
+ if value.is_a?(Hash) && (value_keys = value.keys).size == 1
77
+ value_key = value_keys.first
78
+ build_parameter_name("#{key}[#{value_key}]", value[value_key])
79
+ else
80
+ key
81
+ end
82
+ end
83
+
67
84
  def build_request_body(record)
68
85
  return nil if record.request_content_type.nil?
69
86
  return nil if record.request_params.empty?
@@ -78,8 +95,8 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
78
95
  }
79
96
  end
80
97
 
81
- def build_property(value)
82
- property = build_type(value)
98
+ def build_property(value, disposition: nil)
99
+ property = build_type(value, disposition)
83
100
 
84
101
  case value
85
102
  when Array
@@ -94,7 +111,9 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
94
111
  property
95
112
  end
96
113
 
97
- def build_type(value)
114
+ def build_type(value, disposition)
115
+ return { type: 'string', format: 'binary' } if disposition
116
+
98
117
  case value
99
118
  when String
100
119
  { type: 'string' }
@@ -143,4 +162,8 @@ class << RSpec::OpenAPI::SchemaBuilder = Object.new
143
162
  def normalize_content_type(content_type)
144
163
  content_type&.sub(/;.+\z/, '')
145
164
  end
165
+
166
+ def normalize_content_disposition(content_disposition)
167
+ content_disposition&.sub(/;.+\z/, '')
168
+ end
146
169
  end
@@ -30,6 +30,13 @@ class << RSpec::OpenAPI::SchemaMerger = Object.new
30
30
  deep_reverse_merge!(base[key], value)
31
31
  elsif !base.key?(key)
32
32
  base[key] = value
33
+ elsif base[key].is_a?(Array) && value.is_a?(Array)
34
+ if key == "parameters"
35
+ # merge arrays
36
+ base[key] |= value
37
+ end
38
+ else
39
+ # no-op
33
40
  end
34
41
  end
35
42
  base
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module OpenAPI
3
- VERSION = '0.3.13'
3
+ VERSION = '0.3.18'
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.3.13
4
+ version: 0.3.18
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-02-12 00:00:00.000000000 Z
11
+ date: 2021-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -45,6 +45,7 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
+ - ".github/FUNDING.yml"
48
49
  - ".github/workflows/test.yml"
49
50
  - ".gitignore"
50
51
  - ".rspec"
@@ -89,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
90
  - !ruby/object:Gem::Version
90
91
  version: '0'
91
92
  requirements: []
92
- rubygems_version: 3.2.6
93
+ rubygems_version: 3.1.2
93
94
  signing_key:
94
95
  specification_version: 4
95
96
  summary: Generate OpenAPI schema from RSpec request specs