Skip to content

Commit fd085b6

Browse files
add tests
1 parent 80ba891 commit fd085b6

File tree

11 files changed

+260
-77
lines changed

11 files changed

+260
-77
lines changed

packages/compass-aggregations/src/modules/search-indexes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export const fetchIndexes = (
9090
searchIndexes: { status },
9191
} = getState();
9292

93-
const namespace = viewNamespace || collectionNamespace; // fetch indexes for view if passed in
93+
const namespace = viewNamespace || collectionNamespace;
9494

9595
if (
9696
!dataService ||

packages/compass-aggregations/src/modules/update-view.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import {
1010
} from '@mongodb-js/compass-connections/provider';
1111
import { createDefaultConnectionInfo } from '@mongodb-js/testing-library-compass';
1212

13+
// Importing this to stub showConfirmation
14+
import * as updateViewSlice from './update-view';
15+
1316
const TEST_CONNECTION_INFO = { ...createDefaultConnectionInfo(), title: '' };
1417

1518
describe('update-view module', function () {
@@ -48,15 +51,18 @@ describe('update-view module', function () {
4851
let stateMock: any;
4952
let getStateMock: () => any;
5053
let updateCollectionFake = sinon.fake();
54+
let showConfirmationStub: sinon.SinonStub;
5155

5256
beforeEach(async function () {
5357
dispatchFake = sinon.fake();
5458
updateCollectionFake = sinon.fake.resolves(undefined);
59+
showConfirmationStub = sinon.stub(updateViewSlice, 'showConfirmation');
5560
stateMock = {
5661
pipelineBuilder: { pipelineMode: 'builder-ui' },
5762
focusMode: { isEnabled: false },
5863
namespace: 'aa.bb',
5964
editViewName: 'aa.bb',
65+
searchIndexes: { indexes: [{ name: 'index1' }] },
6066
dataService: {
6167
dataService: {
6268
updateCollection: updateCollectionFake,
@@ -69,12 +75,39 @@ describe('update-view module', function () {
6975
await runUpdateView(dispatchFake, getStateMock, thunkArg as any);
7076
});
7177

78+
afterEach(function () {
79+
showConfirmationStub.restore();
80+
});
81+
7282
it('first it calls to dismiss any existing error', function () {
7383
expect(dispatchFake.firstCall.args[0]).to.deep.equal({
7484
type: 'aggregations/update-view/DISMISS_VIEW_UPDATE_ERROR',
7585
});
7686
});
7787

88+
it('shows confirmation banner when search indexes are present', async function () {
89+
showConfirmationStub.resolves(true);
90+
91+
const runUpdateView = updateView();
92+
await runUpdateView(dispatchFake, getStateMock, thunkArg as any);
93+
94+
expect(showConfirmationStub.calledOnce).to.be.true;
95+
expect(showConfirmationStub.firstCall.args[0]).to.deep.include({
96+
title: `Are you sure you want to update the view?`,
97+
buttonText: 'Update',
98+
});
99+
});
100+
101+
it('does not update view if not confirmed', async function () {
102+
getStateMock = () => stateMock;
103+
showConfirmationStub.resolves(false);
104+
105+
const runUpdateView = updateView();
106+
await runUpdateView(dispatchFake, getStateMock, thunkArg as any);
107+
108+
expect(updateCollectionFake.calledOnce).to.be.false;
109+
});
110+
78111
it('calls the data service to update the view for the provided ns', function () {
79112
expect(updateCollectionFake.firstCall.args[0]).to.equal('aa.bb');
80113
expect(updateCollectionFake.firstCall.args[1]).to.deep.equal({

packages/compass-aggregations/src/modules/update-view.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import type { PipelineBuilderThunkAction } from '.';
99
import { isAction } from '../utils/is-action';
1010
import type { AnyAction } from 'redux';
11-
import { showConfirmation } from '@mongodb-js/compass-components';
11+
import { showConfirmation as showConfirmationModal } from '@mongodb-js/compass-components';
1212
import { fetchIndexes } from './search-indexes';
1313
import { isPipelineSearchQueryable } from 'mongodb-compass/src/app/utils/view-search-queryable';
1414

@@ -76,6 +76,8 @@ export const dismissViewError = (): DismissViewUpdateErrorAction => ({
7676
type: DISMISS_VIEW_UPDATE_ERROR,
7777
});
7878

79+
//Exporting this for test only to stub it and set its value
80+
export const showConfirmation = showConfirmationModal;
7981
/**
8082
* Updates a view.
8183
*

packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.spec.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { IndexesToolbar } from './indexes-toolbar';
1313
import type { PreferencesAccess } from 'compass-preferences-model';
1414
import { createSandboxFromDefaultPreferences } from 'compass-preferences-model';
1515
import { PreferencesProvider } from 'compass-preferences-model/provider';
16+
import type { Document } from 'mongodb';
17+
//import type {Document} from "mongodb";
1618

1719
describe('IndexesToolbar Component', function () {
1820
before(cleanup);
@@ -153,10 +155,34 @@ describe('IndexesToolbar Component', function () {
153155
expect(screen.getByText('Create Search Index')).to.be.visible;
154156
});
155157

156-
it('should not render the refresh button', function () {
158+
it('should render the refresh button', function () {
157159
expect(screen.queryByText('Refresh')).to.be.visible;
158160
});
159161
});
162+
163+
describe('and pipeline is not queryable', function () {
164+
it('should disable the create search index button', function () {
165+
const pipelineMock: Document[] = [
166+
{ $project: { newField: 'testValue' } },
167+
];
168+
const mockCollectionStats = { pipeline: pipelineMock };
169+
170+
renderIndexesToolbar({
171+
isReadonlyView: true,
172+
serverVersion: '8.1.0',
173+
indexView: 'search-indexes',
174+
collectionStats: mockCollectionStats,
175+
});
176+
177+
expect(screen.getByText('Create Search Index')).to.be.visible;
178+
expect(
179+
screen
180+
.getByText('Create Search Index')
181+
.closest('button')
182+
?.getAttribute('aria-disabled')
183+
).to.equal('true');
184+
});
185+
});
160186
});
161187

162188
describe('when it is preferences ReadOnly', function () {

packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { getAtlasSearchIndexesLink } from '../../utils/atlas-search-indexes-link
3131
import { createIndexOpened } from '../../modules/create-index';
3232
import type { IndexView } from '../../modules/index-view';
3333
import { indexViewChanged } from '../../modules/index-view';
34-
import { CollectionStats } from '../../modules/collection-stats';
34+
import type { CollectionStats } from '../../modules/collection-stats';
3535
import { isPipelineSearchQueryable } from 'mongodb-compass/src/app/utils/view-search-queryable';
3636

3737
const toolbarButtonsContainer = css({
@@ -129,9 +129,7 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
129129
const isViewPipelineSearchQueryable =
130130
(isReadonlyView &&
131131
collectionStats?.pipeline &&
132-
isPipelineSearchQueryable(
133-
collectionStats.pipeline as Array<Record<string, any>>
134-
)) ??
132+
isPipelineSearchQueryable(collectionStats.pipeline as Document[])) ??
135133
true;
136134
const pipelineNotSearchQueryableDescription =
137135
'Search indexes can only be created on views containing $addFields, $set or $match stages with the $expr operator.';

packages/compass-indexes/src/components/indexes/indexes.spec.tsx

Lines changed: 93 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import Indexes from './indexes';
1919
import { setupStore } from '../../../test/setup-store';
2020
import { searchIndexes } from '../../../test/fixtures/search-indexes';
2121
import type { RootState } from '../../modules';
22+
import type { Document } from 'mongodb';
2223

2324
const renderIndexes = async (
2425
options: Partial<IndexesPluginOptions> = {},
@@ -321,75 +322,108 @@ describe('Indexes Component', function () {
321322
expect(getSearchIndexesStub.callCount).to.equal(2);
322323
});
323324

324-
it('renders search indexes list if isReadonlyView 8.1+ and has indexes', async function () {
325-
const getSearchIndexesStub = sinon.stub().resolves(searchIndexes);
326-
const dataProvider = {
327-
getSearchIndexes: getSearchIndexesStub,
328-
};
329-
await renderIndexes(undefined, dataProvider, {
330-
indexView: 'search-indexes',
331-
isReadonlyView: true,
332-
serverVersion: '8.1.0',
333-
});
325+
describe('when isReadonly view', function () {
326+
it('renders ViewVersionIncompatibleBanner if view version is <8.0', async function () {
327+
await renderIndexes(undefined, undefined, {
328+
isReadonlyView: true,
329+
serverVersion: '8.0.0',
330+
indexView: 'search-indexes',
331+
});
334332

335-
await waitFor(() => {
336-
expect(screen.getByTestId('search-indexes-list')).to.exist;
333+
expect(screen.getByTestId('view-version-incompatible-banner')).to.exist;
337334
});
338-
});
339335

340-
it('renders correct empty state if isReadonlyView 8.1+ and has no indexes', async function () {
341-
const getSearchIndexesStub = sinon.stub().resolves([]);
342-
const dataProvider = {
343-
getSearchIndexes: getSearchIndexesStub,
344-
};
345-
await renderIndexes(undefined, dataProvider, {
346-
indexView: 'search-indexes',
347-
isReadonlyView: true,
348-
serverVersion: '8.1.0',
336+
it('renders ViewNotSearchCompatibleBanner if view pipeline is not queryable', async function () {
337+
const pipelineMock: Document[] = [
338+
{ $project: { newField: 'testValue' } },
339+
];
340+
const mockCollectionStats = {
341+
index_count: 0,
342+
index_size: 0,
343+
pipeline: pipelineMock,
344+
};
345+
await renderIndexes(undefined, undefined, {
346+
isReadonlyView: true,
347+
serverVersion: '8.1.0',
348+
indexView: 'search-indexes',
349+
collectionStats: mockCollectionStats,
350+
});
351+
352+
expect(
353+
screen.getByTestId('view-not-search-compatible-banner')
354+
).to.exist;
349355
});
350356

351-
expect(screen.getByText('No search indexes yet')).to.be.visible;
352-
expect(screen.getByText('Create Atlas Search Index')).to.be.visible;
353-
});
354-
355-
it('renders correct empty state if isReadonlyView 8.0 and has no indexes', async function () {
356-
const getSearchIndexesStub = sinon.stub().resolves([]);
357-
const dataProvider = {
358-
getSearchIndexes: getSearchIndexesStub,
359-
};
360-
await renderIndexes(undefined, dataProvider, {
361-
indexView: 'search-indexes',
362-
isReadonlyView: true,
363-
serverVersion: '8.0.0',
357+
it('renders search indexes list if 8.1+ and has indexes', async function () {
358+
const getSearchIndexesStub = sinon.stub().resolves(searchIndexes);
359+
const dataProvider = {
360+
getSearchIndexes: getSearchIndexesStub,
361+
};
362+
await renderIndexes(undefined, dataProvider, {
363+
indexView: 'search-indexes',
364+
isReadonlyView: true,
365+
serverVersion: '8.1.0',
366+
});
367+
368+
await waitFor(() => {
369+
expect(screen.getByTestId('search-indexes-list')).to.exist;
370+
});
364371
});
365372

366-
expect(
367-
screen.queryByText(
368-
/Upgrade your cluster or manage search indexes on views in the Atlas UI./i
369-
)
370-
).to.exist;
371-
expect(screen.queryByText('No standard indexes')).to.exist;
372-
expect(screen.queryByText('Create Atlas Search Index')).to.not.exist;
373-
});
373+
it('renders correct empty state if 8.1+ and has no indexes', async function () {
374+
const getSearchIndexesStub = sinon.stub().resolves([]);
375+
const dataProvider = {
376+
getSearchIndexes: getSearchIndexesStub,
377+
};
378+
await renderIndexes(undefined, dataProvider, {
379+
indexView: 'search-indexes',
380+
isReadonlyView: true,
381+
serverVersion: '8.1.0',
382+
});
383+
384+
expect(screen.getByText('No search indexes yet')).to.be.visible;
385+
expect(screen.getByText('Create Atlas Search Index')).to.be.visible;
386+
});
374387

375-
it('renders correct empty state if isReadonlyView <8.0 and has no indexes', async function () {
376-
const getSearchIndexesStub = sinon.stub().resolves([]);
377-
const dataProvider = {
378-
getSearchIndexes: getSearchIndexesStub,
379-
};
380-
await renderIndexes(undefined, dataProvider, {
381-
indexView: 'search-indexes',
382-
isReadonlyView: true,
383-
serverVersion: '7.0.0',
388+
it('renders correct empty state if 8.0 and has no indexes', async function () {
389+
const getSearchIndexesStub = sinon.stub().resolves([]);
390+
const dataProvider = {
391+
getSearchIndexes: getSearchIndexesStub,
392+
};
393+
await renderIndexes(undefined, dataProvider, {
394+
indexView: 'search-indexes',
395+
isReadonlyView: true,
396+
serverVersion: '8.0.0',
397+
});
398+
399+
expect(
400+
screen.queryByText(
401+
/Upgrade your cluster or manage search indexes on views in the Atlas UI./i
402+
)
403+
).to.exist;
404+
expect(screen.queryByText('No standard indexes')).to.exist;
405+
expect(screen.queryByText('Create Atlas Search Index')).to.not.exist;
384406
});
385407

386-
expect(
387-
screen.queryByText(
388-
/Upgrade your cluster to create search indexes on views./i
389-
)
390-
).to.exist;
391-
expect(screen.queryByText('No standard indexes')).to.exist;
392-
expect(screen.queryByText('Create Atlas Search Index')).to.not.exist;
408+
it('renders correct empty state if <8.0 and has no indexes', async function () {
409+
const getSearchIndexesStub = sinon.stub().resolves([]);
410+
const dataProvider = {
411+
getSearchIndexes: getSearchIndexesStub,
412+
};
413+
await renderIndexes(undefined, dataProvider, {
414+
indexView: 'search-indexes',
415+
isReadonlyView: true,
416+
serverVersion: '7.0.0',
417+
});
418+
419+
expect(
420+
screen.queryByText(
421+
/Upgrade your cluster to create search indexes on views./i
422+
)
423+
).to.exist;
424+
expect(screen.queryByText('No standard indexes')).to.exist;
425+
expect(screen.queryByText('Create Atlas Search Index')).to.not.exist;
426+
});
393427
});
394428
});
395429
});

packages/compass-indexes/src/components/indexes/indexes.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ const ViewNotSearchCompatibleBanner = ({
114114
const variant =
115115
hasNoSearchIndexes || !enableAtlasSearchIndexes ? 'warning' : 'danger';
116116
return (
117-
<Banner variant={variant}>
117+
<Banner variant={variant} data-testid="view-not-search-compatible-banner">
118118
{!enableAtlasSearchIndexes && (
119119
<>
120120
<b>Looking for search indexes?</b> <br />
@@ -234,9 +234,7 @@ export function Indexes({
234234
const isViewPipelineSearchQueryable =
235235
(isReadonlyView &&
236236
collectionStats?.pipeline &&
237-
isPipelineSearchQueryable(
238-
collectionStats.pipeline as Array<Record<string, any>>
239-
)) ??
237+
isPipelineSearchQueryable(collectionStats.pipeline as Document[])) ??
240238
true;
241239

242240
const getBanner = () => {

packages/compass-indexes/src/components/search-indexes-table/search-indexes-table.spec.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,26 @@ describe('SearchIndexesTable Component', function () {
128128
expect(openCreateSpy.callCount).to.equal(1);
129129
});
130130

131+
it('renders the zero state with button disabled if there are no indexes and isReadOnlyView with non searchable pipeline', function () {
132+
const pipelineMock: Document[] = [{ $project: { newField: 'testValue' } }];
133+
const mockCollectionStats = { pipeline: pipelineMock };
134+
renderIndexList({
135+
indexes: [],
136+
isReadonlyView: true,
137+
collectionStats: mockCollectionStats,
138+
});
139+
140+
expect(() => {
141+
screen.getByTestId('search-indexes-list');
142+
}).to.throw;
143+
144+
const button = screen.getByTestId('create-atlas-search-index-button');
145+
expect(button).to.exist;
146+
expect(button.closest('button')?.getAttribute('aria-disabled')).to.equal(
147+
'true'
148+
);
149+
});
150+
131151
context('renders list with action', function () {
132152
it('renders drop action and shows modal when clicked', function () {
133153
const onDropIndexSpy = sinon.spy();

packages/compass-indexes/src/components/view-version-incompatible-banners/view-version-incompatible-banners.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ export const ViewVersionIncompatibleBanner = ({
4343
? 'Upgrade your cluster or manage search indexes on views in the Atlas UI.'
4444
: 'Upgrade your cluster to create search indexes on views.';
4545
return (
46-
<Banner variant={BannerVariant.Warning}>
46+
<Banner
47+
variant={BannerVariant.Warning}
48+
data-testid="view-version-incompatible-banner"
49+
>
4750
<b>Looking for search indexes?</b>
4851
<br />
4952
<div className={viewContentStyles}>

0 commit comments

Comments
 (0)