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 new file mode 100644 index 00000000000..5057ee5946a --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts @@ -0,0 +1,10 @@ +import { MockDataGeneratorStep } from './types'; + +export const StepButtonLabelMap = { + [MockDataGeneratorStep.AI_DISCLAIMER]: 'Use Natural Language', + [MockDataGeneratorStep.SCHEMA_CONFIRMATION]: 'Confirm', + [MockDataGeneratorStep.SCHEMA_EDITOR]: 'Next', + [MockDataGeneratorStep.DOCUMENT_COUNT]: 'Next', + [MockDataGeneratorStep.PREVIEW_DATA]: 'Generate Script', + [MockDataGeneratorStep.GENERATE_DATA]: 'Done', +} as const; diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/mock-data-generator-modal.spec.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/mock-data-generator-modal.spec.tsx new file mode 100644 index 00000000000..88d94c6e778 --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/mock-data-generator-modal.spec.tsx @@ -0,0 +1,92 @@ +import { expect } from 'chai'; +import React from 'react'; +import { render, screen } from '@mongodb-js/testing-library-compass'; +import Sinon from 'sinon'; +import MockDataGeneratorModal from './mock-data-generator-modal'; +import { MockDataGeneratorStep } from './types'; +import { StepButtonLabelMap } from './constants'; + +describe('MockDataGeneratorModal', () => { + const sandbox = Sinon.createSandbox(); + let onOpenChange: Sinon.SinonSpy; + + beforeEach(() => { + onOpenChange = sandbox.spy(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + function renderModal({ + isOpen = true, + currentStep = MockDataGeneratorStep.AI_DISCLAIMER, + } = {}) { + function MockDataGeneratorModalWrapper() { + const [currentStepStateMock, onCurrentStepChangeStateMock] = + React.useState(currentStep); + return ( + { + onCurrentStepChangeStateMock(step); + }} + /> + ); + } + return render(); + } + + it('renders the modal when isOpen is true', () => { + renderModal(); + + expect(screen.getByTestId('generate-mock-data-modal')).to.exist; + }); + + it('does not render the modal when isOpen is false', () => { + renderModal({ isOpen: false }); + + expect(screen.queryByTestId('generate-mock-data-modal')).to.not.exist; + }); + + it('calls onOpenChange(false) when the modal is closed', () => { + renderModal(); + + screen.getByLabelText('Close modal').click(); + + expect(onOpenChange.calledOnceWith(false)).to.be.true; + }); + + it('calls onOpenChange(false) when the cancel button is clicked', () => { + renderModal(); + + screen.getByText('Cancel').click(); + + expect(onOpenChange.calledOnceWith(false)).to.be.true; + }); + + it('disables the Back button on the first step', () => { + renderModal(); + + expect( + screen.getByRole('button', { name: 'Back' }).getAttribute('aria-disabled') + ).to.equal('true'); + }); + + describe('when rendering the modal in a specific step', () => { + const steps = Object.keys( + StepButtonLabelMap + ) as unknown as MockDataGeneratorStep[]; + + steps.forEach((currentStep) => { + it(`renders the button with the correct label when the user is in step "${currentStep}"`, () => { + renderModal({ currentStep }); + expect(screen.getByTestId('next-step-button')).to.have.text( + StepButtonLabelMap[currentStep] + ); + }); + }); + }); +}); diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/mock-data-generator-modal.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/mock-data-generator-modal.tsx new file mode 100644 index 00000000000..b7723530d61 --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/mock-data-generator-modal.tsx @@ -0,0 +1,91 @@ +import React from 'react'; + +import { + css, + ModalBody, + ModalHeader, + spacing, +} from '@mongodb-js/compass-components'; + +import { + Button, + Modal, + ModalFooter, + ButtonVariant, +} from '@mongodb-js/compass-components'; +import { MockDataGeneratorStep } from './types'; +import { StepButtonLabelMap } from './constants'; +import { getNextStep, getPreviousStep } from './utils'; + +const footerStyles = css` + flex-direction: row; + justify-content: space-between; +`; + +const rightButtonsStyles = css` + display: flex; + gap: ${spacing[200]}px; + flex-direction: row; +`; + +interface Props { + isOpen: boolean; + onOpenChange: (isOpen: boolean) => void; + currentStep: MockDataGeneratorStep; + onCurrentStepChange: (step: MockDataGeneratorStep) => void; +} + +const MockDataGeneratorModal = ({ + isOpen, + onOpenChange, + currentStep, + onCurrentStepChange, +}: Props) => { + const onNext = () => { + const nextStep = getNextStep(currentStep); + onCurrentStepChange(nextStep); + }; + + const onBack = () => { + const previousStep = getPreviousStep(currentStep); + onCurrentStepChange(previousStep); + }; + + const onCancel = () => { + onOpenChange(false); + }; + + return ( + onOpenChange(open)} + data-testid="generate-mock-data-modal" + > + + + {/* TODO: Render actual step content here based on currentStep. (CLOUDP-333851) */} +
+ + + +
+ + +
+
+ + ); +}; + +export default MockDataGeneratorModal; diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/types.ts b/packages/compass-collection/src/components/mock-data-generator-modal/types.ts new file mode 100644 index 00000000000..6394dc25e2d --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/types.ts @@ -0,0 +1,8 @@ +export enum MockDataGeneratorStep { + AI_DISCLAIMER = 'AI_DISCLAIMER', + SCHEMA_CONFIRMATION = 'SCHEMA_CONFIRMATION', + SCHEMA_EDITOR = 'SCHEMA_EDITOR', + DOCUMENT_COUNT = 'DOCUMENT_COUNT', + PREVIEW_DATA = 'PREVIEW_DATA', + GENERATE_DATA = 'GENERATE_DATA', +} diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/utils.spec.ts b/packages/compass-collection/src/components/mock-data-generator-modal/utils.spec.ts new file mode 100644 index 00000000000..239d3ed2d1e --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/utils.spec.ts @@ -0,0 +1,81 @@ +import { expect } from 'chai'; +import { getNextStep, getPreviousStep } from './utils'; +import { MockDataGeneratorStep } from './types'; + +describe('Mock Data Generator Modal Utils', () => { + describe('getNextStep', () => { + it('should go from AI_DISCLAIMER to SCHEMA_CONFIRMATION', () => { + expect(getNextStep(MockDataGeneratorStep.AI_DISCLAIMER)).to.equal( + MockDataGeneratorStep.SCHEMA_CONFIRMATION + ); + }); + + it('should go from SCHEMA_CONFIRMATION to SCHEMA_EDITOR', () => { + expect(getNextStep(MockDataGeneratorStep.SCHEMA_CONFIRMATION)).to.equal( + MockDataGeneratorStep.SCHEMA_EDITOR + ); + }); + + it('should go from SCHEMA_EDITOR to DOCUMENT_COUNT', () => { + expect(getNextStep(MockDataGeneratorStep.SCHEMA_EDITOR)).to.equal( + MockDataGeneratorStep.DOCUMENT_COUNT + ); + }); + + it('should go from DOCUMENT_COUNT to PREVIEW_DATA', () => { + expect(getNextStep(MockDataGeneratorStep.DOCUMENT_COUNT)).to.equal( + MockDataGeneratorStep.PREVIEW_DATA + ); + }); + + it('should go from PREVIEW_DATA to GENERATE_DATA', () => { + expect(getNextStep(MockDataGeneratorStep.PREVIEW_DATA)).to.equal( + MockDataGeneratorStep.GENERATE_DATA + ); + }); + + it('should stay on GENERATE_DATA if already at GENERATE_DATA', () => { + expect(getNextStep(MockDataGeneratorStep.GENERATE_DATA)).to.equal( + MockDataGeneratorStep.GENERATE_DATA + ); + }); + }); + + describe('getPreviousStep', () => { + it('should stay on AI_DISCLAIMER if already at AI_DISCLAIMER', () => { + expect(getPreviousStep(MockDataGeneratorStep.AI_DISCLAIMER)).to.equal( + MockDataGeneratorStep.AI_DISCLAIMER + ); + }); + + it('should go from SCHEMA_CONFIRMATION to AI_DISCLAIMER', () => { + expect( + getPreviousStep(MockDataGeneratorStep.SCHEMA_CONFIRMATION) + ).to.equal(MockDataGeneratorStep.AI_DISCLAIMER); + }); + + it('should go from SCHEMA_EDITOR to SCHEMA_CONFIRMATION', () => { + expect(getPreviousStep(MockDataGeneratorStep.SCHEMA_EDITOR)).to.equal( + MockDataGeneratorStep.SCHEMA_CONFIRMATION + ); + }); + + it('should go from DOCUMENT_COUNT to SCHEMA_EDITOR', () => { + expect(getPreviousStep(MockDataGeneratorStep.DOCUMENT_COUNT)).to.equal( + MockDataGeneratorStep.SCHEMA_EDITOR + ); + }); + + it('should go from PREVIEW_DATA to DOCUMENT_COUNT', () => { + expect(getPreviousStep(MockDataGeneratorStep.PREVIEW_DATA)).to.equal( + MockDataGeneratorStep.DOCUMENT_COUNT + ); + }); + + it('should go from GENERATE_DATA to PREVIEW_DATA', () => { + expect(getPreviousStep(MockDataGeneratorStep.GENERATE_DATA)).to.equal( + MockDataGeneratorStep.PREVIEW_DATA + ); + }); + }); +}); diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/utils.ts b/packages/compass-collection/src/components/mock-data-generator-modal/utils.ts new file mode 100644 index 00000000000..bc273c07dfc --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/utils.ts @@ -0,0 +1,41 @@ +import { MockDataGeneratorStep } from './types'; + +export const getNextStep = ( + currentStep: MockDataGeneratorStep +): MockDataGeneratorStep => { + switch (currentStep) { + case MockDataGeneratorStep.AI_DISCLAIMER: + return MockDataGeneratorStep.SCHEMA_CONFIRMATION; + case MockDataGeneratorStep.SCHEMA_CONFIRMATION: + return MockDataGeneratorStep.SCHEMA_EDITOR; + case MockDataGeneratorStep.SCHEMA_EDITOR: + return MockDataGeneratorStep.DOCUMENT_COUNT; + case MockDataGeneratorStep.DOCUMENT_COUNT: + return MockDataGeneratorStep.PREVIEW_DATA; + case MockDataGeneratorStep.PREVIEW_DATA: + return MockDataGeneratorStep.GENERATE_DATA; + case MockDataGeneratorStep.GENERATE_DATA: + // No next step after data generation + return currentStep; + } +}; + +export const getPreviousStep = ( + currentStep: MockDataGeneratorStep +): MockDataGeneratorStep => { + switch (currentStep) { + case MockDataGeneratorStep.AI_DISCLAIMER: + // No previous step from AI disclaimer + return currentStep; + case MockDataGeneratorStep.SCHEMA_CONFIRMATION: + return MockDataGeneratorStep.AI_DISCLAIMER; + case MockDataGeneratorStep.SCHEMA_EDITOR: + return MockDataGeneratorStep.SCHEMA_CONFIRMATION; + case MockDataGeneratorStep.DOCUMENT_COUNT: + return MockDataGeneratorStep.SCHEMA_EDITOR; + case MockDataGeneratorStep.PREVIEW_DATA: + return MockDataGeneratorStep.DOCUMENT_COUNT; + case MockDataGeneratorStep.GENERATE_DATA: + return MockDataGeneratorStep.PREVIEW_DATA; + } +};