Skip to content

Commit b471586

Browse files
committed
add faker argument validation for large numbers and add sample function call display
1 parent df49911 commit b471586

File tree

3 files changed

+48
-95
lines changed

3 files changed

+48
-95
lines changed

packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.tsx

Lines changed: 24 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import {
22
Banner,
33
BannerVariant,
44
Body,
5+
Code,
56
css,
7+
Label,
68
Option,
79
palette,
810
Select,
911
spacing,
10-
TextInput,
1112
} from '@mongodb-js/compass-components';
1213
import React from 'react';
1314
import { UNRECOGNIZED_FAKER_METHOD } from '../../modules/collection-tab';
@@ -26,92 +27,11 @@ const labelStyles = css({
2627
fontWeight: 600,
2728
});
2829

29-
/**
30-
* Renders read-only TextInput components for each key-value pair in a faker arguments object.
31-
*/
32-
const getFakerArgsInputFromObject = (fakerArgsObject: Record<string, any>) => {
33-
return Object.entries(fakerArgsObject).map(([key, item]: [string, any]) => {
34-
if (typeof item === 'string' || typeof item === 'boolean') {
35-
return (
36-
<TextInput
37-
key={`faker-arg-${key}`}
38-
type="text"
39-
label={key}
40-
aria-label={`Faker Arg ${key}`}
41-
readOnly
42-
value={item.toString()}
43-
/>
44-
);
45-
} else if (typeof item === 'number') {
46-
return (
47-
<TextInput
48-
key={`faker-arg-${key}`}
49-
type="number"
50-
label={key}
51-
aria-label={`Faker Arg ${key}`}
52-
readOnly
53-
value={item.toString()}
54-
/>
55-
);
56-
} else if (
57-
Array.isArray(item) &&
58-
item.length > 0 &&
59-
typeof item[0] === 'string'
60-
) {
61-
return (
62-
<TextInput
63-
key={`faker-arg-${key}`}
64-
type="text"
65-
label={key}
66-
aria-label={`Faker Arg ${key}`}
67-
readOnly
68-
value={item.join(', ')}
69-
/>
70-
);
71-
}
72-
return null;
73-
});
74-
};
75-
76-
/**
77-
* Renders TextInput components for each faker argument based on its type.
78-
*/
79-
const getFakerArgsInput = (fakerArgs: FakerArg[]) => {
80-
return fakerArgs.map((arg, idx) => {
81-
if (typeof arg === 'string' || typeof arg === 'boolean') {
82-
return (
83-
<TextInput
84-
key={`faker-arg-${idx}`}
85-
type="text"
86-
label="Faker Arg"
87-
readOnly
88-
value={arg.toString()}
89-
/>
90-
);
91-
} else if (typeof arg === 'number') {
92-
return (
93-
<TextInput
94-
key={`faker-arg-${idx}`}
95-
type="number"
96-
label="Faker Arg"
97-
readOnly
98-
value={arg.toString()}
99-
/>
100-
);
101-
} else if (typeof arg === 'object' && 'json' in arg) {
102-
// parse the object
103-
let parsedArg;
104-
try {
105-
parsedArg = JSON.parse(arg.json);
106-
} catch {
107-
// If parsing fails, skip rendering this arg
108-
return null;
109-
}
110-
if (typeof parsedArg === 'object') {
111-
return getFakerArgsInputFromObject(parsedArg);
112-
}
113-
}
114-
});
30+
const formatFakerFunctionCallWithArgs = (
31+
fakerFunction: string,
32+
fakerArgs: FakerArg[]
33+
) => {
34+
return `faker.${fakerFunction}(${fakerArgs.join(', ')})`;
11535
};
11636

11737
interface Props {
@@ -158,13 +78,28 @@ const FakerMappingSelector = ({
15878
</Option>
15979
))}
16080
</Select>
161-
{activeFakerFunction === UNRECOGNIZED_FAKER_METHOD && (
81+
{activeFakerFunction === UNRECOGNIZED_FAKER_METHOD ? (
16282
<Banner variant={BannerVariant.Warning}>
16383
Please select a function or we will default fill this field with the
16484
string &quot;Unrecognized&quot;
16585
</Banner>
86+
) : (
87+
<>
88+
<Label htmlFor="sample-faker-function-call">
89+
Sample Faker Function Call
90+
</Label>
91+
<Code
92+
id="sample-faker-function-call"
93+
language="javascript"
94+
copyable={false}
95+
>
96+
{formatFakerFunctionCallWithArgs(
97+
activeFakerFunction,
98+
activeFakerArgs
99+
)}
100+
</Code>
101+
</>
166102
)}
167-
{getFakerArgsInput(activeFakerArgs)}
168103
</div>
169104
);
170105
};

packages/compass-collection/src/components/mock-data-generator-modal/utils.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ describe('Mock Data Generator Utils', () => {
3737
expect(areFakerArgsValid([longStr])).to.be.false;
3838
});
3939

40+
it('returns false for numbers that are too large', () => {
41+
expect(areFakerArgsValid([1001])).to.be.false;
42+
expect(areFakerArgsValid([-1001])).to.be.false;
43+
expect(areFakerArgsValid([{ json: { length: 1001 } } as any])).to.be
44+
.false;
45+
expect(areFakerArgsValid([{ json: { length: -1001 } } as any])).to.be
46+
.false;
47+
expect(
48+
areFakerArgsValid([{ json: { width: 1001, height: 1001 } } as any])
49+
).to.be.false;
50+
});
51+
4052
it('returns true for nested valid arrays', () => {
4153
expect(
4254
areFakerArgsValid([

packages/compass-collection/src/components/mock-data-generator-modal/utils.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { faker } from '@faker-js/faker/locale/en';
55
const MAX_FAKER_ARGS_LENGTH = 10;
66
const MAX_FAKER_STRING_LENGTH = 1000;
77
const MAX_FAKER_ARGS_DEPTH = 3;
8+
const MAX_FAKER_NUMBER_SIZE = 1000;
89

910
/**
1011
* Checks if the provided faker arguments are valid.
@@ -30,23 +31,28 @@ export function areFakerArgsValid(
3031
if (arg === null || arg === undefined) {
3132
return false;
3233
}
33-
if (typeof arg === 'number') {
34-
if (!Number.isFinite(arg)) {
34+
if (typeof arg === 'boolean') {
35+
// booleans are always valid, continue
36+
continue;
37+
} else if (typeof arg === 'number') {
38+
if (!Number.isFinite(arg) || Math.abs(arg) > MAX_FAKER_NUMBER_SIZE) {
3539
return false;
3640
}
3741
} else if (typeof arg === 'string') {
3842
if (arg.length > MAX_FAKER_STRING_LENGTH) {
3943
return false;
4044
}
41-
} else if (typeof arg === 'boolean') {
42-
// booleans are always valid, continue
4345
} else if (Array.isArray(arg)) {
4446
if (!areFakerArgsValid(arg, depth + 1)) {
4547
return false;
4648
}
47-
} else if (typeof arg === 'object' && typeof arg.json === 'string') {
49+
} else if (
50+
typeof arg === 'object' &&
51+
arg !== null &&
52+
typeof (arg as { json?: unknown }).json === 'string'
53+
) {
4854
try {
49-
const parsedJson = JSON.parse(arg.json);
55+
const parsedJson = JSON.parse((arg as { json: string }).json);
5056
if (!areFakerArgsValid(Object.values(parsedJson), depth + 1)) {
5157
return false;
5258
}

0 commit comments

Comments
 (0)