Skip to content

Commit

Permalink
tests(search indexes): setup e2e search indexes test COMPASS-7171 (#4832
Browse files Browse the repository at this point in the history
)

Co-authored-by: Le Roux Bodenstein <[email protected]>
  • Loading branch information
mabaasit and lerouxb authored Sep 15, 2023
1 parent c9014c9 commit eeca40a
Show file tree
Hide file tree
Showing 9 changed files with 311 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .evergreen/functions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ variables:
EVERGREEN_BUCKET_NAME: mciuploads
EVERGREEN_BUCKET_KEY_PREFIX: ${project}/${revision}_${revision_order_id}
MONGODB_RUNNER_LOG_DIR: ${workdir}/src/.testserver/
E2E_TESTS_ATLAS_CS_WITHOUT_SEARCH: ${e2e_tests_atlas_cs_without_search}
E2E_TESTS_ATLAS_CS_WITH_SEARCH: ${e2e_tests_atlas_cs_with_search}

# This is here with the variables because anchors aren't supported across includes
post:
Expand Down
17 changes: 16 additions & 1 deletion packages/compass-e2e-tests/helpers/commands/create-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,22 @@ export async function createIndex(
const indexName = extraOptions?.indexName ?? `${fieldName}_${indexType}`;

// Open the modal
await browser.clickVisible(Selectors.CreateIndexButton);
const isWithCreateDropdown = await browser
.$(Selectors.CreateIndexDropdownButton)
.isExisting();
if (isWithCreateDropdown) {
await browser.waitUntil(async () => {
await browser.clickVisible(Selectors.CreateIndexDropdownButton);
return await browser
.$(Selectors.createIndexDropdownAction('regular-indexes'))
.isExisting();
});
await browser.clickVisible(
Selectors.createIndexDropdownAction('regular-indexes')
);
} else {
await browser.clickVisible(Selectors.CreateIndexButton);
}
const createModal = await browser.$(Selectors.CreateIndexModal);
await createModal.waitForDisplayed();

Expand Down
38 changes: 38 additions & 0 deletions packages/compass-e2e-tests/helpers/commands/create-search-index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { CompassBrowser } from '../compass-browser';
import * as Selectors from '../selectors';

export async function createSearchIndex(
browser: CompassBrowser,
indexName: string,
indexDefinition: string,
screenshotName?: string
): Promise<void> {
// Open modal using dropdown
await browser.clickVisible(Selectors.CreateIndexDropdownButton);
await browser
.$(Selectors.createIndexDropdownAction('search-indexes'))
.waitForDisplayed();
await browser.clickVisible(
Selectors.createIndexDropdownAction('search-indexes')
);

const createModal = await browser.$(Selectors.CreateSearchIndexModal);
await createModal.waitForDisplayed();

await browser.setValueVisible(Selectors.CreateSearchIndexName, indexName);

await browser.setCodemirrorEditorValue(
Selectors.CreateSearchIndexDefinition,
indexDefinition
);

if (screenshotName) {
await browser.screenshot(screenshotName);
}

// Create the index
await browser.clickVisible(Selectors.CreateSearchIndexConfirmButton);

// Assert that modal goes away
await createModal.waitForDisplayed({ reverse: true });
}
29 changes: 29 additions & 0 deletions packages/compass-e2e-tests/helpers/commands/drop-search-index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { CompassBrowser } from '../compass-browser';
import * as Selectors from '../selectors';

export async function dropSearchIndex(
browser: CompassBrowser,
indexName: string,
screenshotName?: string
) {
const indexRowSelector = Selectors.searchIndexRow(indexName);
const indexRow = await browser.$(indexRowSelector);
await indexRow.waitForDisplayed();

await browser.hover(indexRowSelector);
await browser.clickVisible(Selectors.searchIndexDropButton(indexName));

const dropModal = await browser.$(Selectors.ConfirmationModal);
await dropModal.waitForDisplayed();

const confirmInput = await browser.$(Selectors.ConfirmationModalInput);
await confirmInput.waitForDisplayed();
await confirmInput.setValue(indexName);

if (screenshotName) {
await browser.screenshot(screenshotName);
}

await browser.clickVisible(Selectors.ConfirmationModalConfirmButton());
await dropModal.waitForDisplayed({ reverse: true });
}
2 changes: 2 additions & 0 deletions packages/compass-e2e-tests/helpers/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,5 @@ export * from './create-index';
export * from './drop-index';
export * from './hide-index';
export * from './unhide-index';
export * from './create-search-index';
export * from './drop-search-index';
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ async function navigateToCollection(
const sidebarFilterInputElement = await browser.$(
Selectors.SidebarFilterInput
);
await sidebarFilterInputElement.clearValue();
await sidebarFilterInputElement.setValue(collectionName);
const collectionElement = await browser.$(collectionSelector);

Expand Down
28 changes: 28 additions & 0 deletions packages/compass-e2e-tests/helpers/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,7 @@ export const explainPlanSummaryStat = (
};

// Indexes tab
type IndexesType = 'regular-indexes' | 'search-indexes';
export const IndexList = '[data-testid="indexes-list"]';
export const indexComponent = (name: string): string => {
return `[data-testid="indexes-row-${name}"]`;
Expand All @@ -934,10 +935,35 @@ export const indexOptionInput = (
return `[data-testid="create-index-modal-${fieldName}-${type}"]`;
};

export const indexesSegmentedTab = (name: IndexesType) => {
return `[data-testid="indexes-segment-controls"] [data-testid="${name}-tab"] button`;
};

// Search Index
export const SearchIndexList = '[data-testid="search-indexes"]';
export const CreateSearchIndexModal =
'[data-testid="create-search-index-modal"]';
export const CreateSearchIndexName = '[data-testid="name-of-search-index"]';
export const CreateSearchIndexDefinition =
'[data-testid="definition-of-search-index"]';
export const CreateSearchIndexConfirmButton =
'[data-testid="create-search-index-button"]';
export const searchIndexRow = (name: string) =>
`[data-testid="search-indexes-row-${name}"]`;
export const searchIndexDropButton = (name: string) =>
`${searchIndexRow(name)} [data-testid="search-index-actions-drop-action"]`;

// Indexes modal
export const CreateIndexModal = '[data-testid="create-index-modal"]';
export const CreateIndexButton =
'[data-testid="open-create-index-modal-button"]';
export const CreateIndexDropdownButton =
'[data-testid="multiple-index-types-creation-dropdown-show-actions"]';
export const createIndexDropdownAction = (type: IndexesType) => {
const action =
type === 'regular-indexes' ? 'createRegularIndex' : 'createSearchIndex';
return `[data-testid="multiple-index-types-creation-dropdown-${action}-action"]`;
};
export const createIndexModalFieldNameSelectInput = (idx: number): string => {
return `[data-testid="create-index-fields-name-${idx}"] input`;
};
Expand Down Expand Up @@ -1090,6 +1116,8 @@ export const ExportToLanguageQueryOutput =

// Confirmation modal
export const ConfirmationModal = '[data-testid="confirmation-modal"]';
export const ConfirmationModalInput =
'[data-testid="confirmation-modal"] input';
export const ConfirmationModalConfirmButton = (
modalSelector = ConfirmationModal
) => `${modalSelector} [role=dialog] button:nth-of-type(1)`;
Expand Down
185 changes: 185 additions & 0 deletions packages/compass-e2e-tests/tests/search-indexes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import type { CompassBrowser } from '../helpers/compass-browser';
import {
beforeTests,
afterTests,
afterTest,
MONGODB_TEST_SERVER_PORT,
Selectors,
serverSatisfies,
} from '../helpers/compass';
import type { Compass } from '../helpers/compass';
import { disconnect } from '../helpers/commands';
import { expect } from 'chai';
import { type Db, MongoClient } from 'mongodb';

type Connection = {
name: string;
connectionString?: string;
};

const connectionsWithNoSearchSupport: Connection[] = [
{
name: 'Local Connection',
connectionString: `mongodb://localhost:${MONGODB_TEST_SERVER_PORT}/test`,
},
{
name: 'Atlas Free Cluster',
connectionString: process.env.E2E_TESTS_ATLAS_CS_WITHOUT_SEARCH,
},
];
const connectionsWithSearchSupport: Connection[] = [
{
name: 'Atlas Dedicated Cluster',
connectionString: process.env.E2E_TESTS_ATLAS_CS_WITH_SEARCH,
},
// todo: atlas local dev
];

const INDEX_DEFINITION = JSON.stringify({
mappings: {
dynamic: true,
},
});

function getRandomNumber() {
return Math.floor(Math.random() * 2 ** 20);
}

describe('Search Indexes', function () {
let compass: Compass;
let browser: CompassBrowser;
let mongoClient: MongoClient;
let dbInstance: Db;
let currentConnectionString: string;

// DB name is always same.
const DB_NAME = 'e2e_indexes_test';
// Collection name is random per every test.
let collectionName: string;

before(async function () {
// $search works with server 4.2 or more
if (!serverSatisfies('>= 4.1.11')) {
this.skip();
}
compass = await beforeTests({
extraSpawnArgs: ['--enableAtlasSearchIndexManagement'],
});
browser = compass.browser;
});

after(async function () {
await afterTests(compass, this.currentTest);
});

beforeEach(async function () {
collectionName = `e2e_coll_numbers_${getRandomNumber()}`;
// Ensure namespace exists
{
mongoClient = new MongoClient(currentConnectionString);
await mongoClient.connect();
dbInstance = mongoClient.db(DB_NAME);

// Try to delete a namespace if it exists
try {
await dbInstance.dropCollection(collectionName);
} catch (e) {
// noop
}

// Create a namespace
await dbInstance.createCollection(collectionName);
}

await browser.connectWithConnectionString(currentConnectionString);
await browser.navigateToCollectionTab(DB_NAME, collectionName, 'Indexes');
});

afterEach(async function () {
// Drop the collection
{
try {
await dbInstance.dropCollection(collectionName);
} catch (e) {
console.log(`Failed to drop collection: ${DB_NAME}.${collectionName}`);
}
}
void mongoClient.close();
await disconnect(browser);
await afterTest(compass, this.currentTest);
});

for (const { name, connectionString } of connectionsWithNoSearchSupport) {
context(`does not support search indexes in ${name}`, function () {
before(function () {
if (!connectionString) {
return this.skip();
}
currentConnectionString = connectionString;
});

it('allows users to create a regular index', async function () {
const indexName = await browser.createIndex({
fieldName: 'e2e_tests_index',
indexType: 'text',
});
await browser.dropIndex(indexName);
});

it('renders search indexes tab disabled', async function () {
const searchTab = await browser.$(
Selectors.indexesSegmentedTab('search-indexes')
);
const isTabClickable = await searchTab.isClickable();
expect(isTabClickable).to.be.false;
});
});
}

for (const { name, connectionString } of connectionsWithSearchSupport) {
context(`supports search indexes in ${name}`, function () {
before(function () {
if (!connectionString) {
return this.skip();
}
currentConnectionString = connectionString;
});

it('allows users to create a regular indexes', async function () {
await browser.clickVisible(
Selectors.indexesSegmentedTab('regular-indexes')
);
const indexName = await browser.createIndex({
fieldName: 'e2e_tests_index',
indexType: 'text',
});
await browser.dropIndex(indexName);
});

it('allows users to create, view and drop search indexes', async function () {
const indexName = `e2e_search_index_${getRandomNumber()}`;
await browser.clickVisible(
Selectors.indexesSegmentedTab('search-indexes')
);
await browser.createSearchIndex(indexName, INDEX_DEFINITION);
await browser.waitForAnimations(Selectors.SearchIndexList);

const rowSelector = Selectors.searchIndexRow(indexName);

// View it
await browser.$(rowSelector).waitForDisplayed();
await browser.waitUntil(async function () {
const text = await browser.$(rowSelector).getText();
return text.indexOf('PENDING') > -1;
});

// Drop it
await browser.dropSearchIndex(indexName);
// todo: check the index status to be either DELETING or the row disappears
});

it('allows users to update and view search indexes');
it('runs a search aggregation with index name');
});
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,12 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
className={alignSelfEndStyles}
label="Viewing"
defaultValue="regular-indexes"
data-testid="indexes-segment-controls"
>
<SegmentedControlOption value="regular-indexes">
<SegmentedControlOption
data-testid="regular-indexes-tab"
value="regular-indexes"
>
Indexes
</SegmentedControlOption>
{!isAtlasSearchSupported && (
Expand All @@ -177,6 +181,7 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
trigger={({ children, ...props }) => (
<SegmentedControlOption
{...props}
data-testid="search-indexes-tab"
value="search-indexes"
disabled={true}
>
Expand All @@ -189,7 +194,10 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
</Tooltip>
)}
{isAtlasSearchSupported && (
<SegmentedControlOption value="search-indexes">
<SegmentedControlOption
data-testid="search-indexes-tab"
value="search-indexes"
>
Search Indexes
</SegmentedControlOption>
)}
Expand Down

0 comments on commit eeca40a

Please sign in to comment.