Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,67 @@
import React, { useMemo } from 'react';
import {
css,
spacing,
Body,
DocumentList,
} from '@mongodb-js/compass-components';
import HadronDocument from 'hadron-document';
import type { FakerSchema } from './types';
import { generateDocument } from './script-generation-utils';

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

const documentContainerStyles = css({
display: 'flex',
flexDirection: 'column',
gap: spacing[300],
});

const documentWrapperStyles = css({
border: '1px solid #E8EDEB',
borderRadius: '6px',
padding: 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++) {
const plainDoc = generateDocument(confirmedFakerSchema);
const hadronDoc = new HadronDocument(plainDoc);
hadronDoc.expand(); // Expand by default for better preview
documents.push(hadronDoc);
}

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>
<div className={documentContainerStyles}>
{sampleDocuments.map((doc, index) => (
<div key={index} className={documentWrapperStyles}>
<DocumentList.Document value={doc} />
</div>
))}
</div>
</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