Mock: `override.mock.properties` needs to recurse inside arrrays
Please consider this OpenAPI spec (simplified for brevity)
paths:
/users:
get:
operationId: getUsers
responses:
'200':
description: User listing success
content:
application/json:
schema:
$ref: '#/components/schemas/retrievedUsers'
/user/{id}:
get:
operationId: getUser
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: User get success
content:
application/json:
schema:
$ref: '#/components/schemas/retrievedUser'
components:
schemas:
baseUser:
type: object
description: Base user object
properties:
firstName:
type: string
lastName:
type: string
email:
type: string
retrievedUser:
description: User object as it shall be retrieved
allOf:
- $ref: '#/components/schemas/baseUser'
- type: object
required: ["id", "lastName", "email"]
properties:
id:
type: string
retrievedUsers:
description: Array of `retrievedUser` objects
type: array
items:
$ref: '#/components/schemas/retrievedUser'
And this config (also simplified for brevity):
export default defineConfig({
myproject: {
input: {
target: 'spec/myproject.yml',
},
output: {
mode: 'split',
target: 'src/gen/myproject.ts',
client: 'fetch',
mock: true,
override: {
mock: {
properties: {
firstName: () => faker.person.firstName(),
lastName: () => faker.person.lastName(),
email: () => faker.internet.email(),
},
},
},
}
});
The faker calls are used in the getUser mocks, but they are completely ignored in the getUsers mock. Just because they are objects in an array?... Why does that matter?
Compare a correctly generated mock:
export const getGetUserResponseMock = (): RetrievedUser => ({
...{
firstName: (() => faker.person.firstName())(),
lastName: (() => faker.person.lastName())(),
email: (() => faker.internet.email())(),
}, ...{ id: faker.string.alpha({ length: { min: 10, max: 20 } }) },
});
With the one where it goes wrong:
export const getGetUsersResponseMock = (): RetrievedUsers => (
Array.from({ length: faker.number.int({ min: 1, max: 10 }) }, (_, i) => i + 1).map(() => ({
...{
firstName: faker.helpers.arrayElement([faker.string.alpha({ length: { min: 10, max: 20 } }), undefined]),
lastName: faker.helpers.arrayElement([faker.string.alpha({ length: { min: 10, max: 20 } }), undefined]),
email: faker.helpers.arrayElement([faker.string.alpha({ length: { min: 10, max: 20 } }), undefined]),
},
}))
);
Why is it not using the functions I told it to use? The properties do have the exact same name in both cases, so what mechanism decides when exactly to use (or not use) override.mock.properties functions?
If this is intended behaviour in some way, please update the documentation to describe how exactly this decision is made per property, and how to write it in such a way that it always picks up these properties. Otherwise, it would be a bug that needs fixing.
I'm still using Orval 7.11.2 (because of #2464) on Node.js 22.20.0.
Also note how 50% of the properties in a generated array are allowed to be undefined, despite the spec clearly stating they are required. Why is that?
This is partially fixed by adding override.mock.required = true but that requires ALL properties, not just the actually required ones. And then there still an optional property (firstName) that is never allowed to be undefined when a override.mock.properties exists for it.
Do you need a separate issue # for this?