diff --git a/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.spec.tsx b/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.spec.tsx index 3d0ed11e56f..164ad403081 100644 --- a/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.spec.tsx +++ b/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.spec.tsx @@ -1,4 +1,7 @@ -import { ATLAS_SEARCH_TEMPLATES } from '@mongodb-js/mongodb-constants'; +import { + ATLAS_SEARCH_TEMPLATES, + ATLAS_VECTOR_SEARCH_TEMPLATE, +} from '@mongodb-js/mongodb-constants'; import { expect } from 'chai'; import { BaseSearchIndexModal } from './base-search-index-modal'; import sinon from 'sinon'; @@ -7,7 +10,10 @@ import { render, screen, cleanup, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { getCodemirrorEditorValue } from '@mongodb-js/compass-editor'; +import { + getCodemirrorEditorValue, + setCodemirrorEditorValue, +} from '@mongodb-js/compass-editor'; function normalizedTemplateNamed(name: string) { const snippet = @@ -19,6 +25,20 @@ function normalizedTemplateNamed(name: string) { return snippet.replace(/\${\d+:([^}]+)}/gm, '$1'); } +const VALID_ATLAS_SEARCH_INDEX_DEFINITION = { + fields: [ + { + type: 'vector', + path: 'pineapple', + numDimensions: 1000, + similarity: 'cosine', + }, + ], +}; +const VALID_ATLAS_SEARCH_INDEX_DEFINITION_STRING = JSON.stringify( + VALID_ATLAS_SEARCH_INDEX_DEFINITION +); + function renderBaseSearchIndexModal( props?: Partial> ) { @@ -113,7 +133,7 @@ describe('Base Search Index Modal', function () { }); }); - it('submits the modal with the correct type on create search index', function () { + it('submits the modal with the correct type on create search index', async function () { userEvent.click( screen.getByTestId('search-index-type-vectorSearch-button'), undefined, @@ -122,15 +142,73 @@ describe('Base Search Index Modal', function () { skipPointerEventsCheck: true, } ); + await waitFor(() => { + const indexDef = getCodemirrorEditorValue( + 'definition-of-search-index' + ); + expect(indexDef).to.equal(ATLAS_VECTOR_SEARCH_TEMPLATE.snippet); + }); + + // Set the value to something where the create index button is enabled. + await setCodemirrorEditorValue( + 'definition-of-search-index', + VALID_ATLAS_SEARCH_INDEX_DEFINITION_STRING + ); userEvent.click( screen.getByRole('button', { name: 'Create Search Index' }) ); expect(onSubmitSpy).to.have.been.calledOnceWithExactly({ name: 'default', - definition: {}, + definition: VALID_ATLAS_SEARCH_INDEX_DEFINITION, type: 'vectorSearch', }); }); + + it('resets the template on type switch', async function () { + userEvent.click( + screen.getByTestId('search-index-type-vectorSearch-button'), + undefined, + { + // leafygreen adds pointer-events: none on actually clickable elements + skipPointerEventsCheck: true, + } + ); + + await waitFor(() => { + const indexDef = getCodemirrorEditorValue( + 'definition-of-search-index' + ); + expect(indexDef).to.equal(ATLAS_VECTOR_SEARCH_TEMPLATE.snippet); + }); + + userEvent.click( + screen.getByTestId('search-index-type-search-button'), + undefined, + { + // leafygreen adds pointer-events: none on actually clickable elements + skipPointerEventsCheck: true, + } + ); + + await waitFor(() => { + const indexDef = getCodemirrorEditorValue( + 'definition-of-search-index' + ); + expect(indexDef).to.equal( + normalizedTemplateNamed('Dynamic field mappings') + ); + }); + // Ensure the state is updated when the ace snippet changes. + await new Promise((resolve) => setTimeout(resolve, 10)); + userEvent.click( + screen.getByRole('button', { name: 'Create Search Index' }) + ); + expect(onSubmitSpy).to.have.been.calledOnceWithExactly({ + name: 'default', + definition: { mappings: { dynamic: true } }, + type: 'search', + }); + }); }); describe('templates', function () { diff --git a/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.tsx b/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.tsx index 53b46ab4e57..c0d38f6195b 100644 --- a/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.tsx +++ b/packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.tsx @@ -37,6 +37,7 @@ import type { Document } from 'mongodb'; import { useTrackOnChange } from '@mongodb-js/compass-logging/provider'; import { SearchIndexTemplateDropdown } from '../search-index-template-dropdown'; import { + ATLAS_SEARCH_TEMPLATES, ATLAS_VECTOR_SEARCH_TEMPLATE, type SearchTemplate, } from '@mongodb-js/mongodb-constants'; @@ -201,6 +202,7 @@ export const BaseSearchIndexModal: React.FunctionComponent< useEffect(() => { if (isModalOpen) { + setSearchIndexType('search'); setIndexName(initialIndexName); setIndexDefinition(initialIndexDefinition); setParsingError(undefined); @@ -261,12 +263,14 @@ export const BaseSearchIndexModal: React.FunctionComponent< // Set the template. if (value === 'vectorSearch') { + setIndexDefinition(ATLAS_VECTOR_SEARCH_TEMPLATE.snippet); onChangeTemplate(ATLAS_VECTOR_SEARCH_TEMPLATE); } else { - onSearchIndexDefinitionChanged(DEFAULT_INDEX_DEFINITION); + setIndexDefinition(ATLAS_SEARCH_TEMPLATES[0].snippet); + onChangeTemplate(ATLAS_SEARCH_TEMPLATES[0]); } }, - [setSearchIndexType, onChangeTemplate, onSearchIndexDefinitionChanged] + [setSearchIndexType, onChangeTemplate, setIndexDefinition] ); const fields = useAutocompleteFields(namespace); @@ -421,7 +425,7 @@ export const BaseSearchIndexModal: React.FunctionComponent< data-testid="search-index-submit-button" variant="primary" onClick={onSubmitIndex} - disabled={isBusy} + disabled={isBusy || !!parsingError} > {mode === 'create' ? 'Create Search Index' : 'Save'}