From dbeb25602c13792a2ad2c8a73ef4464179406bfe Mon Sep 17 00:00:00 2001 From: Kyle W Lai Date: Mon, 6 Oct 2025 12:58:10 -0400 Subject: [PATCH 1/8] Add mappings --- .../collection-header-actions.tsx | 6 +- .../mock-data-generator-modal/constants.ts | 70 +++++++++++++++++++ .../faker-mapping-selector.tsx | 25 +++++-- .../faker-schema-editor-screen.tsx | 5 ++ .../raw-schema-confirmation-screen.tsx | 17 +++-- .../src/stores/collection-tab.ts | 7 +- .../src/atlas-ai-service.ts | 3 +- packages/compass-generative-ai/src/index.ts | 2 + 8 files changed, 113 insertions(+), 22 deletions(-) diff --git a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx index 613ab6375e0..d4c2a515085 100644 --- a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx +++ b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx @@ -102,9 +102,9 @@ const CollectionHeaderActions: React.FunctionComponent< const { database, collection } = toNS(namespace); // Check if user is in treatment group for Mock Data Generator experiment - const isInMockDataTreatmentVariant = - mockDataGeneratorAssignment?.assignment?.assignmentData?.variant === - ExperimentTestGroup.mockDataGeneratorVariant; + const isInMockDataTreatmentVariant = true; // EDITBACK + // mockDataGeneratorAssignment?.assignment?.assignmentData?.variant === + // ExperimentTestGroup.mockDataGeneratorVariant; const shouldShowMockDataButton = isInMockDataTreatmentVariant && diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts b/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts index 10c3c707087..9d4ad07fe29 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts +++ b/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts @@ -1,3 +1,4 @@ +import type { MongoDBFieldType } from '@mongodb-js/compass-generative-ai'; import { MockDataGeneratorStep } from './types'; export const StepButtonLabelMap = { @@ -10,3 +11,72 @@ export const StepButtonLabelMap = { export const DEFAULT_DOCUMENT_COUNT = 1000; export const MAX_DOCUMENT_COUNT = 100000; + +/** + * Map of MongoDB types to available Faker methods. + * Not all Faker methods are included here. + * More can be found in the Faker.js API: https://fakerjs.dev/api/ + */ +export const MONGO_TYPE_TO_FAKER_METHODS: Record< + MongoDBFieldType, + Array +> = { + String: [ + 'lorem.word', + 'lorem.words', + 'lorem.sentence', + 'lorem.paragraph', + 'person.firstName', + 'person.lastName', + 'person.fullName', + 'person.jobTitle', + 'internet.email', + 'internet.url', + 'internet.domainName', + 'internet.userName', + 'phone.number', + 'location.city', + 'location.country', + 'location.streetAddress', + 'location.zipCode', + 'location.state', + 'company.name', + 'company.catchPhrase', + 'color.human', + 'commerce.productName', + 'commerce.department', + 'finance.accountName', + 'finance.currencyCode', + 'git.commitSha', + 'string.uuid', + 'string.alpha', + 'string.alphanumeric', + ], + Number: [ + 'number.int', + 'number.float', + 'finance.amount', + 'location.latitude', + 'location.longitude', + ], + Int32: ['number.int', 'finance.amount'], + Long: ['number.int', 'number.bigInt'], + Decimal128: ['number.float', 'finance.amount'], + Boolean: ['datatype.boolean'], + Date: [ + 'date.recent', + 'date.past', + 'date.future', + 'date.anytime', + 'date.birthdate', + ], + Timestamp: ['date.recent', 'date.past', 'date.future', 'date.anytime'], + ObjectId: ['database.mongodbObjectId'], + Binary: ['string.hexadecimal', 'string.binary'], + RegExp: ['lorem.word', 'string.alpha'], + Code: ['lorem.sentence', 'lorem.paragraph', 'git.commitMessage'], + MinKey: ['number.int'], + MaxKey: ['number.int'], + Symbol: ['lorem.word', 'string.symbol'], + DBRef: ['database.mongodbObjectId'], +}; diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.tsx index b6c1aa726b0..cd1673cc92b 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.tsx @@ -8,9 +8,11 @@ import { Select, spacing, } from '@mongodb-js/compass-components'; -import React from 'react'; +import React, { useMemo } from 'react'; import { UNRECOGNIZED_FAKER_METHOD } from '../../modules/collection-tab'; import type { MongoDBFieldType } from '@mongodb-js/compass-generative-ai'; +import { MongoDBFieldTypeValues } from '@mongodb-js/compass-generative-ai'; +import { MONGO_TYPE_TO_FAKER_METHODS } from './constants'; const fieldMappingSelectorsStyles = css({ width: '50%', @@ -37,6 +39,17 @@ const FakerMappingSelector = ({ onJsonTypeSelect, onFakerFunctionSelect, }: Props) => { + const fakerMethodOptions = useMemo(() => { + const methods = + MONGO_TYPE_TO_FAKER_METHODS[activeJsonType as MongoDBFieldType] || []; + + if (methods.includes(activeFakerFunction)) { + return methods; + } + + return [activeFakerFunction, ...methods]; + }, [activeJsonType, activeFakerFunction]); + return (
Mapping @@ -46,8 +59,7 @@ const FakerMappingSelector = ({ value={activeJsonType} onChange={(value) => onJsonTypeSelect(value as MongoDBFieldType)} > - {/* TODO(CLOUDP-344400) : Make the select input editable and render other options depending on the JSON type selected */} - {[activeJsonType].map((type) => ( + {Object.values(MongoDBFieldTypeValues).map((type) => ( @@ -59,10 +71,9 @@ const FakerMappingSelector = ({ value={activeFakerFunction} onChange={onFakerFunctionSelect} > - {/* TODO(CLOUDP-344400): Make the select input editable and render other JSON types */} - {[activeFakerFunction].map((field) => ( - ))} diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx index 39b6a5d7a27..42cf78831d9 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx @@ -14,6 +14,7 @@ import FieldSelector from './schema-field-selector'; import FakerMappingSelector from './faker-mapping-selector'; import type { FakerSchema, MockDataGeneratorState } from './types'; import type { MongoDBFieldType } from '@mongodb-js/compass-generative-ai'; +import { getDefaultFakerMethod } from './script-generation-utils'; const containerStyles = css({ display: 'flex', @@ -72,11 +73,15 @@ const FakerSchemaEditorContent = ({ const onJsonTypeSelect = (newJsonType: MongoDBFieldType) => { const currentMapping = fakerSchemaFormValues[activeField]; if (currentMapping) { + // When MongoDB type changes, update the faker method to a default for that type + const defaultFakerMethod = getDefaultFakerMethod(newJsonType); setFakerSchemaFormValues({ ...fakerSchemaFormValues, [activeField]: { ...currentMapping, mongoType: newJsonType, + fakerMethod: defaultFakerMethod, + fakerArgs: [], // Reset args when changing type }, }); resetIsSchemaConfirmed(); diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx index e55182e192c..2e82c1cd3b1 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx @@ -9,6 +9,7 @@ import { BannerVariant, Body, DocumentList, + useDarkMode, } from '@mongodb-js/compass-components'; import { usePreference } from 'compass-preferences-model/provider'; @@ -23,11 +24,14 @@ interface RawSchemaConfirmationScreenProps { fakerSchemaGenerationStatus: MockDataGeneratorState['status']; } -const documentContainerStyles = css({ - backgroundColor: palette.gray.light3, - border: `1px solid ${palette.gray.light2}`, - borderRadius: spacing[400], -}); +const getDocumentContainerStyles = (isDarkMode: boolean) => + css({ + backgroundColor: isDarkMode ? palette.gray.dark3 : palette.gray.light3, + border: `1px solid ${ + isDarkMode ? palette.gray.dark2 : palette.gray.light2 + }`, + borderRadius: spacing[400], + }); const documentStyles = css({ padding: `${spacing[400]}px ${spacing[900]}px`, @@ -52,6 +56,7 @@ const RawSchemaConfirmationScreen = ({ const enableSampleDocumentPassing = usePreference( 'enableGenAISampleDocumentPassing' ); + const isDarkMode = useDarkMode(); const subtitleText = enableSampleDocumentPassing ? 'Sample Documents Collected' @@ -69,7 +74,7 @@ const RawSchemaConfirmationScreen = ({ {subtitleText} {descriptionText} -
+
Date: Mon, 6 Oct 2025 13:30:01 -0400 Subject: [PATCH 2/8] Cleanup --- .../collection-header-actions.tsx | 6 +++--- packages/compass-collection/src/stores/collection-tab.ts | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx index d4c2a515085..613ab6375e0 100644 --- a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx +++ b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx @@ -102,9 +102,9 @@ const CollectionHeaderActions: React.FunctionComponent< const { database, collection } = toNS(namespace); // Check if user is in treatment group for Mock Data Generator experiment - const isInMockDataTreatmentVariant = true; // EDITBACK - // mockDataGeneratorAssignment?.assignment?.assignmentData?.variant === - // ExperimentTestGroup.mockDataGeneratorVariant; + const isInMockDataTreatmentVariant = + mockDataGeneratorAssignment?.assignment?.assignmentData?.variant === + ExperimentTestGroup.mockDataGeneratorVariant; const shouldShowMockDataButton = isInMockDataTreatmentVariant && diff --git a/packages/compass-collection/src/stores/collection-tab.ts b/packages/compass-collection/src/stores/collection-tab.ts index 968f673baee..fc404e20c1f 100644 --- a/packages/compass-collection/src/stores/collection-tab.ts +++ b/packages/compass-collection/src/stores/collection-tab.ts @@ -170,9 +170,10 @@ export function activatePlugin( ExperimentTestName.mockDataGenerator, false // Don't track "Experiment Viewed" event here ); - return true; // EDITBACK - // assignment?.assignmentData?.variant === - // ExperimentTestGroup.mockDataGeneratorVariant + return ( + assignment?.assignmentData?.variant === + ExperimentTestGroup.mockDataGeneratorVariant + ); } catch (error) { // On error, default to not running schema analysis logger.debug( From 73f6b49a8ddcf72240c3dc46d3f018ec9181c42d Mon Sep 17 00:00:00 2001 From: Kyle W Lai Date: Mon, 6 Oct 2025 15:31:13 -0400 Subject: [PATCH 3/8] Add unit tests --- .../faker-mapping-selector.spec.tsx | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx new file mode 100644 index 00000000000..87184817b8c --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx @@ -0,0 +1,152 @@ +import { expect } from 'chai'; +import React from 'react'; +import { + screen, + render, + cleanup, + waitFor, + userEvent, +} from '@mongodb-js/testing-library-compass'; +import sinon from 'sinon'; +import FakerMappingSelector from './faker-mapping-selector'; +import { UNRECOGNIZED_FAKER_METHOD } from '../../modules/collection-tab'; +import { MONGO_TYPE_TO_FAKER_METHODS } from './constants'; +import { MongoDBFieldTypeValues } from '@mongodb-js/compass-generative-ai'; + +const mockActiveJsonType = MongoDBFieldTypeValues.String; +const mockActiveFakerFunction = 'lorem.word'; +const onJsonTypeSelectStub = sinon.stub(); +const onFakerFunctionSelectStub = sinon.stub(); + +describe('FakerMappingSelector', () => { + afterEach(() => { + cleanup(); + }); + + it('should display all MongoDB types in the dropdown', async () => { + // Check that all MongoDB types from the constant are present + const mongoTypes = Object.keys(MongoDBFieldTypeValues); + + render( + + ); + + const jsonTypeSelect = screen.getByLabelText('JSON Type'); + userEvent.click(jsonTypeSelect); + + for (const type of mongoTypes) { + await waitFor(() => { + expect(screen.getByRole('option', { name: type })).to.exist; + }); + } + }); + + describe('should display faker methods for each MongoDB type', () => { + Object.entries(MONGO_TYPE_TO_FAKER_METHODS).forEach( + ([mongoType, methods]) => { + it(`should display faker methods for ${mongoType}`, () => { + const firstMethod = methods[0]; + + render( + + ); + + const fakerFunctionSelect = screen.getByLabelText('Faker Function'); + userEvent.click(fakerFunctionSelect); + + methods.forEach((method) => { + expect(screen.getByRole('option', { name: method })).to.exist; + }); + }); + } + ); + }); + + it('should call onJsonTypeSelect when MongoDB type changes', async () => { + render( + + ); + + const jsonTypeSelect = screen.getByLabelText('JSON Type'); + userEvent.click(jsonTypeSelect); + + const numberOption = await screen.findByRole('option', { name: 'Number' }); + userEvent.click(numberOption); + + expect(onJsonTypeSelectStub).to.have.been.calledOnceWith('Number'); + }); + + it('should call onFakerFunctionSelect when faker function changes', async () => { + render( + + ); + + const fakerFunctionSelect = screen.getByLabelText('Faker Function'); + userEvent.click(fakerFunctionSelect); + + const emailOption = await screen.findByRole('option', { + name: 'internet.email', + }); + userEvent.click(emailOption); + + expect(onFakerFunctionSelectStub).to.have.been.calledOnceWith( + 'internet.email' + ); + }); + + it('should show warning banner when faker method is unrecognized', () => { + render( + + ); + + expect( + screen.getByText( + /Please select a function or we will default fill this field/ + ) + ).to.exist; + }); + + it('should not show warning banner when faker method is recognized', () => { + render( + + ); + + expect( + screen.queryByText( + /Please select a function or we will default fill this field/ + ) + ).to.not.exist; + }); +}); From b478cd2f93d5ed08d4480057704bbab2321c87ab Mon Sep 17 00:00:00 2001 From: Kyle W Lai Date: Fri, 10 Oct 2025 16:13:00 -0400 Subject: [PATCH 4/8] Memorize css --- .../faker-mapping-selector.spec.tsx | 48 +++++++++---------- .../faker-mapping-selector.tsx | 5 +- .../raw-schema-confirmation-screen.tsx | 9 +++- .../script-generation-utils.spec.ts | 31 ++++++------ .../script-generation-utils.ts | 3 +- 5 files changed, 51 insertions(+), 45 deletions(-) diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx index 87184817b8c..5b455ba74a3 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx @@ -47,31 +47,31 @@ describe('FakerMappingSelector', () => { }); describe('should display faker methods for each MongoDB type', () => { - Object.entries(MONGO_TYPE_TO_FAKER_METHODS).forEach( - ([mongoType, methods]) => { - it(`should display faker methods for ${mongoType}`, () => { - const firstMethod = methods[0]; - - render( - - ); - - const fakerFunctionSelect = screen.getByLabelText('Faker Function'); - userEvent.click(fakerFunctionSelect); - - methods.forEach((method) => { - expect(screen.getByRole('option', { name: method })).to.exist; - }); + for (const [mongoType, methods] of Object.entries( + MONGO_TYPE_TO_FAKER_METHODS + )) { + it(`should display faker methods for ${mongoType}`, () => { + const firstMethod = methods[0]; + + render( + + ); + + const fakerFunctionSelect = screen.getByLabelText('Faker Function'); + userEvent.click(fakerFunctionSelect); + + methods.forEach((method) => { + expect(screen.getByRole('option', { name: method })).to.exist; }); - } - ); + }); + } }); it('should call onJsonTypeSelect when MongoDB type changes', async () => { diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.tsx index cd1673cc92b..38868371a81 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.tsx @@ -27,7 +27,7 @@ const labelStyles = css({ }); interface Props { - activeJsonType: string; + activeJsonType: MongoDBFieldType; activeFakerFunction: string; onJsonTypeSelect: (jsonType: MongoDBFieldType) => void; onFakerFunctionSelect: (fakerFunction: string) => void; @@ -40,8 +40,7 @@ const FakerMappingSelector = ({ onFakerFunctionSelect, }: Props) => { const fakerMethodOptions = useMemo(() => { - const methods = - MONGO_TYPE_TO_FAKER_METHODS[activeJsonType as MongoDBFieldType] || []; + const methods = MONGO_TYPE_TO_FAKER_METHODS[activeJsonType] || []; if (methods.includes(activeFakerFunction)) { return methods; diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx index 2e82c1cd3b1..7872ad79b2d 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { connect } from 'react-redux'; import { @@ -58,6 +58,11 @@ const RawSchemaConfirmationScreen = ({ ); const isDarkMode = useDarkMode(); + const documentContainerStyles = useMemo( + () => getDocumentContainerStyles(!!isDarkMode), + [isDarkMode] + ); + const subtitleText = enableSampleDocumentPassing ? 'Sample Documents Collected' : 'Document Schema Identified'; @@ -74,7 +79,7 @@ const RawSchemaConfirmationScreen = ({ {subtitleText} {descriptionText} -
+
{ const schema = { unknownField: { mongoType: 'String' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, }; @@ -803,32 +804,32 @@ describe('Script Generation', () => { const schema = { unknownNumber: { mongoType: 'Number' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, unknownInt: { mongoType: 'Int32' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, unknownInt32: { mongoType: 'Int32' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, unknownInt64: { mongoType: 'Long' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, unknownLong: { mongoType: 'Long' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, unknownDecimal128: { mongoType: 'Decimal128' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, }; @@ -879,7 +880,7 @@ describe('Script Generation', () => { const schema = { unknownDate: { mongoType: 'Date' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, }; @@ -903,7 +904,7 @@ describe('Script Generation', () => { const schema = { unknownBool: { mongoType: 'Boolean' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, }; @@ -927,7 +928,7 @@ describe('Script Generation', () => { const schema = { unknownId: { mongoType: 'ObjectId' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, }; @@ -951,7 +952,7 @@ describe('Script Generation', () => { const schema = { unknownType: { mongoType: 'String' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, }; @@ -975,7 +976,7 @@ describe('Script Generation', () => { const schema = { timestampField: { mongoType: 'Timestamp' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, }; @@ -999,7 +1000,7 @@ describe('Script Generation', () => { const schema = { regexField: { mongoType: 'RegExp' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, }; @@ -1023,7 +1024,7 @@ describe('Script Generation', () => { const schema = { jsField: { mongoType: 'Code' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], }, }; @@ -1399,7 +1400,7 @@ describe('Script Generation', () => { const schema = { unknownField: { mongoType: 'String' as const, - fakerMethod: 'unrecognized', + fakerMethod: UNRECOGNIZED_FAKER_METHOD, fakerArgs: [], probability: 0.5, }, diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/script-generation-utils.ts b/packages/compass-collection/src/components/mock-data-generator-modal/script-generation-utils.ts index 15687a4b76d..46424fcc9cb 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/script-generation-utils.ts +++ b/packages/compass-collection/src/components/mock-data-generator-modal/script-generation-utils.ts @@ -1,6 +1,7 @@ import type { MongoDBFieldType } from '@mongodb-js/compass-generative-ai'; import type { FakerFieldMapping } from './types'; import { prettify } from '@mongodb-js/compass-editor'; +import { UNRECOGNIZED_FAKER_METHOD } from '../../modules/collection-tab'; export type FakerArg = string | number | boolean | { json: string }; @@ -446,7 +447,7 @@ function renderArrayCode( */ function generateFakerCall(mapping: FakerFieldMapping): string { const method = - mapping.fakerMethod === 'unrecognized' + mapping.fakerMethod === UNRECOGNIZED_FAKER_METHOD ? getDefaultFakerMethod(mapping.mongoType) : mapping.fakerMethod; From 85bf859ae49451d32dc1ef3ca28ca18fab7578aa Mon Sep 17 00:00:00 2001 From: Kyle W Lai Date: Fri, 10 Oct 2025 19:36:24 -0400 Subject: [PATCH 5/8] Default to LLM suggested faker fields if choosing an LLM suggested method --- .../faker-schema-editor-screen.tsx | 65 +++++++++++++++---- .../raw-schema-confirmation-screen.tsx | 33 +++++----- 2 files changed, 70 insertions(+), 28 deletions(-) diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx index 42cf78831d9..f5b24852699 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx @@ -12,7 +12,11 @@ import { import React from 'react'; import FieldSelector from './schema-field-selector'; import FakerMappingSelector from './faker-mapping-selector'; -import type { FakerSchema, MockDataGeneratorState } from './types'; +import type { + FakerSchema, + FakerFieldMapping, + MockDataGeneratorState, +} from './types'; import type { MongoDBFieldType } from '@mongodb-js/compass-generative-ai'; import { getDefaultFakerMethod } from './script-generation-utils'; @@ -60,6 +64,20 @@ const FakerSchemaEditorContent = ({ const [fakerSchemaFormValues, setFakerSchemaFormValues] = React.useState(fakerSchema); + // Store original LLM mappings to restore when reselecting original methods + const originalLlmMappings = React.useRef>( + Object.fromEntries( + Object.entries(fakerSchema).map(([field, mapping]) => [ + field, + { + mongoType: mapping.mongoType, + fakerMethod: mapping.fakerMethod, + fakerArgs: mapping.fakerArgs, + }, + ]) + ) + ); + const fieldPaths = Object.keys(fakerSchemaFormValues); const [activeField, setActiveField] = React.useState(fieldPaths[0]); @@ -72,17 +90,25 @@ const FakerSchemaEditorContent = ({ const onJsonTypeSelect = (newJsonType: MongoDBFieldType) => { const currentMapping = fakerSchemaFormValues[activeField]; + const originalLlmMapping = originalLlmMappings.current[activeField]; + if (currentMapping) { - // When MongoDB type changes, update the faker method to a default for that type - const defaultFakerMethod = getDefaultFakerMethod(newJsonType); + const isSwitchingToOriginalType = + originalLlmMapping && newJsonType === originalLlmMapping.mongoType; + + const newMapping = + isSwitchingToOriginalType && originalLlmMapping + ? { ...originalLlmMapping } + : { + ...currentMapping, + mongoType: newJsonType, + fakerMethod: getDefaultFakerMethod(newJsonType), + fakerArgs: [], + }; + setFakerSchemaFormValues({ ...fakerSchemaFormValues, - [activeField]: { - ...currentMapping, - mongoType: newJsonType, - fakerMethod: defaultFakerMethod, - fakerArgs: [], // Reset args when changing type - }, + [activeField]: newMapping, }); resetIsSchemaConfirmed(); } @@ -90,13 +116,26 @@ const FakerSchemaEditorContent = ({ const onFakerFunctionSelect = (newFakerFunction: string) => { const currentMapping = fakerSchemaFormValues[activeField]; + const originalLlmMapping = originalLlmMappings.current[activeField]; + if (currentMapping) { + const isSwitchingToLlmSuggestion = + originalLlmMapping && + currentMapping.mongoType === originalLlmMapping.mongoType && + newFakerFunction === originalLlmMapping.fakerMethod; + + const newMapping = + isSwitchingToLlmSuggestion && originalLlmMapping + ? { ...originalLlmMapping } + : { + ...currentMapping, + fakerMethod: newFakerFunction, + fakerArgs: [], + }; + setFakerSchemaFormValues({ ...fakerSchemaFormValues, - [activeField]: { - ...currentMapping, - fakerMethod: newFakerFunction, - }, + [activeField]: newMapping, }); resetIsSchemaConfirmed(); } diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx index 7872ad79b2d..788e09ea23c 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React from 'react'; import { connect } from 'react-redux'; import { @@ -10,6 +10,7 @@ import { Body, DocumentList, useDarkMode, + cx, } from '@mongodb-js/compass-components'; import { usePreference } from 'compass-preferences-model/provider'; @@ -24,14 +25,16 @@ interface RawSchemaConfirmationScreenProps { fakerSchemaGenerationStatus: MockDataGeneratorState['status']; } -const getDocumentContainerStyles = (isDarkMode: boolean) => - css({ - backgroundColor: isDarkMode ? palette.gray.dark3 : palette.gray.light3, - border: `1px solid ${ - isDarkMode ? palette.gray.dark2 : palette.gray.light2 - }`, - borderRadius: spacing[400], - }); +const documentContainerStyles = css({ + backgroundColor: palette.gray.light3, + border: `1px solid ${palette.gray.light2}`, + borderRadius: spacing[400], +}); +const documentContainerDarkStyles = css({ + backgroundColor: palette.gray.dark3, + border: `1px solid ${palette.gray.dark2}`, + borderRadius: spacing[400], +}); const documentStyles = css({ padding: `${spacing[400]}px ${spacing[900]}px`, @@ -58,11 +61,6 @@ const RawSchemaConfirmationScreen = ({ ); const isDarkMode = useDarkMode(); - const documentContainerStyles = useMemo( - () => getDocumentContainerStyles(!!isDarkMode), - [isDarkMode] - ); - const subtitleText = enableSampleDocumentPassing ? 'Sample Documents Collected' : 'Document Schema Identified'; @@ -79,7 +77,12 @@ const RawSchemaConfirmationScreen = ({ {subtitleText} {descriptionText} -
+
Date: Tue, 14 Oct 2025 13:27:52 -0400 Subject: [PATCH 6/8] Address comments --- .../mock-data-generator-modal/constants.ts | 23 ++++++++++-- .../faker-schema-editor-screen.tsx | 36 +++++++++---------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts b/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts index 9d4ad07fe29..c5935479ee6 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts +++ b/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts @@ -13,9 +13,9 @@ export const DEFAULT_DOCUMENT_COUNT = 1000; export const MAX_DOCUMENT_COUNT = 100000; /** - * Map of MongoDB types to available Faker methods. + * Map of MongoDB types to available Faker v9 methods. * Not all Faker methods are included here. - * More can be found in the Faker.js API: https://fakerjs.dev/api/ + * More can be found in the Faker.js API: https://v9.fakerjs.dev/api/ */ export const MONGO_TYPE_TO_FAKER_METHODS: Record< MongoDBFieldType, @@ -30,7 +30,10 @@ export const MONGO_TYPE_TO_FAKER_METHODS: Record< 'person.lastName', 'person.fullName', 'person.jobTitle', + 'internet.displayName', 'internet.email', + 'internet.emoji', + 'internet.password', 'internet.url', 'internet.domainName', 'internet.userName', @@ -51,8 +54,24 @@ export const MONGO_TYPE_TO_FAKER_METHODS: Record< 'string.uuid', 'string.alpha', 'string.alphanumeric', + 'system.fileName', + 'system.filePath', + 'system.mimeType', + 'book.title', + 'music.songName', + 'food.dish', + 'animal.type', + 'vehicle.model', + 'hacker.phrase', + 'science.chemicalElement', ], Number: [ + 'number.binary', + 'number.octal', + 'number.hex', + 'commerce.price', + 'date.weekday', + 'internet.port', 'number.int', 'number.float', 'finance.amount', diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx index f5b24852699..eed57c72ac7 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/faker-schema-editor-screen.tsx @@ -70,9 +70,7 @@ const FakerSchemaEditorContent = ({ Object.entries(fakerSchema).map(([field, mapping]) => [ field, { - mongoType: mapping.mongoType, - fakerMethod: mapping.fakerMethod, - fakerArgs: mapping.fakerArgs, + ...mapping, }, ]) ) @@ -96,15 +94,14 @@ const FakerSchemaEditorContent = ({ const isSwitchingToOriginalType = originalLlmMapping && newJsonType === originalLlmMapping.mongoType; - const newMapping = - isSwitchingToOriginalType && originalLlmMapping - ? { ...originalLlmMapping } - : { - ...currentMapping, - mongoType: newJsonType, - fakerMethod: getDefaultFakerMethod(newJsonType), - fakerArgs: [], - }; + const newMapping = isSwitchingToOriginalType + ? { ...originalLlmMapping } + : { + ...currentMapping, + mongoType: newJsonType, + fakerMethod: getDefaultFakerMethod(newJsonType), + fakerArgs: [], + }; setFakerSchemaFormValues({ ...fakerSchemaFormValues, @@ -124,14 +121,13 @@ const FakerSchemaEditorContent = ({ currentMapping.mongoType === originalLlmMapping.mongoType && newFakerFunction === originalLlmMapping.fakerMethod; - const newMapping = - isSwitchingToLlmSuggestion && originalLlmMapping - ? { ...originalLlmMapping } - : { - ...currentMapping, - fakerMethod: newFakerFunction, - fakerArgs: [], - }; + const newMapping = isSwitchingToLlmSuggestion + ? { ...originalLlmMapping } + : { + ...currentMapping, + fakerMethod: newFakerFunction, + fakerArgs: [], + }; setFakerSchemaFormValues({ ...fakerSchemaFormValues, From d3baf49e88edad54d303abcc63d250bf8862dd51 Mon Sep 17 00:00:00 2001 From: Kyle W Lai Date: Tue, 14 Oct 2025 15:47:06 -0400 Subject: [PATCH 7/8] Fix failing unit tests --- .../faker-mapping-selector.spec.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx index 5b455ba74a3..15c98b76298 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx @@ -12,9 +12,11 @@ import FakerMappingSelector from './faker-mapping-selector'; import { UNRECOGNIZED_FAKER_METHOD } from '../../modules/collection-tab'; import { MONGO_TYPE_TO_FAKER_METHODS } from './constants'; import { MongoDBFieldTypeValues } from '@mongodb-js/compass-generative-ai'; +import { FakerArg } from './script-generation-utils'; const mockActiveJsonType = MongoDBFieldTypeValues.String; const mockActiveFakerFunction = 'lorem.word'; +const mockActiveFakerArgs: Array = []; const onJsonTypeSelectStub = sinon.stub(); const onFakerFunctionSelectStub = sinon.stub(); @@ -31,6 +33,7 @@ describe('FakerMappingSelector', () => { @@ -59,6 +62,7 @@ describe('FakerMappingSelector', () => { mongoType as keyof typeof MONGO_TYPE_TO_FAKER_METHODS } activeFakerFunction={firstMethod} + activeFakerArgs={mockActiveFakerArgs} onJsonTypeSelect={onJsonTypeSelectStub} onFakerFunctionSelect={onFakerFunctionSelectStub} /> @@ -79,6 +83,7 @@ describe('FakerMappingSelector', () => { @@ -98,6 +103,7 @@ describe('FakerMappingSelector', () => { @@ -121,6 +127,7 @@ describe('FakerMappingSelector', () => { @@ -138,6 +145,7 @@ describe('FakerMappingSelector', () => { From e1d8a5f149cae685ab91ec46b061018239571b4d Mon Sep 17 00:00:00 2001 From: Kyle W Lai Date: Tue, 14 Oct 2025 17:34:15 -0400 Subject: [PATCH 8/8] Fix failing type check --- .../mock-data-generator-modal/faker-mapping-selector.spec.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx index 15c98b76298..84d7c129603 100644 --- a/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx +++ b/packages/compass-collection/src/components/mock-data-generator-modal/faker-mapping-selector.spec.tsx @@ -12,7 +12,7 @@ import FakerMappingSelector from './faker-mapping-selector'; import { UNRECOGNIZED_FAKER_METHOD } from '../../modules/collection-tab'; import { MONGO_TYPE_TO_FAKER_METHODS } from './constants'; import { MongoDBFieldTypeValues } from '@mongodb-js/compass-generative-ai'; -import { FakerArg } from './script-generation-utils'; +import type { FakerArg } from './script-generation-utils'; const mockActiveJsonType = MongoDBFieldTypeValues.String; const mockActiveFakerFunction = 'lorem.word';