Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import RawSchemaConfirmationScreen from './raw-schema-confirmation-screen';
import FakerSchemaEditorScreen from './faker-schema-editor-screen';
import ScriptScreen from './script-screen';
import DocumentCountScreen from './document-count-screen';
import PreviewScreen from './preview-screen';

const footerStyles = css`
flex-direction: row;
Expand Down Expand Up @@ -95,7 +96,15 @@ const MockDataGeneratorModal = ({
/>
);
case MockDataGeneratorStep.PREVIEW_DATA:
return <></>; // TODO: CLOUDP-333857
return (
<PreviewScreen
confirmedFakerSchema={
fakerSchemaGenerationState.status === 'completed'
? fakerSchemaGenerationState.fakerSchema
: {}
}
/>
);
case MockDataGeneratorStep.GENERATE_DATA:
return <ScriptScreen />;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { useMemo } from 'react';
import { css, spacing, Body, Code } from '@mongodb-js/compass-components';
import { EJSON } from 'bson';
import type { FakerSchema } from './types';
import { generateDocument } from './script-generation-utils';

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

interface PreviewScreenProps {
confirmedFakerSchema: FakerSchema;
}

const NUM_SAMPLE_DOCUMENTS = 3;

function PreviewScreen({ confirmedFakerSchema }: PreviewScreenProps) {
const sampleDocuments = useMemo(() => {
const documents = [];
for (let i = 0; i < NUM_SAMPLE_DOCUMENTS; i++) {
documents.push(generateDocument(confirmedFakerSchema));
}

return documents;
}, [confirmedFakerSchema]);

return (
<div data-testid="preview-screen">
<Body as="h2" baseFontSize={16} weight="medium">
Preview Mock Data
</Body>
<Body className={descriptionStyles}>
Below is a sample of documents that will be generated based on your
script
</Body>
<Code language="javascript" copyable={false}>
{EJSON.stringify(sampleDocuments, undefined, 2)}
</Code>
</div>
);
}

export default PreviewScreen;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'chai';
import { faker } from '@faker-js/faker/locale/en';
import { generateScript } from './script-generation-utils';
import { generateScript, generateDocument } from './script-generation-utils';
import type { FakerFieldMapping } from './types';

/**
Expand Down Expand Up @@ -1421,4 +1421,151 @@ describe('Script Generation', () => {
}
});
});

describe('generateDocument', () => {
it('should generate document with simple flat fields', () => {
const schema = {
name: {
mongoType: 'String' as const,
fakerMethod: 'person.fullName',
fakerArgs: [],
probability: 1.0,
},
age: {
mongoType: 'Number' as const,
fakerMethod: 'number.int',
fakerArgs: [{ json: '{"min": 18, "max": 65}' }],
probability: 1.0,
},
};

const document = generateDocument(schema);

expect(document).to.be.an('object');
expect(document).to.have.property('name');
expect(document.name).to.be.a('string').and.not.be.empty;
expect(document).to.have.property('age');
expect(document.age).to.be.a('number');
expect(document.age).to.be.at.least(18).and.at.most(65);
});

it('should generate document with arrays', () => {
const schema = {
'tags[]': {
mongoType: 'String' as const,
fakerMethod: 'lorem.word',
fakerArgs: [],
probability: 1.0,
},
};

const document = generateDocument(schema, { 'tags[]': 2 });

expect(document).to.be.an('object');
expect(document).to.have.property('tags');
expect(document.tags).to.be.an('array').with.length(2);
for (const tag of document.tags as string[]) {
expect(tag).to.be.a('string').and.not.be.empty;
}
});

it('should generate document with complex nested arrays and custom lengths', () => {
const schema = {
'users[].posts[].tags[]': {
mongoType: 'String' as const,
fakerMethod: 'lorem.word',
fakerArgs: [],
probability: 1.0,
},
'matrix[][]': {
mongoType: 'Number' as const,
fakerMethod: 'number.int',
fakerArgs: [{ json: '{"min": 1, "max": 10}' }],
probability: 1.0,
},
};

const arrayLengthMap = {
'users[]': 2,
'users[].posts[]': 3,
'users[].posts[].tags[]': 4,
'matrix[]': 2,
'matrix[][]': 3,
};

const document = generateDocument(schema, arrayLengthMap);

expect(document).to.be.an('object');

// Check users array structure
expect(document).to.have.property('users');
expect(document.users).to.be.an('array').with.length(2);

// Check nested structure with proper types
const users = document.users as Array<{
posts: Array<{ tags: string[] }>;
}>;

for (const user of users) {
expect(user).to.be.an('object');
expect(user).to.have.property('posts');
expect(user.posts).to.be.an('array').with.length(3);

for (const post of user.posts) {
expect(post).to.be.an('object');
expect(post).to.have.property('tags');
expect(post.tags).to.be.an('array').with.length(4);

for (const tag of post.tags) {
expect(tag).to.be.a('string').and.not.be.empty;
}
}
}

// Check matrix (2D array)
expect(document).to.have.property('matrix');
expect(document.matrix).to.be.an('array').with.length(2);

const matrix = document.matrix as number[][];
for (const row of matrix) {
expect(row).to.be.an('array').with.length(3);
for (const cell of row) {
expect(cell).to.be.a('number').and.be.at.least(1).and.at.most(10);
}
}
});

it('should handle probability fields correctly', () => {
const schema = {
name: {
mongoType: 'String' as const,
fakerMethod: 'person.fullName',
fakerArgs: [],
probability: 1.0,
},
optionalField: {
mongoType: 'String' as const,
fakerMethod: 'lorem.word',
fakerArgs: [],
probability: 0.0, // Should never appear
},
alwaysPresent: {
mongoType: 'Number' as const,
fakerMethod: 'number.int',
fakerArgs: [],
probability: 1.0,
},
};

const document = generateDocument(schema);

expect(document).to.be.an('object');
expect(document).to.have.property('name');
expect(document.name).to.be.a('string').and.not.be.empty;
expect(document).to.have.property('alwaysPresent');
expect(document.alwaysPresent).to.be.a('number');
// optionalField should not be present due to 0.0 probability
expect(document).to.not.have.property('optionalField');
});
});
});
Loading
Loading