Skip to content
Closed
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
42 changes: 42 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect } from 'chai';
import React from 'react';
import {
screen,
render,
renderWithActiveConnection,
waitFor,
userEvent,
} from '@mongodb-js/testing-library-compass';
Expand All @@ -14,12 +14,19 @@ import { MockDataGeneratorStep } from './types';
import { StepButtonLabelMap } from './constants';
import type { CollectionState } from '../../modules/collection-tab';
import { default as collectionTabReducer } from '../../modules/collection-tab';
import type { ConnectionInfo } from '@mongodb-js/connection-info';

describe('MockDataGeneratorModal', () => {
function renderModal({
async function renderModal({
isOpen = true,
currentStep = MockDataGeneratorStep.SCHEMA_CONFIRMATION,
mockServices = createMockServices(),
connectionInfo,
}: {
isOpen?: boolean;
currentStep?: MockDataGeneratorStep;
mockServices?: any;
connectionInfo?: ConnectionInfo;
} = {}) {
const initialState: CollectionState = {
workspaceTabId: 'test-workspace-tab-id',
Expand Down Expand Up @@ -52,10 +59,11 @@ describe('MockDataGeneratorModal', () => {
applyMiddleware(thunk.withExtraArgument(mockServices))
);

return render(
return await renderWithActiveConnection(
<Provider store={store}>
<MockDataGeneratorModal />
</Provider>
</Provider>,
connectionInfo
);
}

Expand Down Expand Up @@ -89,20 +97,20 @@ describe('MockDataGeneratorModal', () => {
}

describe('generally', () => {
it('renders the modal when isOpen is true', () => {
renderModal();
it('renders the modal when isOpen is true', async () => {
await renderModal();

expect(screen.getByTestId('generate-mock-data-modal')).to.exist;
});

it('does not render the modal when isOpen is false', () => {
renderModal({ isOpen: false });
it('does not render the modal when isOpen is false', async () => {
await renderModal({ isOpen: false });

expect(screen.queryByTestId('generate-mock-data-modal')).to.not.exist;
});

it('closes the modal when the close button is clicked', async () => {
renderModal();
await renderModal();

expect(screen.getByTestId('generate-mock-data-modal')).to.exist;
userEvent.click(screen.getByLabelText('Close modal'));
Expand All @@ -113,7 +121,7 @@ describe('MockDataGeneratorModal', () => {
});

it('closes the modal when the cancel button is clicked', async () => {
renderModal();
await renderModal();

expect(screen.getByTestId('generate-mock-data-modal')).to.exist;
userEvent.click(screen.getByText('Cancel'));
Expand Down Expand Up @@ -154,7 +162,7 @@ describe('MockDataGeneratorModal', () => {

it('cancels in-flight faker mapping requests when the cancel button is clicked', async () => {
const mockServices = createMockServicesWithSlowAiRequest();
renderModal({ mockServices: mockServices as any });
await renderModal({ mockServices: mockServices as any });

expect(screen.getByTestId('raw-schema-confirmation')).to.exist;
userEvent.click(screen.getByText('Confirm'));
Expand All @@ -170,7 +178,7 @@ describe('MockDataGeneratorModal', () => {

it('cancels in-flight faker mapping requests when the back button is clicked after schema confirmation', async () => {
const mockServices = createMockServicesWithSlowAiRequest();
renderModal({ mockServices: mockServices as any });
await renderModal({ mockServices: mockServices as any });

expect(screen.getByTestId('raw-schema-confirmation')).to.exist;
userEvent.click(screen.getByText('Confirm'));
Expand All @@ -186,8 +194,8 @@ describe('MockDataGeneratorModal', () => {
});

describe('on the schema confirmation step', () => {
it('disables the Back button', () => {
renderModal();
it('disables the Back button', async () => {
await renderModal();

expect(
screen
Expand All @@ -197,7 +205,7 @@ describe('MockDataGeneratorModal', () => {
});

it('renders the faker schema editor when the confirm button is clicked', async () => {
renderModal();
await renderModal();

expect(screen.getByTestId('raw-schema-confirmation')).to.exist;
expect(screen.queryByTestId('faker-schema-editor')).to.not.exist;
Expand All @@ -212,7 +220,7 @@ describe('MockDataGeneratorModal', () => {
const mockServices = createMockServices();
mockServices.atlasAiService.getMockDataSchema = () =>
Promise.reject('faker schema generation failed');
renderModal({ mockServices });
await renderModal({ mockServices });

expect(screen.getByTestId('raw-schema-confirmation')).to.exist;
expect(screen.queryByTestId('faker-schema-editor')).to.not.exist;
Expand All @@ -228,15 +236,101 @@ describe('MockDataGeneratorModal', () => {
// todo: assert that closing then re-opening the modal after an LLM err removes the err message
});

describe('on the generate data step', () => {
it('enables the Back button', async () => {
await renderModal({ currentStep: MockDataGeneratorStep.GENERATE_DATA });

expect(
screen
.getByRole('button', { name: 'Back' })
.getAttribute('aria-disabled')
).to.not.equal('true');
});

it('renders the main sections: Prerequisites, steps, and Resources', async () => {
await renderModal({ currentStep: MockDataGeneratorStep.GENERATE_DATA });

expect(screen.getByText('Prerequisites')).to.exist;
expect(screen.getByText('1. Create a .js file with the following script'))
.to.exist;
expect(screen.getByText('2. Run the script with')).to.exist;
expect(screen.getByText('Resources')).to.exist;
});

it('closes the modal when the Done button is clicked', async () => {
await renderModal({ currentStep: MockDataGeneratorStep.GENERATE_DATA });

expect(screen.getByTestId('generate-mock-data-modal')).to.exist;
userEvent.click(screen.getByText('Done'));
await waitFor(
() =>
expect(screen.queryByTestId('generate-mock-data-modal')).to.not.exist
);
});

it('renders the Database Users link with correct URL when projectId is available', async () => {
const atlasConnectionInfo: ConnectionInfo = {
id: 'test-atlas-connection',
connectionOptions: { connectionString: 'mongodb://localhost:27017' },
atlasMetadata: {
orgId: 'test-org',
projectId: 'test-project-123',
clusterName: 'test-cluster',
clusterUniqueId: 'test-cluster-unique-id',
clusterType: 'REPLICASET' as const,
clusterState: 'IDLE' as const,
metricsId: 'test-metrics-id',
metricsType: 'replicaSet' as const,
regionalBaseUrl: null,
instanceSize: 'M10',
supports: {
globalWrites: false,
rollingIndexes: true,
},
},
};

await renderModal({
currentStep: MockDataGeneratorStep.GENERATE_DATA,
connectionInfo: atlasConnectionInfo,
});

const databaseUsersLink = screen.getByRole('link', {
name: 'Access your Database Users',
});
expect(databaseUsersLink.getAttribute('href')).to.equal(
'/v2/test-project-123#/security/database/users'
);
});

it('does not render the Database Users link when projectId is not available', async () => {
const nonAtlasConnectionInfo: ConnectionInfo = {
id: 'test-local-connection',
connectionOptions: { connectionString: 'mongodb://localhost:27017' },
// No atlasMetadata means no projectId
};

await renderModal({
currentStep: MockDataGeneratorStep.GENERATE_DATA,
connectionInfo: nonAtlasConnectionInfo,
});

expect(screen.queryByRole('link', { name: 'Access your Database Users' }))
.to.not.exist;
});

// todo: assert that the generated script is displayed in the code block
});

describe('when rendering the modal in a specific step', () => {
const steps = Object.keys(
StepButtonLabelMap
) as unknown as MockDataGeneratorStep[];

// note: these tests can be removed after every modal step is implemented
steps.forEach((currentStep) => {
it(`renders the button with the correct label when the user is in step "${currentStep}"`, () => {
renderModal({ currentStep });
it(`renders the button with the correct label when the user is in step "${currentStep}"`, async () => {
await renderModal({ currentStep });
expect(screen.getByTestId('next-step-button')).to.have.text(
StepButtonLabelMap[currentStep]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ import {
} from '../../modules/collection-tab';
import { default as SchemaConfirmationScreen } from './raw-schema-confirmation';
import FakerSchemaEditor from './faker-schema-editor';
import ScriptScreen from './script-screen';

const STEP_TO_STEP_CONTENT: Record<MockDataGeneratorStep, React.JSX.Element> = {
[MockDataGeneratorStep.SCHEMA_CONFIRMATION]: <SchemaConfirmationScreen />,
[MockDataGeneratorStep.SCHEMA_EDITOR]: <FakerSchemaEditor />,
[MockDataGeneratorStep.DOCUMENT_COUNT]: <></>, // TODO: Implement as part of CLOUDP-333856
[MockDataGeneratorStep.PREVIEW_DATA]: <></>, // TODO: Implement as part of CLOUDP-333857
[MockDataGeneratorStep.GENERATE_DATA]: <ScriptScreen />,
};

const footerStyles = css`
flex-direction: row;
Expand Down Expand Up @@ -62,18 +71,9 @@ const MockDataGeneratorModal = ({
}
};

let stepContent: React.ReactNode;

if (currentStep === MockDataGeneratorStep.SCHEMA_CONFIRMATION) {
stepContent = <SchemaConfirmationScreen />;
}

if (currentStep === MockDataGeneratorStep.SCHEMA_EDITOR) {
stepContent = <FakerSchemaEditor />;
}

return (
<Modal
size="large"
open={isOpen}
setOpen={(open) => {
if (!open) {
Expand All @@ -84,8 +84,9 @@ const MockDataGeneratorModal = ({
>
<ModalHeader title="Generate Mock Data" />
<ModalBody>
{stepContent}
<div data-testid={`generate-mock-data-step-${currentStep}`} />
<div data-testid={`generate-mock-data-step-${currentStep}`}>
{STEP_TO_STEP_CONTENT[currentStep]}
</div>
</ModalBody>
<ModalFooter className={footerStyles}>
<Button
Expand Down
Loading
Loading