Skip to content

Commit 64d47de

Browse files
committed
generate documents with faker for PreviewScreen
1 parent 2d6038e commit 64d47de

File tree

5 files changed

+304
-68
lines changed

5 files changed

+304
-68
lines changed

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@ import {
1313
spacing,
1414
} from '@mongodb-js/compass-components';
1515

16-
import {
17-
type MockDataGeneratorState,
18-
MockDataGeneratorStep,
19-
ValidatedFakerSchemaMapping,
20-
} from './types';
16+
import type { ValidatedFakerSchemaMapping } from './types';
17+
import { type MockDataGeneratorState, MockDataGeneratorStep } from './types';
2118
import { StepButtonLabelMap } from './constants';
2219
import type { CollectionState } from '../../modules/collection-tab';
2320
import {
@@ -91,12 +88,15 @@ const MockDataGeneratorModal = ({
9188
// function validateFakerSchema(input: FakerSchemaMapping): asserts input is ValidatedFakerSchemaMapping {
9289
// ...
9390
// }
94-
const confirmedFakerSchema = (
95-
fakerSchemaGenerationState.status === 'completed'
96-
? fakerSchemaGenerationState.fakerSchema
97-
: []
98-
) as ValidatedFakerSchemaMapping[];
99-
return <PreviewScreen confirmedFakerSchema={confirmedFakerSchema} />;
91+
return (
92+
<PreviewScreen
93+
confirmedFakerSchema={
94+
(fakerSchemaGenerationState.status === 'completed'
95+
? fakerSchemaGenerationState.fakerSchema
96+
: []) as ValidatedFakerSchemaMapping[]
97+
}
98+
/>
99+
);
100100
case MockDataGeneratorStep.GENERATE_DATA:
101101
return <ScriptScreen />;
102102
}

packages/compass-collection/src/components/mock-data-generator-modal/preview-screen.tsx

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,12 @@
11
import React, { useMemo } from 'react';
22
import { css, spacing, Body, Code } from '@mongodb-js/compass-components';
33
import type { ValidatedFakerSchemaMapping } from './types';
4-
import { faker } from '@faker-js/faker/locale/en';
5-
import { FIELD_NAME_SEPARATOR } from '../../transform-schema-to-field-info';
4+
import { generateDocument } from './script-generation-utils';
65

76
const descriptionStyles = css({
87
marginBottom: spacing[200],
98
});
109

11-
const UNRECOGNIZED_FAKER_METHOD = 'Unrecognized';
12-
13-
// TODO(CLOUDP-333857): borrow from `script-generation-utils` to convert to a nested document structure (and especially handle [] markers)
14-
function createDocumentFactory(fakerSchema: ValidatedFakerSchemaMapping[]) {
15-
return () => {
16-
const flatDocument: Record<string, string | number | boolean | null> = {};
17-
18-
for (const field of fakerSchema) {
19-
const { fieldPath, fakerMethod, fakerArgs } = field;
20-
21-
if (fakerMethod === UNRECOGNIZED_FAKER_METHOD) {
22-
flatDocument[fieldPath] = null;
23-
continue;
24-
}
25-
26-
try {
27-
// e.g., "person.firstName" -> ["person", "firstName"])
28-
const [moduleName, methodName] = fakerMethod.split('.');
29-
30-
// This check should not fail if fakerSchema is validated properly
31-
if (typeof (faker as any)[moduleName]?.[methodName] !== 'function') {
32-
flatDocument[fieldPath] = null;
33-
continue;
34-
}
35-
36-
// Process faker arguments
37-
const processedArgs = fakerArgs.map((arg) => {
38-
if (typeof arg === 'object' && arg !== null && 'json' in arg) {
39-
try {
40-
return JSON.parse(arg.json);
41-
} catch {
42-
return arg.json;
43-
}
44-
}
45-
return arg;
46-
});
47-
48-
// Call the faker method with processed arguments
49-
const fakerModule = (faker as any)[moduleName];
50-
flatDocument[fieldPath] = fakerModule[methodName](...processedArgs);
51-
} catch (error) {
52-
// If there's any error generating the value, set it to null
53-
flatDocument[fieldPath] = null;
54-
}
55-
}
56-
57-
return flatDocument;
58-
};
59-
}
60-
6110
interface PreviewScreenProps {
6211
confirmedFakerSchema: ValidatedFakerSchemaMapping[];
6312
}
@@ -66,11 +15,9 @@ const NUM_SAMPLE_DOCUMENTS = 5;
6615

6716
function PreviewScreen({ confirmedFakerSchema }: PreviewScreenProps) {
6817
const sampleDocuments = useMemo(() => {
69-
const documentFactory = createDocumentFactory(confirmedFakerSchema);
70-
7118
const documents = [];
7219
for (let i = 0; i < NUM_SAMPLE_DOCUMENTS; i++) {
73-
documents.push(documentFactory());
20+
documents.push(generateDocument(confirmedFakerSchema));
7421
}
7522

7623
return documents;

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

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import { expect } from 'chai';
22
import { faker } from '@faker-js/faker/locale/en';
33
import {
44
generateScript,
5+
generateDocument,
56
type FakerFieldMapping,
67
} from './script-generation-utils';
8+
import type { ValidatedFakerSchemaMapping } from './types';
79

810
/**
911
* Helper function to test that generated document code is executable
@@ -1255,4 +1257,135 @@ describe('Script Generation', () => {
12551257
}
12561258
});
12571259
});
1260+
1261+
describe('generateDocument', () => {
1262+
const createValidatedSchemaMapping = (
1263+
fieldPath: string,
1264+
fakerMethod: string,
1265+
mongoType: string = 'String',
1266+
fakerArgs: any[] = []
1267+
) =>
1268+
({
1269+
fieldPath,
1270+
fakerMethod,
1271+
mongoType,
1272+
fakerArgs,
1273+
} as ValidatedFakerSchemaMapping);
1274+
1275+
it('should generate document with simple flat fields of mixed types', () => {
1276+
const schema: ValidatedFakerSchemaMapping[] = [
1277+
createValidatedSchemaMapping('name', 'person.fullName'),
1278+
createValidatedSchemaMapping('age', 'number.int', 'Number'),
1279+
createValidatedSchemaMapping('isActive', 'datatype.boolean', 'Boolean'),
1280+
createValidatedSchemaMapping('createdAt', 'date.recent', 'Date'),
1281+
createValidatedSchemaMapping(
1282+
'_id',
1283+
'database.mongodbObjectId',
1284+
'ObjectId'
1285+
),
1286+
];
1287+
1288+
const document = generateDocument(schema);
1289+
1290+
expect(document).to.be.an('object');
1291+
expect(document).to.have.property('name');
1292+
expect(document.name).to.be.a('string').and.not.be.empty;
1293+
expect(document).to.have.property('age');
1294+
expect(document.age).to.be.a('number');
1295+
expect(document).to.have.property('isActive');
1296+
expect(document.isActive).to.be.a('boolean');
1297+
expect(document).to.have.property('createdAt');
1298+
expect(document.createdAt).to.be.a('date');
1299+
expect(document).to.have.property('_id');
1300+
expect(document._id).to.be.a('string');
1301+
});
1302+
1303+
it('should generate document with multi-dimensional arrays of mixed types', () => {
1304+
const schema: ValidatedFakerSchemaMapping[] = [
1305+
createValidatedSchemaMapping(
1306+
'numberMatrix[][]',
1307+
'number.int',
1308+
'Number'
1309+
),
1310+
createValidatedSchemaMapping('stringMatrix[][]', 'lorem.word'),
1311+
createValidatedSchemaMapping(
1312+
'booleanGrid[][]',
1313+
'datatype.boolean',
1314+
'Boolean'
1315+
),
1316+
];
1317+
1318+
const arrayLengthMap = {
1319+
numberMatrix: [2, 3],
1320+
stringMatrix: [2, 2],
1321+
booleanGrid: [3, 2],
1322+
};
1323+
1324+
const document = generateDocument(schema, arrayLengthMap);
1325+
1326+
expect(document).to.be.an('object');
1327+
expect(document).to.have.property('numberMatrix');
1328+
expect(document.numberMatrix).to.be.an('array').with.length(2);
1329+
expect(document.numberMatrix[0]).to.be.an('array').with.length(3);
1330+
expect(document.numberMatrix[0][0]).to.be.a('number');
1331+
1332+
expect(document).to.have.property('stringMatrix');
1333+
expect(document.stringMatrix).to.be.an('array').with.length(2);
1334+
expect(document.stringMatrix[0]).to.be.an('array').with.length(2);
1335+
expect(document.stringMatrix[0][0]).to.be.a('string').and.not.be.empty;
1336+
1337+
expect(document).to.have.property('booleanGrid');
1338+
expect(document.booleanGrid).to.be.an('array').with.length(3);
1339+
expect(document.booleanGrid[0]).to.be.an('array').with.length(2);
1340+
expect(document.booleanGrid[0][0]).to.be.a('boolean');
1341+
});
1342+
1343+
it('should handle complex nested structures with arrays and objects', () => {
1344+
const schema: ValidatedFakerSchemaMapping[] = [
1345+
createValidatedSchemaMapping('company.name', 'company.name'),
1346+
createValidatedSchemaMapping(
1347+
'company.employees[].name',
1348+
'person.fullName'
1349+
),
1350+
createValidatedSchemaMapping(
1351+
'company.employees[].email',
1352+
'internet.email'
1353+
),
1354+
createValidatedSchemaMapping(
1355+
'company.employees[].skills[]',
1356+
'lorem.word'
1357+
),
1358+
createValidatedSchemaMapping('company.founded', 'date.past', 'Date'),
1359+
createValidatedSchemaMapping(
1360+
'company.isActive',
1361+
'datatype.boolean',
1362+
'Boolean'
1363+
),
1364+
];
1365+
1366+
const document = generateDocument(schema);
1367+
1368+
expect(document).to.be.an('object');
1369+
expect(document).to.have.property('company');
1370+
expect(document.company).to.be.an('object');
1371+
expect(document.company).to.have.property('name');
1372+
expect(document.company.name).to.be.a('string').and.not.be.empty;
1373+
expect(document.company).to.have.property('founded');
1374+
expect(document.company.founded).to.be.a('date');
1375+
expect(document.company).to.have.property('isActive');
1376+
expect(document.company.isActive).to.be.a('boolean');
1377+
expect(document.company).to.have.property('employees');
1378+
expect(document.company.employees).to.be.an('array').with.length(3);
1379+
1380+
const firstEmployee = document.company.employees[0];
1381+
expect(firstEmployee).to.be.an('object');
1382+
expect(firstEmployee).to.have.property('name');
1383+
expect(firstEmployee.name).to.be.a('string').and.not.be.empty;
1384+
expect(firstEmployee).to.have.property('email');
1385+
expect(firstEmployee.email).to.be.a('string').and.include('@');
1386+
expect(firstEmployee).to.have.property('skills');
1387+
expect(firstEmployee.skills).to.be.an('array').with.length(3);
1388+
expect(firstEmployee.skills[0]).to.be.a('string').and.not.be.empty;
1389+
});
1390+
});
12581391
});

0 commit comments

Comments
 (0)