Skip to content

Commit d919f9f

Browse files
feat: allow defining min and max ranges for mocked numbers and strings (#2150)
* feat: allow defining min and max ranges for mocked numbers and strings * Add same defaults also for bigInts * Fix tests since int64 format should only work with integer type
1 parent 72c21ca commit d919f9f

File tree

20 files changed

+361
-105
lines changed

20 files changed

+361
-105
lines changed

docs/src/pages/reference/configuration/output.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,6 +1666,86 @@ module.exports = {
16661666
};
16671667
```
16681668

1669+
##### stringMin
1670+
1671+
Type: `Number`.
1672+
1673+
Set the default minimum length of generated strings. Used if `minLength` is not defined for the property. (Default is `10`)
1674+
1675+
```js
1676+
module.exports = {
1677+
petstore: {
1678+
output: {
1679+
override: {
1680+
mock: {
1681+
stringMin: 5,
1682+
},
1683+
},
1684+
},
1685+
},
1686+
};
1687+
```
1688+
1689+
##### stringMax
1690+
1691+
Type: `Number`.
1692+
1693+
Set the default maximum length of generated strings. Used if `maxLength` is not defined for the property. (Default is `20`)
1694+
1695+
```js
1696+
module.exports = {
1697+
petstore: {
1698+
output: {
1699+
override: {
1700+
mock: {
1701+
stringMax: 15,
1702+
},
1703+
},
1704+
},
1705+
},
1706+
};
1707+
```
1708+
1709+
##### numberMin
1710+
1711+
Type: `Number`.
1712+
1713+
Set the default minimum value of generated numbers. Used if `minimum` is not defined for the property.
1714+
1715+
```js
1716+
module.exports = {
1717+
petstore: {
1718+
output: {
1719+
override: {
1720+
mock: {
1721+
numberMin: 5,
1722+
},
1723+
},
1724+
},
1725+
},
1726+
};
1727+
```
1728+
1729+
##### numberMax
1730+
1731+
Type: `Number`.
1732+
1733+
Set the default maximum value of generated numbers. Used if `maximum` is not defined for the property.
1734+
1735+
```js
1736+
module.exports = {
1737+
petstore: {
1738+
output: {
1739+
override: {
1740+
mock: {
1741+
numberMax: 15,
1742+
},
1743+
},
1744+
},
1745+
},
1746+
};
1747+
```
1748+
16691749
##### fractionDigits
16701750

16711751
Type: `Number`.

packages/core/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,10 @@ export type GlobalMockOptions = {
326326
export type OverrideMockOptions = Partial<GlobalMockOptions> & {
327327
arrayMin?: number;
328328
arrayMax?: number;
329+
stringMin?: number;
330+
stringMax?: number;
331+
numberMin?: number;
332+
numberMax?: number;
329333
required?: boolean;
330334
properties?: MockProperties;
331335
format?: Record<string, unknown>;

packages/mock/src/faker/getters/scalar.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { describe, it, expect } from 'vitest';
22
import { getMockScalar } from './scalar';
33
import type { ContextSpecs } from '@orval/core';
4+
import type { SchemaObjectType } from 'openapi3-ts/oas30';
45

56
describe('getMockScalar (int64 format handling)', () => {
67
const baseArg = {
78
item: {
9+
type: 'integer' as SchemaObjectType,
810
format: 'int64',
911
minimum: 1,
1012
maximum: 100,

packages/mock/src/faker/getters/scalar.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,6 @@ export const getMockScalar = ({
119119
};
120120
}
121121

122-
if (item.format && item.format === 'int64') {
123-
const value = context.output.override.useBigInt
124-
? `faker.number.bigInt({min: ${item.minimum}, max: ${item.maximum}})`
125-
: `faker.number.int({min: ${item.minimum}, max: ${item.maximum}})`;
126-
127-
return {
128-
value: getNullable(value, item.nullable),
129-
imports: [],
130-
name: item.name,
131-
overrided: false,
132-
};
133-
}
134-
135122
const type = getItemType(item);
136123
const isFakerV9 =
137124
!!context.output.packageJson &&
@@ -140,13 +127,17 @@ export const getMockScalar = ({
140127
switch (type) {
141128
case 'number':
142129
case 'integer': {
130+
const intFunction =
131+
item.format === 'int64' && context.output.override.useBigInt
132+
? 'bigInt'
133+
: 'int';
143134
let value = getNullable(
144-
`faker.number.int({min: ${item.minimum}, max: ${item.maximum}${isFakerV9 ? `, multipleOf: ${item.multipleOf}` : ''}})`,
135+
`faker.number.${intFunction}({min: ${item.minimum ?? mockOptions?.numberMin}, max: ${item.maximum ?? mockOptions?.numberMax}${isFakerV9 ? `, multipleOf: ${item.multipleOf}` : ''}})`,
145136
item.nullable,
146137
);
147138
if (type === 'number') {
148139
value = getNullable(
149-
`faker.number.float({min: ${item.minimum}, max: ${item.maximum ?? 999999999}, ${item.multipleOf ? `multipleOf: ${item.multipleOf}` : `fractionDigits: ${mockOptions?.fractionDigits}`}})`,
140+
`faker.number.float({min: ${item.minimum ?? mockOptions?.numberMin}, max: ${item.maximum ?? mockOptions?.numberMax}, ${item.multipleOf ? `multipleOf: ${item.multipleOf}` : `fractionDigits: ${mockOptions?.fractionDigits}`}})`,
150141
item.nullable,
151142
);
152143
}
@@ -244,10 +235,7 @@ export const getMockScalar = ({
244235
}
245236

246237
case 'string': {
247-
const length =
248-
item.minLength !== undefined || item.maxLength !== undefined
249-
? `{length: {min: ${item.minLength ?? 0}, max: ${item.maxLength ?? (item.minLength ?? 0) + 20}}}`
250-
: 20;
238+
const length = `{length: {min: ${item.minLength ?? mockOptions?.stringMin}, max: ${item.maxLength ?? mockOptions?.stringMax}}}`;
251239
let value = `faker.string.alpha(${length})`;
252240
const stringImports: GeneratorImport[] = [];
253241

packages/mock/src/msw/mocks.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ const getMockWithoutFunc = (
3434
): MockOptions => ({
3535
arrayMin: override?.mock?.arrayMin,
3636
arrayMax: override?.mock?.arrayMax,
37+
stringMin: override?.mock?.stringMin,
38+
stringMax: override?.mock?.stringMax,
39+
numberMin: override?.mock?.numberMin,
40+
numberMax: override?.mock?.numberMax,
3741
required: override?.mock?.required,
3842
fractionDigits: override?.mock?.fractionDigits,
3943
...(override?.mock?.properties

packages/orval/src/utils/options.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ export const normalizeOptions = async (
207207
mock: {
208208
arrayMin: outputOptions.override?.mock?.arrayMin ?? 1,
209209
arrayMax: outputOptions.override?.mock?.arrayMax ?? 10,
210+
stringMin: outputOptions.override?.mock?.stringMin ?? 10,
211+
stringMax: outputOptions.override?.mock?.stringMax ?? 20,
210212
fractionDigits: outputOptions.override?.mock?.fractionDigits ?? 2,
211213
...outputOptions.override?.mock,
212214
},

samples/angular-app/src/api/endpoints/pets/pets.msw.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ export const getListPetsResponseMock = (): Pets =>
1515
{ length: faker.number.int({ min: 1, max: 10 }) },
1616
(_, i) => i + 1,
1717
).map(() => ({
18-
id: faker.number.int({ min: undefined, max: undefined }),
18+
id: faker.number.int({
19+
min: undefined,
20+
max: undefined,
21+
multipleOf: undefined,
22+
}),
1923
name: (() => faker.person.lastName())(),
2024
tag: (() => faker.person.lastName())(),
2125
}));

samples/basic/api/endpoints/petstoreFromFileSpecWithTransformer.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ export const getListPetsResponseMock = (): PetsArray =>
8181
{ length: faker.number.int({ min: 1, max: 20 }) },
8282
(_, i) => i + 1,
8383
).map(() => ({
84-
id: faker.number.int({ min: undefined, max: undefined }),
84+
id: faker.number.int({
85+
min: undefined,
86+
max: undefined,
87+
multipleOf: undefined,
88+
}),
8589
name: 'jon',
8690
age: faker.helpers.arrayElement([
8791
faker.number.int({ min: 0, max: 30, multipleOf: undefined }),
@@ -110,7 +114,11 @@ export const getListPetsNestedArrayResponseMock = (
110114
{ length: faker.number.int({ min: 1, max: 10 }) },
111115
(_, i) => i + 1,
112116
).map(() => ({
113-
id: faker.number.int({ min: undefined, max: undefined }),
117+
id: faker.number.int({
118+
min: undefined,
119+
max: undefined,
120+
multipleOf: undefined,
121+
}),
114122
name: 'jon',
115123
age: faker.helpers.arrayElement([
116124
faker.number.int({ min: 0, max: 30, multipleOf: undefined }),

samples/hono/hono-with-fetch-client/next-app/app/gen/pets/pets.msw.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,34 @@ export const getListPetsResponseMock = (): Pets =>
1616
(_, i) => i + 1,
1717
).map(() => ({
1818
id: faker.number.int({ min: undefined, max: undefined }),
19-
name: faker.string.alpha(20),
20-
tag: faker.string.alpha(20),
19+
name: faker.string.alpha({ length: { min: 10, max: 20 } }),
20+
tag: faker.string.alpha({ length: { min: 10, max: 20 } }),
2121
}));
2222

2323
export const getCreatePetsResponseMock = (
2424
overrideResponse: Partial<Pet> = {},
2525
): Pet => ({
2626
id: faker.number.int({ min: undefined, max: undefined }),
27-
name: faker.string.alpha(20),
28-
tag: faker.string.alpha(20),
27+
name: faker.string.alpha({ length: { min: 10, max: 20 } }),
28+
tag: faker.string.alpha({ length: { min: 10, max: 20 } }),
2929
...overrideResponse,
3030
});
3131

3232
export const getUpdatePetsResponseMock = (
3333
overrideResponse: Partial<Pet> = {},
3434
): Pet => ({
3535
id: faker.number.int({ min: undefined, max: undefined }),
36-
name: faker.string.alpha(20),
37-
tag: faker.string.alpha(20),
36+
name: faker.string.alpha({ length: { min: 10, max: 20 } }),
37+
tag: faker.string.alpha({ length: { min: 10, max: 20 } }),
3838
...overrideResponse,
3939
});
4040

4141
export const getShowPetByIdResponseMock = (
4242
overrideResponse: Partial<Pet> = {},
4343
): Pet => ({
4444
id: faker.number.int({ min: undefined, max: undefined }),
45-
name: faker.string.alpha(20),
46-
tag: faker.string.alpha(20),
45+
name: faker.string.alpha({ length: { min: 10, max: 20 } }),
46+
tag: faker.string.alpha({ length: { min: 10, max: 20 } }),
4747
...overrideResponse,
4848
});
4949

samples/next-app-with-fetch/app/gen/pets/pets.msw.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,16 @@ export const getListPetsResponseMock = (): Pets =>
6969
{ ...getListPetsResponseDogMock() },
7070
{ ...getListPetsResponseCatMock() },
7171
]),
72-
'@id': faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
72+
'@id': faker.helpers.arrayElement([
73+
faker.string.alpha({ length: { min: 10, max: 20 } }),
74+
undefined,
75+
]),
7376
id: faker.number.int({ min: undefined, max: undefined }),
74-
name: faker.string.alpha(20),
75-
tag: faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
77+
name: faker.string.alpha({ length: { min: 10, max: 20 } }),
78+
tag: faker.helpers.arrayElement([
79+
faker.string.alpha({ length: { min: 10, max: 20 } }),
80+
undefined,
81+
]),
7682
email: faker.helpers.arrayElement([faker.internet.email(), undefined]),
7783
callingCode: faker.helpers.arrayElement([
7884
faker.helpers.arrayElement(['+33', '+420', '+33'] as const),
@@ -142,10 +148,16 @@ export const getCreatePetsResponseMock = (): Pet => ({
142148
{ ...getCreatePetsResponseDogMock() },
143149
{ ...getCreatePetsResponseCatMock() },
144150
]),
145-
'@id': faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
151+
'@id': faker.helpers.arrayElement([
152+
faker.string.alpha({ length: { min: 10, max: 20 } }),
153+
undefined,
154+
]),
146155
id: faker.number.int({ min: undefined, max: undefined }),
147-
name: faker.string.alpha(20),
148-
tag: faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
156+
name: faker.string.alpha({ length: { min: 10, max: 20 } }),
157+
tag: faker.helpers.arrayElement([
158+
faker.string.alpha({ length: { min: 10, max: 20 } }),
159+
undefined,
160+
]),
149161
email: faker.helpers.arrayElement([faker.internet.email(), undefined]),
150162
callingCode: faker.helpers.arrayElement([
151163
faker.helpers.arrayElement(['+33', '+420', '+33'] as const),
@@ -215,10 +227,16 @@ export const getUpdatePetsResponseMock = (): Pet => ({
215227
{ ...getUpdatePetsResponseDogMock() },
216228
{ ...getUpdatePetsResponseCatMock() },
217229
]),
218-
'@id': faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
230+
'@id': faker.helpers.arrayElement([
231+
faker.string.alpha({ length: { min: 10, max: 20 } }),
232+
undefined,
233+
]),
219234
id: faker.number.int({ min: undefined, max: undefined }),
220-
name: faker.string.alpha(20),
221-
tag: faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
235+
name: faker.string.alpha({ length: { min: 10, max: 20 } }),
236+
tag: faker.helpers.arrayElement([
237+
faker.string.alpha({ length: { min: 10, max: 20 } }),
238+
undefined,
239+
]),
222240
email: faker.helpers.arrayElement([faker.internet.email(), undefined]),
223241
callingCode: faker.helpers.arrayElement([
224242
faker.helpers.arrayElement(['+33', '+420', '+33'] as const),
@@ -288,10 +306,16 @@ export const getShowPetByIdResponseMock = (): Pet => ({
288306
{ ...getShowPetByIdResponseDogMock() },
289307
{ ...getShowPetByIdResponseCatMock() },
290308
]),
291-
'@id': faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
309+
'@id': faker.helpers.arrayElement([
310+
faker.string.alpha({ length: { min: 10, max: 20 } }),
311+
undefined,
312+
]),
292313
id: faker.number.int({ min: undefined, max: undefined }),
293-
name: faker.string.alpha(20),
294-
tag: faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
314+
name: faker.string.alpha({ length: { min: 10, max: 20 } }),
315+
tag: faker.helpers.arrayElement([
316+
faker.string.alpha({ length: { min: 10, max: 20 } }),
317+
undefined,
318+
]),
295319
email: faker.helpers.arrayElement([faker.internet.email(), undefined]),
296320
callingCode: faker.helpers.arrayElement([
297321
faker.helpers.arrayElement(['+33', '+420', '+33'] as const),

0 commit comments

Comments
 (0)