Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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 @@ -429,7 +429,7 @@ describe('CollectionHeader [Component]', function () {
schemaAnalysis: {
status: SCHEMA_ANALYSIS_STATE_COMPLETE,
processedSchema: {
field1: { type: 'String', sample_values: ['value1'] },
field1: { type: 'String', sampleValues: ['value1'] },
},
schemaMetadata: {
maxNestingDepth: 2, // Below the limit of 4
Expand Down Expand Up @@ -485,7 +485,7 @@ describe('CollectionHeader [Component]', function () {
schemaAnalysis: {
status: SCHEMA_ANALYSIS_STATE_COMPLETE,
processedSchema: {
field1: { type: 'String', sample_values: ['value1'] },
field1: { type: 'String', sampleValues: ['value1'] },
},
schemaMetadata: {
maxNestingDepth: 4, // Exceeds the limit
Expand Down Expand Up @@ -514,7 +514,7 @@ describe('CollectionHeader [Component]', function () {
schemaAnalysis: {
status: SCHEMA_ANALYSIS_STATE_COMPLETE,
processedSchema: {
field1: { type: 'String', sample_values: ['value1'] },
field1: { type: 'String', sampleValues: ['value1'] },
},
schemaMetadata: {
maxNestingDepth: 2,
Expand All @@ -541,7 +541,7 @@ describe('CollectionHeader [Component]', function () {
schemaAnalysis: {
status: SCHEMA_ANALYSIS_STATE_COMPLETE,
processedSchema: {
field1: { type: 'String', sample_values: ['value1'] },
field1: { type: 'String', sampleValues: ['value1'] },
},
schemaMetadata: {
maxNestingDepth: 2,
Expand Down Expand Up @@ -576,7 +576,7 @@ describe('CollectionHeader [Component]', function () {
schemaAnalysis: {
status: SCHEMA_ANALYSIS_STATE_COMPLETE,
processedSchema: {
field1: { type: 'String', sample_values: ['value1'] },
field1: { type: 'String', sampleValues: ['value1'] },
},
schemaMetadata: {
maxNestingDepth: 2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const defaultSchemaAnalysisState: SchemaAnalysisState = {
name: {
type: 'String',
probability: 1.0,
sample_values: ['John', 'Jane'],
sampleValues: ['John', 'Jane'],
},
},
arrayLengthMap: {},
Expand Down Expand Up @@ -510,7 +510,7 @@ describe('MockDataGeneratorModal', () => {
type: {
type: 'String',
probability: 1.0,
sample_values: ['cat', 'dog'],
sampleValues: ['cat', 'dog'],
},
},
sampleDocument: { name: 'Peaches', age: 10, type: 'cat' },
Expand Down
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