Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions lib/rspec/openapi/schema_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ def build(record)

private

def enrich_with_required_keys(obj)
if obj.dig(:schema, :type) != 'object'
obj
else
# TODO: Nested object
required_keys = obj.dig(:schema, :properties)&.map do |key, value|
return nil if value[:nullable] == true
key
end.compact
obj[:schema][:required] = required_keys
obj
end
end

def response_example(record, disposition:)
return nil if !example_enabled? || disposition

Expand Down Expand Up @@ -113,10 +127,10 @@ def build_request_body(record)

{
content: {
normalize_content_type(record.request_content_type) => {
normalize_content_type(record.request_content_type) => enrich_with_required_keys({
schema: build_property(record.request_params),
example: (build_example(record.request_params) if example_enabled?),
}.compact,
}).compact,
},
}
end
Expand Down
4 changes: 4 additions & 0 deletions lib/rspec/openapi/schema_merger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ def merge_schema!(base, spec)
if key == 'parameters'
base[key] = value | base[key]
base[key].uniq! { |param| param.slice('name', 'in') }
elsif key == 'required'
# Preserve properties that appears in all test cases
base[key] = value & base[key]
else
# last one wins
base[key] = value
end
else
Expand Down
2 changes: 1 addition & 1 deletion spec/rails/app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ def create
name: params[:name],
relations: {
avatar: {
url: params[:avatar_url],
url: params[:avatar_url] || 'https://example.com/avatar.png',
},
pets: params[:pets] || [],
},
Expand Down
17 changes: 14 additions & 3 deletions spec/rails/doc/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,12 @@
"database_id": {
"type": "integer"
}
}
},
"required": [
"name",
"description",
"database_id"
]
},
"example": {
"name": "k0kubun",
Expand Down Expand Up @@ -409,7 +414,10 @@
}
}
}
}
},
"required": [
"nested"
]
},
"example": {
"nested": {
Expand Down Expand Up @@ -569,7 +577,10 @@
"no_content": {
"type": "string"
}
}
},
"required": [
"no_content"
]
},
"example": {
"no_content": "true"
Expand Down
2 changes: 2 additions & 0 deletions spec/rails/doc/smart/expected.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ paths:
type: string
avatar_url:
type: string
required:
- name
example:
name: alice
avatar_url: "https://example.com/avatar.png"
Expand Down
3 changes: 3 additions & 0 deletions spec/rails/doc/smart/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ paths:
type: array
items:
"$ref": "#/components/schemas/Pet"
required:
- name
- no-such-field
responses:
'201':
description: returns a user
Expand Down
7 changes: 7 additions & 0 deletions spec/requests/rails_smart_merge_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@

RSpec.describe 'Users', type: :request do
describe '#create' do
it 'accepts missing avatar_url' do
post '/users', headers: { authorization: 'k0kubun', 'Content-Type': 'application/json' }, params: {
name: 'alice',
}.to_json
expect(response.status).to eq(201)
end

it 'returns an user' do
post '/users', headers: { authorization: 'k0kubun', 'Content-Type': 'application/json' }, params: {
name: 'alice',
Expand Down
5 changes: 4 additions & 1 deletion spec/roda/doc/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
"id": {
"type": "integer"
}
}
},
"required": [
"id"
]
},
"example": {
"id": 1
Expand Down