From ef3f8fd280952ae5913818ee8db143d76b68e8f6 Mon Sep 17 00:00:00 2001 From: Rhys Howell Date: Thu, 22 Feb 2024 11:38:10 -0500 Subject: [PATCH 1/3] reset atlas search index type and definition on reopen and type change --- .../base-search-index-modal.spec.tsx | 52 ++++++++++++++++++- .../base-search-index-modal.tsx | 6 ++- 2 files changed, 55 insertions(+), 3 deletions(-) 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..00838feaaa1 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'; @@ -19,6 +22,9 @@ function normalizedTemplateNamed(name: string) { return snippet.replace(/\${\d+:([^}]+)}/gm, '$1'); } +const NORMALIZED_ATLAS_VECTOR_SEARCH_TEMPLATE = + ATLAS_VECTOR_SEARCH_TEMPLATE.snippet.replace(/\${\d+:([^}]+)}/gm, '$1'); + function renderBaseSearchIndexModal( props?: Partial> ) { @@ -131,6 +137,50 @@ describe('Base Search Index Modal', function () { 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(NORMALIZED_ATLAS_VECTOR_SEARCH_TEMPLATE); + }); + + 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') + ); + }); + 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..2271ee423a1 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); @@ -263,10 +265,10 @@ export const BaseSearchIndexModal: React.FunctionComponent< if (value === 'vectorSearch') { onChangeTemplate(ATLAS_VECTOR_SEARCH_TEMPLATE); } else { - onSearchIndexDefinitionChanged(DEFAULT_INDEX_DEFINITION); + onChangeTemplate(ATLAS_SEARCH_TEMPLATES[0]); } }, - [setSearchIndexType, onChangeTemplate, onSearchIndexDefinitionChanged] + [setSearchIndexType, onChangeTemplate] ); const fields = useAutocompleteFields(namespace); From b437673c136a8f10dc2d60e7993728d775a8b522 Mon Sep 17 00:00:00 2001 From: Rhys Howell Date: Thu, 22 Feb 2024 13:22:30 -0500 Subject: [PATCH 2/3] fixup: disable button on parsing error, update tests for disabled race condition with invalid template --- .../base-search-index-modal.spec.tsx | 35 +++++++++++++++++-- .../base-search-index-modal.tsx | 2 +- 2 files changed, 33 insertions(+), 4 deletions(-) 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 00838feaaa1..5a9805392b1 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 @@ -10,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 = @@ -25,6 +28,20 @@ function normalizedTemplateNamed(name: string) { const NORMALIZED_ATLAS_VECTOR_SEARCH_TEMPLATE = ATLAS_VECTOR_SEARCH_TEMPLATE.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> ) { @@ -119,7 +136,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, @@ -128,12 +145,24 @@ describe('Base Search Index Modal', function () { skipPointerEventsCheck: true, } ); + await waitFor(() => { + const indexDef = getCodemirrorEditorValue( + 'definition-of-search-index' + ); + expect(indexDef).to.equal(NORMALIZED_ATLAS_VECTOR_SEARCH_TEMPLATE); + }); + + // 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', }); }); 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 2271ee423a1..327bd3a8e85 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 @@ -423,7 +423,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'} From dde6f4a2c9f2bb1ce630d6b475641b0881adc414 Mon Sep 17 00:00:00 2001 From: Rhys Howell Date: Thu, 22 Feb 2024 16:10:40 -0500 Subject: [PATCH 3/3] fixup: set snippet text for tests race --- .../base-search-index-modal.spec.tsx | 9 ++++----- .../search-indexes-modals/base-search-index-modal.tsx | 4 +++- 2 files changed, 7 insertions(+), 6 deletions(-) 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 5a9805392b1..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 @@ -25,9 +25,6 @@ function normalizedTemplateNamed(name: string) { return snippet.replace(/\${\d+:([^}]+)}/gm, '$1'); } -const NORMALIZED_ATLAS_VECTOR_SEARCH_TEMPLATE = - ATLAS_VECTOR_SEARCH_TEMPLATE.snippet.replace(/\${\d+:([^}]+)}/gm, '$1'); - const VALID_ATLAS_SEARCH_INDEX_DEFINITION = { fields: [ { @@ -149,7 +146,7 @@ describe('Base Search Index Modal', function () { const indexDef = getCodemirrorEditorValue( 'definition-of-search-index' ); - expect(indexDef).to.equal(NORMALIZED_ATLAS_VECTOR_SEARCH_TEMPLATE); + expect(indexDef).to.equal(ATLAS_VECTOR_SEARCH_TEMPLATE.snippet); }); // Set the value to something where the create index button is enabled. @@ -181,7 +178,7 @@ describe('Base Search Index Modal', function () { const indexDef = getCodemirrorEditorValue( 'definition-of-search-index' ); - expect(indexDef).to.equal(NORMALIZED_ATLAS_VECTOR_SEARCH_TEMPLATE); + expect(indexDef).to.equal(ATLAS_VECTOR_SEARCH_TEMPLATE.snippet); }); userEvent.click( @@ -201,6 +198,8 @@ describe('Base Search Index Modal', function () { 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' }) ); 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 327bd3a8e85..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 @@ -263,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 { + setIndexDefinition(ATLAS_SEARCH_TEMPLATES[0].snippet); onChangeTemplate(ATLAS_SEARCH_TEMPLATES[0]); } }, - [setSearchIndexType, onChangeTemplate] + [setSearchIndexType, onChangeTemplate, setIndexDefinition] ); const fields = useAutocompleteFields(namespace);