oneOf where more than 2 types inside an array
Are you using jest or chai? Jest
Are you using OpenAPI 2, 3.0.X, or 3.1.0? OpenAPI 3.0.3
Describe the bug clearly
When I use oneOf for items in an array with more than 2 distinct references, it fails randomly and can't discriminate which is the matched entity type (even with discriminator property).
Steps to reproduce the bug:
- Create an open api spec with
oneOfwith more than 2 - for example
List:
type: array
items:
oneOf:
- $ref: '#/components/schemas/Account'
- $ref: '#/components/schemas/Item'
- $ref: '#/components/schemas/Payment'
- From an endpoint, return this array with a mix of these 3 entities, eg
[
{ type: 'Account' },
{ type: 'Item' },
{ type: 'Payment' }
]
(my actual entities are more complex than this, but for the sake of a simple bug description, this will suffice)
- It fails on 1 of the 3 entity types, if I remove one and only do 2 entity types then it is fine.
What did you expect to happen instead? It validates the array correctly
Are you going to resolve the issue? If I'm pointed in the right direction I may be able to!
Thanks for raising this @harveyappleton 🙂
I may have time next weekend to look at this. In the meantime if you'd like to recreate this using this file: https://github.com/openapi-library/OpenAPIValidators/blob/master/packages/jest-openapi/test/bugRecreationTemplate.test.ts (just clone the repo and post a link to your branch here). That will help speed up my investigation
Hey @rwalle61 - think I might have found cause of issue AND produced a demo
https://github.com/harveyappleton/OpenAPIValidators/tree/master
Clone this fork
Go into project
cd packages/jest-openapi
yarn test
You should see the failing test
● Recreate bug (issue #257) › passes
expect(received).toSatisfyApiSpec() // Matches 'received' to a response defined in your API spec, then validates 'received' against it
expected received to satisfy the '200' response defined for endpoint 'GET /recreate/bug' in your API spec
received did not satisfy it because: included/1/type must be equal to one of the allowed values, included/1/attributes must have required property 'rating', included/1/attributes must NOT have additional properties, included/1/type must be equal to one of the allowed values, included/1/type must be equal to one of the allowed values, included/1/attributes must have required property 'description', included/1/attributes must NOT have additional properties, included/1 must match exactly one schema in oneOf, included/3/type must be equal to one of the allowed values, included/3/attributes must have required property 'rating', included/3/attributes must NOT have additional properties, included/3/type must be equal to one of the allowed values, included/3/type must be equal to one of the allowed values, included/3/attributes must have required property 'description', included/3/attributes must NOT have additional properties, included/3 must match exactly one schema in oneOf
received contained: {
body: {
included: [
{ type: 'Apple', attributes: { rating: 5 } },
{ type: 'AppleOrange', attributes: { isTasty: true } },
{
type: 'Banana',
attributes: { description: 'Yellow and sumptuous' }
},
{ type: 'AppleOrange', attributes: { isTasty: false } },
{
type: 'Banana',
attributes: { description: 'Another thing about a banana' }
}
]
}
}
It is because it seems to match AppleOrange as Apple, perhaps it is using some sort of string starts with method? Rather than matching the entire string??
If you change AppleOrange to Orange (in both the test file and schema), it will pass!
Schema & test file are in: OpenAPIValidators/blob/master/packages/jest-openapi/__test__ on my branch.
Hope that helps
Thanks @harveyappleton ! I didn't have time to investigate this weekend but you've given me a great starting point for when I can. Seems like something odd is happening
No problems @rwalle61 - if you can point me in the right direction, I might be able to do a fix for this :)
@rwalle61 any progress on the oneOf issues?
I have similar problem with the following:
received did not satisfy it because: response must match exactly one schema in oneOf
received contained: { body: { id: 'e1b051bf-e12e-4c1f-a257-f9de2de8bbfb' } }
OpenAPI:
The '201' response defined for endpoint 'POST /jobs/{myId}/foos' in API spec: {
'201': {
description: 'Foo created successfully',
content: {
'application/json': {
schema: {
oneOf: [
{ '$ref': '#/components/schemas/createFooResponse' },
{
'$ref': '#/components/schemas/createMultipleFoosResponse'
}
]
}
}
}
}
}
createFooResponse:
type: object
properties:
id:
$ref: '#/components/schemas/fooId'
createMultipleFoosResponse:
type: object
properties:
ids:
type: array
items:
$ref: '#/components/schemas/fooId'
fooId:
type: string
format: uuid
Sorry I don't have time to investigate this further, happy for someone else to take a closer look 🙂 we parse the OpenAPI spec and pass the schemas to a 3rd party validator (openapi-response-validator) so it would be good to confirm if the bug is in our code or theirs (in my experience, it is probably ours 😁)