Skip to content

Commit 7ba6b3a

Browse files
authored
chore(compass-e2e-tests): Add tests for "Export aggregation" feature COMPASS-5822 (#3116)
* chore(compass-e2e-tests): Add tests for "Export aggregation" feature * chore(compass-e2e-tests): Relax error message check to cover different server versions * chore(compass-e2e-tests): Simplify regex even more
1 parent 051c97c commit 7ba6b3a

File tree

5 files changed

+104
-32
lines changed

5 files changed

+104
-32
lines changed

packages/compass-e2e-tests/helpers/commands/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ export * from './navigate-to-connect-tab';
3939
export * from './expand-connect-form-options';
4040
export * from './reset-connect-form';
4141
export * from './scroll-to-virtual-item';
42+
export * from './set-export-filename';
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import chai, { expect } from 'chai';
2+
import { promises as fs } from 'fs';
3+
import type { CompassBrowser } from '../compass-browser';
4+
import * as Selectors from '../selectors';
5+
import chaiAsPromised from 'chai-as-promised';
6+
7+
chai.use(chaiAsPromised);
8+
9+
export async function setExportFilename(
10+
browser: CompassBrowser,
11+
filename: string
12+
): Promise<void> {
13+
// make sure the file doesn't already exist
14+
await expect(fs.stat(filename)).to.be.rejected;
15+
16+
await browser.execute(function (f) {
17+
document.dispatchEvent(
18+
new CustomEvent('selectExportFileName', { detail: f })
19+
);
20+
}, filename);
21+
22+
await browser.waitUntil(async () => {
23+
const exportModalFileText = await browser.$(Selectors.ExportModalFileText);
24+
const value = await exportModalFileText.getValue();
25+
return value === filename;
26+
});
27+
}

packages/compass-e2e-tests/helpers/selectors.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,10 +625,14 @@ export const SavePipelineMenuContent = '[data-testid="save-menu-content"]';
625625
export const SavePipelineCreateViewAction =
626626
'[data-testid="save-menu-createView"]';
627627
export const SavePipelineSaveAsAction = '[data-testid="save-menu-saveAs"]';
628+
export const AggregationAutoPreviewToggle =
629+
'[data-testid="pipeline-toolbar-preview-toggle"]';
630+
export const AggregationErrorBanner = '[data-testid="pipeline-results-error"]';
628631

629632
export const RunPipelineButton = `[data-testid="pipeline-toolbar-run-button"]`;
630633
export const EditPipelineButton = `[data-testid="pipeline-toolbar-edit-button"]`;
631634
export const GoToCollectionButton = `[data-testid="pipeline-results-go-to-collection"]`;
635+
export const ExportAggregationResultsButton = `[data-testid="pipeline-toolbar-export-aggregation-button"]`;
632636

633637
// New Aggregation Toolbar Specific
634638
export const AggregationToolbarCreateMenu = '[data-testid="create-new-menu"]';

packages/compass-e2e-tests/tests/collection-aggregations-tab.test.ts

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import chai from 'chai';
22
import semver from 'semver';
33
import type { Element } from 'webdriverio';
4+
import { promises as fs } from 'fs';
45
import type { CompassBrowser } from '../helpers/compass-browser';
5-
import { beforeTests, afterTests, afterTest } from '../helpers/compass';
6+
import {
7+
beforeTests,
8+
afterTests,
9+
afterTest,
10+
outputFilename,
11+
} from '../helpers/compass';
612
import type { Compass } from '../helpers/compass';
713
import { MONGODB_VERSION } from '../helpers/compass';
814
import * as Selectors from '../helpers/selectors';
@@ -703,6 +709,64 @@ describe('Collection aggregations tab', function () {
703709
await emptyResultsBanner.waitForDisplayed();
704710
});
705711

712+
it('handles errors in aggregations', async function () {
713+
// Disable autopreview so we can run an aggregation that will cause an error
714+
await browser.clickVisible(Selectors.AggregationAutoPreviewToggle);
715+
716+
// Set first stage to an invalid $project stage to trigger server error
717+
await browser.focusStageOperator(0);
718+
await browser.selectStageOperator(0, '$project');
719+
await browser.setAceValue(Selectors.stageEditor(0), '{}');
720+
721+
// Run and wait for results
722+
await goToRunAggregation();
723+
724+
const errorBanner = await browser.$(Selectors.AggregationErrorBanner);
725+
await errorBanner.waitForDisplayed();
726+
const errorText = await errorBanner.getText();
727+
728+
expect(errorText).to.match(
729+
/(\$project )?specification must have at least one field/
730+
);
731+
});
732+
733+
it('supports exporting aggregation results', async function () {
734+
// Set first stage to $match
735+
await browser.focusStageOperator(0);
736+
await browser.selectStageOperator(0, '$match');
737+
await browser.setAceValue(Selectors.stageEditor(0), '{ i: 5 }');
738+
739+
// Open the modal
740+
await browser.clickVisible(Selectors.ExportAggregationResultsButton);
741+
const exportModal = await browser.$(Selectors.ExportModal);
742+
await exportModal.waitForDisplayed();
743+
744+
// Set filename
745+
const filename = outputFilename('aggregated-numbers.json');
746+
await browser.setExportFilename(filename);
747+
748+
// Start export and wait for results
749+
await browser.clickVisible(Selectors.ExportModalExportButton);
750+
const exportModalShowFileButtonElement = await browser.$(
751+
Selectors.ExportModalShowFileButton
752+
);
753+
await exportModalShowFileButtonElement.waitForDisplayed();
754+
755+
// Close modal
756+
await browser.clickVisible(Selectors.ExportModalCloseButton);
757+
const exportModalElement = await browser.$(Selectors.ExportModal);
758+
await exportModalElement.waitForDisplayed({ reverse: true });
759+
760+
// Confirm that we exported what we expected to export
761+
const text = await fs.readFile(filename, 'utf-8');
762+
const docs = JSON.parse(text);
763+
764+
expect(docs).to.have.lengthOf(1);
765+
expect(docs[0]).to.have.property('_id');
766+
expect(docs[0]).to.have.property('i', 5);
767+
expect(docs[0]).to.have.property('j', 0);
768+
});
769+
706770
// TODO: stages can be re-arranged by drag and drop and the preview is refreshed after rearranging them
707771
// TODO: test auto-preview and limit
708772
// TODO: save a pipeline, close compass, re-open compass, load the pipeline

packages/compass-e2e-tests/tests/collection-export.test.ts

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { promises as fs } from 'fs';
2-
import chai from 'chai';
3-
import chaiAsPromised from 'chai-as-promised';
2+
import { expect } from 'chai';
43
import type { CompassBrowser } from '../helpers/compass-browser';
54
import { startTelemetryServer } from '../helpers/telemetry';
65
import type { Telemetry } from '../helpers/telemetry';
@@ -14,10 +13,6 @@ import type { Compass } from '../helpers/compass';
1413
import * as Selectors from '../helpers/selectors';
1514
import { createNumbersCollection } from '../helpers/insert-data';
1615

17-
chai.use(chaiAsPromised);
18-
19-
const { expect } = chai;
20-
2116
async function selectExportFileTypeCSV(browser: CompassBrowser) {
2217
// select csv (unselected at first, selected by the end)
2318
await browser.clickVisible(
@@ -29,25 +24,6 @@ async function selectExportFileTypeCSV(browser: CompassBrowser) {
2924
await selectExportFileTypeButtonElement.waitForDisplayed();
3025
}
3126

32-
async function setExportFilename(browser: CompassBrowser, filename: string) {
33-
// make sure the file doesn't already exist
34-
await expect(fs.stat(filename)).to.be.rejected;
35-
36-
await browser.execute(function (f) {
37-
// eslint-disable-next-line no-undef
38-
document.dispatchEvent(
39-
// eslint-disable-next-line no-undef
40-
new CustomEvent('selectExportFileName', { detail: f })
41-
);
42-
}, filename);
43-
44-
await browser.waitUntil(async () => {
45-
const exportModalFileText = await browser.$(Selectors.ExportModalFileText);
46-
const value = await exportModalFileText.getValue();
47-
return value === filename;
48-
});
49-
}
50-
5127
describe('Collection export', function () {
5228
let compass: Compass;
5329
let browser: CompassBrowser;
@@ -103,7 +79,7 @@ describe('Collection export', function () {
10379
// select CSV
10480
await selectExportFileTypeCSV(browser);
10581
const filename = outputFilename('filtered-numbers.csv');
106-
await setExportFilename(browser, filename);
82+
await browser.setExportFilename(filename);
10783
await browser.clickVisible(Selectors.ExportModalExportButton);
10884

10985
// wait for it to finish
@@ -176,7 +152,7 @@ describe('Collection export', function () {
176152
// CSV file type
177153
await selectExportFileTypeCSV(browser);
178154
const filename = outputFilename('all-numbers.csv');
179-
await setExportFilename(browser, filename);
155+
await browser.setExportFilename(filename);
180156
await browser.clickVisible(Selectors.ExportModalExportButton);
181157

182158
// wait for it to finish, then close the modal
@@ -236,7 +212,7 @@ describe('Collection export', function () {
236212
// CSV file type
237213
await selectExportFileTypeCSV(browser);
238214
const filename = outputFilename('numbers-only.csv');
239-
await setExportFilename(browser, filename);
215+
await browser.setExportFilename(filename);
240216
await browser.clickVisible(Selectors.ExportModalExportButton);
241217

242218
// wait for it to finish
@@ -303,7 +279,7 @@ describe('Collection export', function () {
303279

304280
// leave the file type on the default (JSON)
305281
const filename = outputFilename('filtered-numbers.json');
306-
await setExportFilename(browser, filename);
282+
await browser.setExportFilename(filename);
307283
await browser.clickVisible(Selectors.ExportModalExportButton);
308284

309285
// wait for it to finish
@@ -374,7 +350,7 @@ describe('Collection export', function () {
374350

375351
// go with the default file type (JSON)
376352
const filename = outputFilename('all-numbers.json');
377-
await setExportFilename(browser, filename);
353+
await browser.setExportFilename(filename);
378354
await browser.clickVisible(Selectors.ExportModalExportButton);
379355

380356
// wait for it to finish, then close the modal
@@ -432,7 +408,7 @@ describe('Collection export', function () {
432408

433409
// go with the default file type (JSON)
434410
const filename = outputFilename('numbers-only.json');
435-
await setExportFilename(browser, filename);
411+
await browser.setExportFilename(filename);
436412
await browser.clickVisible(Selectors.ExportModalExportButton);
437413

438414
// wait for it to finish

0 commit comments

Comments
 (0)