diff --git a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx index e26ed4d4f7d..a88790dd483 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: 'Dismiss Skills Banner', + }); + + 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..4e5bd1bfa51 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'; @@ -195,11 +200,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( + 'mongodb_compass_dismissedAtlasIndexSkillBanner', + false + ); + const { shouldShowAtlasSkillsBanner } = useAtlasSkillsBanner( + SkillsBannerContextEnum.Indexes + ); + const errorMessage = currentIndexesView === 'regular-indexes' ? regularIndexes.error @@ -286,6 +301,23 @@ export function Indexes({ >
{getBanner()} + + { + setSkillDismissed(true); + track('Atlas Skills CTA Dismissed', { + context: 'Indexes Tab', + }); + }} + showBanner={shouldShowAtlasSkillsBanner && !atlasSkillsBanner} + onCtaClick={() => { + track('Atlas Skills CTA Clicked', { + context: 'Indexes Tab', + }); + }} + /> {!isReadonlyView && currentIndexesView === 'regular-indexes' && ( )}