From f9b15e7c7d9df4a5a11494cac4bfadce94bf511f Mon Sep 17 00:00:00 2001 From: Carolyn McCawley Date: Thu, 16 Oct 2025 17:42:53 -0400 Subject: [PATCH 1/2] CLOUDP-349755: indexes banner --- .../src/components/indexes/indexes.spec.tsx | 149 ++++++++++++++++++ .../src/components/indexes/indexes.tsx | 37 ++++- 2 files changed, 185 insertions(+), 1 deletion(-) diff --git a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx index e26ed4d4f7d..f17f5a3532f 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx @@ -7,6 +7,7 @@ import { within, fireEvent, waitFor, + userEvent, } from '@mongodb-js/testing-library-compass'; import { expect } from 'chai'; import sinon from 'sinon'; @@ -20,6 +21,8 @@ import { setupStore } from '../../../test/setup-store'; import { searchIndexes } from '../../../test/fixtures/search-indexes'; import type { RootState } from '../../modules'; import type { Document } from 'mongodb'; +import { CompassExperimentationProvider } from '@mongodb-js/compass-telemetry'; +import { ExperimentTestGroup } from '@mongodb-js/compass-telemetry/provider'; const renderIndexes = async ( options: Partial = {}, @@ -430,4 +433,150 @@ describe('Indexes Component', function () { }); }); }); + + // @experiment Skills in Atlas | Jira Epic: CLOUDP-346311 + describe('Atlas Skills Banner', function () { + const renderIndexesWithExperimentation = async (experimentationOptions?: { + isInExperiment?: boolean; + isInVariant?: boolean; + }) => { + const mockUseAssignment = sinon.stub(); + const mockUseTrackInSample = sinon.stub(); + const mockAssignExperiment = sinon.stub(); + const mockGetAssignment = sinon.stub(); + + const commonAsyncStatus = { + asyncStatus: null, + error: null, + isLoading: false, + isError: false, + isSuccess: true, + }; + + if (experimentationOptions?.isInExperiment) { + if (experimentationOptions?.isInVariant) { + mockUseAssignment.returns({ + assignment: { + assignmentData: { + variant: ExperimentTestGroup.atlasSkillsVariant, + }, + }, + ...commonAsyncStatus, + }); + } else { + mockUseAssignment.returns({ + assignment: { + assignmentData: { + variant: ExperimentTestGroup.atlasSkillsControl, + }, + }, + ...commonAsyncStatus, + }); + } + } else { + mockUseAssignment.returns({ + assignment: null, + ...commonAsyncStatus, + }); + } + + mockUseTrackInSample.returns(commonAsyncStatus); + mockAssignExperiment.returns(Promise.resolve(null)); + mockGetAssignment.returns(Promise.resolve(null)); + + const store = setupStore({ isSearchIndexesSupported: true }, {}); + + await waitFor(() => { + expect(store.getState().regularIndexes.status).to.be.oneOf([ + 'READY', + 'ERROR', + ]); + expect(store.getState().searchIndexes.status).to.be.oneOf([ + 'READY', + 'ERROR', + ]); + }); + + render( + + + + + + ); + + return store; + }; + + it('should show skills banner when user is in experiment and in variant', async function () { + await renderIndexesWithExperimentation({ + isInExperiment: true, + isInVariant: true, + }); + + expect( + screen.getByText( + 'Design and apply indexes that make queries run faster.' + ) + ).to.be.visible; + + expect(screen.getByRole('link', { name: /go to skills/i })).to.be.visible; + expect(screen.getByLabelText('Award Icon')).to.be.visible; + }); + + it('should not show skills banner when user is in experiment but not in variant', async function () { + await renderIndexesWithExperimentation({ + isInExperiment: true, + isInVariant: false, + }); + + expect( + screen.queryByText( + 'Design and apply indexes that make queries run faster.' + ) + ).to.not.exist; + expect(screen.queryByRole('link', { name: /go to skills/i })).to.not + .exist; + }); + + it('should not show skills banner by default when user is not in experiment', async function () { + await renderIndexesWithExperimentation({ + isInExperiment: false, + isInVariant: false, + }); + + expect( + screen.queryByText( + 'Design and apply indexes that make queries run faster.' + ) + ).to.not.exist; + expect(screen.queryByRole('link', { name: /go to skills/i })).to.not + .exist; + }); + + it('should dismiss banner when close button is clicked', async function () { + await renderIndexesWithExperimentation({ + isInExperiment: true, + isInVariant: true, + }); + + const closeButton = screen.getByRole('button', { + name: 'Close Atlas Skills CTA', + }); + + expect(closeButton).to.be.visible; + userEvent.click(closeButton); + + expect( + screen.queryByText( + 'Design and apply indexes that make queries run faster.' + ) + ).to.not.exist; + }); + }); }); diff --git a/packages/compass-indexes/src/components/indexes/indexes.tsx b/packages/compass-indexes/src/components/indexes/indexes.tsx index 35395784230..77937fb297f 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.tsx @@ -9,8 +9,13 @@ import { usePersistedState, EmptyContent, Body, + AtlasSkillsBanner, } from '@mongodb-js/compass-components'; - +import { + useTelemetry, + SkillsBannerContextEnum, + useAtlasSkillsBanner, +} from '@mongodb-js/compass-telemetry/provider'; import IndexesToolbar from '../indexes-toolbar/indexes-toolbar'; import RegularIndexesTable from '../regular-indexes-table/regular-indexes-table'; import SearchIndexesTable from '../search-indexes-table/search-indexes-table'; @@ -55,6 +60,9 @@ const linkTitle = 'Search and Vector Search.'; const DISMISSED_SEARCH_INDEXES_BANNER_LOCAL_STORAGE_KEY = 'mongodb_compass_dismissedSearchIndexesBanner' as const; +const DISMISSED_ATLAS_INDEX_SKILL_BANNER_LOCAL_STORAGE_KEY = + 'mongodb_compass_dismissedAtlasIndexSkillBanner' as const; + const ViewVersionIncompatibleEmptyState = ({ serverVersion, enableAtlasSearchIndexes, @@ -195,11 +203,21 @@ export function Indexes({ serverVersion, collectionStats, }: IndexesProps) { + const track = useTelemetry(); const [atlasBannerDismissed, setDismissed] = usePersistedState( DISMISSED_SEARCH_INDEXES_BANNER_LOCAL_STORAGE_KEY, false ); + // @experiment Skills in Atlas | Jira Epic: CLOUDP-346311 + const [atlasSkillsBanner, setSkillDismissed] = usePersistedState( + DISMISSED_ATLAS_INDEX_SKILL_BANNER_LOCAL_STORAGE_KEY, + false + ); + const { shouldShowAtlasSkillsBanner } = useAtlasSkillsBanner( + SkillsBannerContextEnum.Indexes + ); + const errorMessage = currentIndexesView === 'regular-indexes' ? regularIndexes.error @@ -286,6 +304,23 @@ export function Indexes({ >
{getBanner()} + + { + setSkillDismissed(true); + track('Indexes Skill CTA Dismissed', { + context: 'Atlas Skills', + }); + }} + showBanner={shouldShowAtlasSkillsBanner && !atlasSkillsBanner} + onCtaClick={() => { + track('Indexes Skill CTA Clicked', { + context: 'Atlas Skills', + }); + }} + /> {!isReadonlyView && currentIndexesView === 'regular-indexes' && ( )} From 7844c83fcc72a46e757670223a9567b5af3b234d Mon Sep 17 00:00:00 2001 From: Carolyn McCawley Date: Fri, 17 Oct 2025 13:45:21 -0400 Subject: [PATCH 2/2] CLOUDP-349755: analytics update --- .../src/components/indexes/indexes.spec.tsx | 2 +- .../src/components/indexes/indexes.tsx | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx index f17f5a3532f..a88790dd483 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx @@ -566,7 +566,7 @@ describe('Indexes Component', function () { }); const closeButton = screen.getByRole('button', { - name: 'Close Atlas Skills CTA', + name: 'Dismiss Skills Banner', }); expect(closeButton).to.be.visible; diff --git a/packages/compass-indexes/src/components/indexes/indexes.tsx b/packages/compass-indexes/src/components/indexes/indexes.tsx index 77937fb297f..4e5bd1bfa51 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.tsx @@ -60,9 +60,6 @@ const linkTitle = 'Search and Vector Search.'; const DISMISSED_SEARCH_INDEXES_BANNER_LOCAL_STORAGE_KEY = 'mongodb_compass_dismissedSearchIndexesBanner' as const; -const DISMISSED_ATLAS_INDEX_SKILL_BANNER_LOCAL_STORAGE_KEY = - 'mongodb_compass_dismissedAtlasIndexSkillBanner' as const; - const ViewVersionIncompatibleEmptyState = ({ serverVersion, enableAtlasSearchIndexes, @@ -211,7 +208,7 @@ export function Indexes({ // @experiment Skills in Atlas | Jira Epic: CLOUDP-346311 const [atlasSkillsBanner, setSkillDismissed] = usePersistedState( - DISMISSED_ATLAS_INDEX_SKILL_BANNER_LOCAL_STORAGE_KEY, + 'mongodb_compass_dismissedAtlasIndexSkillBanner', false ); const { shouldShowAtlasSkillsBanner } = useAtlasSkillsBanner( @@ -310,14 +307,14 @@ export function Indexes({ skillsUrl="https://learn.mongodb.com/courses/indexing-design-fundamentals?team=growth" onCloseSkillsBanner={() => { setSkillDismissed(true); - track('Indexes Skill CTA Dismissed', { - context: 'Atlas Skills', + track('Atlas Skills CTA Dismissed', { + context: 'Indexes Tab', }); }} showBanner={shouldShowAtlasSkillsBanner && !atlasSkillsBanner} onCtaClick={() => { - track('Indexes Skill CTA Clicked', { - context: 'Atlas Skills', + track('Atlas Skills CTA Clicked', { + context: 'Indexes Tab', }); }} />