From a2bd0bacdbc2c1b2df6a8954cff7cc30230e5902 Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Tue, 21 Nov 2023 14:09:20 +0000 Subject: [PATCH] chore(e2e): add bulk update E2E test (#5139) * add bulk update E2E test * add a test for update favourite queries --- .../src/components/bulk-update-dialog.tsx | 23 ++- .../compass-e2e-tests/helpers/selectors.ts | 16 ++ .../tests/collection-bulk-update.test.ts | 188 ++++++++++++++++++ 3 files changed, 222 insertions(+), 5 deletions(-) create mode 100644 packages/compass-e2e-tests/tests/collection-bulk-update.test.ts diff --git a/packages/compass-crud/src/components/bulk-update-dialog.tsx b/packages/compass-crud/src/components/bulk-update-dialog.tsx index 21af1fedeba..dbd3b910c81 100644 --- a/packages/compass-crud/src/components/bulk-update-dialog.tsx +++ b/packages/compass-crud/src/components/bulk-update-dialog.tsx @@ -294,8 +294,16 @@ export default function BulkUpdateDialog({ }, [isOpen, wasOpen, updateText]); return ( - - + +
@@ -355,7 +363,7 @@ export default function BulkUpdateDialog({ Preview{' '} (sample of {preview.changes.length} document - {preview.changes.length !== 1 && 's'}) + {preview.changes.length === 1 ? '' : 's'})
@@ -377,15 +385,20 @@ export default function BulkUpdateDialog({
-
diff --git a/packages/compass-e2e-tests/helpers/selectors.ts b/packages/compass-e2e-tests/helpers/selectors.ts index 461275c20ee..d91797dc260 100644 --- a/packages/compass-e2e-tests/helpers/selectors.ts +++ b/packages/compass-e2e-tests/helpers/selectors.ts @@ -533,6 +533,7 @@ export const ConfirmDeleteDocumentButton = `${DocumentFooter} [data-testid="dele export const JSONDocumentCard = '[data-testid="editable-json"]'; export const JSONEditDocumentButton = `${JSONDocumentCard} [data-testid="editor-action-Edit"]`; export const ShowMoreFieldsButton = '[data-testid="show-more-fields-button"]'; +export const OpenBulkUpdateButton = '[data-testid="crud-update"]'; // Insert Document modal @@ -586,6 +587,18 @@ export const importPreviewFieldHeaderCheckbox = (fieldName: string): string => { return `[data-testid="preview-field-header-${fieldName}"] [data-testid="toggle-import-field-checkbox-${fieldName}"]`; }; +// Bulk Update Modal +export const BulkUpdateModal = '[data-testid="bulk-update-dialog"]'; +export const BulkUpdateReadonlyFilter = `${BulkUpdateModal} [data-testid="readonly-filter"]`; +export const BulkUpdateUpdate = `${BulkUpdateModal} [data-testid="bulk-update-update"]`; +export const BulkUpdateTitle = `${BulkUpdateModal} [data-testid="modal-title"]`; +export const BulkUpdateUpdateButton = `${BulkUpdateModal} [data-testid="update-button"]`; +export const BulkUpdateCancelButton = `${BulkUpdateModal} [data-testid="cancel-button"]`; +export const BulkUpdatePreviewDocument = `${BulkUpdateModal} [data-testid="bulk-update-preview-document"]`; +export const BulkUpdateSaveFavorite = `${BulkUpdateModal} [data-testid="inline-save-query-modal-opener"]`; +export const BulkUpdateFavouriteNameInput = `${BulkUpdateModal} [data-testid="inline-save-query-modal-input"]`; +export const BulkUpdateFavouriteSaveButton = `${BulkUpdateModal} [data-testid="inline-save-query-modal-submit"]`; + // Connection import/export modals export const ExportConnectionsModalOpen = '[data-testid="favorites-menu-export-favorites-action"]'; @@ -669,6 +682,9 @@ export const SavedItemMenu = '[data-testid="saved-item-actions"]'; export const SavedItemMenuItemCopy = `${SavedItemMenu} [data-testid="saved-item-actions-copy-action"]`; export const SavedItemMenuItemRename = `${SavedItemMenu} [data-testid="saved-item-actions-rename-action"]`; export const SavedItemMenuItemDelete = `${SavedItemMenu} [data-testid="saved-item-actions-delete-action"]`; +export const FavouriteQueriesButton = `${QueryBarHistory} [data-testid="past-queries-favorites"] button`; +export const FavouriteQueryListItem = `${QueryBarHistory} [data-testid="favorite-query-list-item"]`; +export const FavouriteQueryTitle = `${QueryBarHistory} [data-testid="query-history-query-title"]`; export const myQueriesItem = (title: string): string => { return `[data-testid="my-queries-content"] [title="${title}"]`; diff --git a/packages/compass-e2e-tests/tests/collection-bulk-update.test.ts b/packages/compass-e2e-tests/tests/collection-bulk-update.test.ts new file mode 100644 index 00000000000..9719cd8f40d --- /dev/null +++ b/packages/compass-e2e-tests/tests/collection-bulk-update.test.ts @@ -0,0 +1,188 @@ +import { expect } from 'chai'; +import type { CompassBrowser } from '../helpers/compass-browser'; +import { startTelemetryServer } from '../helpers/telemetry'; +import type { Telemetry } from '../helpers/telemetry'; +import { beforeTests, afterTests, afterTest } from '../helpers/compass'; +import type { Compass } from '../helpers/compass'; +import * as Selectors from '../helpers/selectors'; +import { createNumbersCollection } from '../helpers/insert-data'; + +describe('Bulk Update', () => { + let compass: Compass; + let browser: CompassBrowser; + let telemetry: Telemetry; + + before(async function () { + telemetry = await startTelemetryServer(); + compass = await beforeTests({ + extraSpawnArgs: ['--enableBulkUpdateOperations'], + }); + browser = compass.browser; + }); + + after(async function () { + await afterTests(compass, this.currentTest); + await telemetry.stop(); + }); + + beforeEach(async function () { + await createNumbersCollection(); + await browser.connectWithConnectionString(); + await browser.navigateToCollectionTab('test', 'numbers', 'Documents'); + }); + + afterEach(async function () { + await afterTest(compass, this.currentTest); + }); + + it('updates documents matching a filter', async function () { + //const telemetryEntry = await browser.listenForTelemetryEvents(telemetry); + + // Set a query that we'll use. + await browser.runFindOperation('Documents', '{ i: 5 }'); + + // Open the modal. + await browser.clickVisible(Selectors.OpenBulkUpdateButton); + await browser.$(Selectors.BulkUpdateModal).waitForDisplayed(); + + // TODO(COMPASS-7448): Make sure the query is shown in the modal. + + // Check that it will update the expected number of documents + expect(await browser.$(Selectors.BulkUpdateTitle).getText()).to.equal( + 'Update 1 document' + ); + expect( + await browser.$(Selectors.BulkUpdateUpdateButton).getText() + ).to.equal('Update 1 document'); + + // Check that the modal starts with the default update text + expect( + await browser.getCodemirrorEditorText(Selectors.BulkUpdateUpdate) + ).to.equal('{ $set: { } }'); + + // Change the update text + await browser.setCodemirrorEditorValue( + Selectors.BulkUpdateUpdate, + '{ $set: { foo: "bar" } }' + ); + + // Wait for the preview to update accordingly + await browser.waitUntil(async () => { + const text = await browser + .$(Selectors.BulkUpdatePreviewDocument + ':first-child') + .getText(); + console.log(text); + return /foo\s+:\s+"bar"/.test(text); + }); + + // Press update + await browser.clickVisible(Selectors.BulkUpdateUpdateButton); + + // The modal should go away + await browser + .$(Selectors.BulkUpdateModal) + .waitForDisplayed({ reverse: true }); + + // TODO(COMPASS-7457): The toast should eventually say that it is done and have a refresh + // button, but right now it has a timeout and goes away automatically, so + // that will just flake. + + // TODO(COMPASS-7388): Check the telemetry once we add it + + // Keep running a new find and make sure the doc eventually matches the + // expected query (once the update ran). + // TODO(COMPASS-7457): Once we can wait for a stable toast we don't have to + // do this in a loop - we can just run this once when the update finishes. + await browser.waitUntil(async () => { + await browser.runFindOperation('Documents', '{ i: 5, foo: "bar" }'); + const modifiedDocument = await browser.$(Selectors.DocumentListEntry); + await modifiedDocument.waitForDisplayed(); + const doc = await getFormattedDocument(browser); + return /^_id: ObjectId\('[a-f0-9]{24}'\) i: 5 j: 0 foo: "bar"$/.test(doc); + }); + }); + + it('can save an update query as a favourite and return to it', async function () { + // Set a query that we'll use. + await browser.runFindOperation('Documents', '{ i: { $gt: 5 } }'); + + // Open the modal. + await browser.clickVisible(Selectors.OpenBulkUpdateButton); + await browser.$(Selectors.BulkUpdateModal).waitForDisplayed(); + + // Change the update text + await browser.setCodemirrorEditorValue( + Selectors.BulkUpdateUpdate, + '{ $set: { k: 0 } }' + ); + + // Click save to open the popover + await browser.clickVisible(Selectors.BulkUpdateSaveFavorite); + + // Fill in a name + const input = await browser.$(Selectors.BulkUpdateFavouriteNameInput); + input.waitForDisplayed(); + input.setValue('My Update Query'); + + // Click save to save the query + await browser.$(Selectors.BulkUpdateFavouriteSaveButton).waitForEnabled(); + await browser.clickVisible(Selectors.BulkUpdateFavouriteSaveButton); + + // Close the modal + await browser.clickVisible(Selectors.BulkUpdateCancelButton); + + // Wait for the modal to go away + await browser + .$(Selectors.BulkUpdateModal) + .waitForDisplayed({ reverse: true }); + + // Open the dropdown + await browser.clickVisible(Selectors.QueryBarHistoryButton); + + // Wait for the popover to show + await browser.$(Selectors.QueryBarHistory).waitForDisplayed(); + + // Browse to Favourites + await browser.clickVisible(Selectors.FavouriteQueriesButton); + + // Wait for the favourite to show and click it + await browser.waitUntil(async () => { + const favouriteElements = await browser.$$( + Selectors.FavouriteQueryListItem + ); + for (const element of favouriteElements) { + const favouriteName = await element + .$(Selectors.FavouriteQueryTitle) + .getText(); + console.log(favouriteName); + if (favouriteName === 'My Update Query') { + await element.click(); + return true; + } + } + return false; + }); + + // The modal should open + await browser.$(Selectors.BulkUpdateModal).waitForDisplayed(); + + // TODO(COMPASS-7448): Make sure the query is shown in the modal. + + // Check that the modal starts with the expected update text + expect(await browser.getCodemirrorEditorText(Selectors.BulkUpdateUpdate)).to + .equal(`{ + $set: { + k: 0 + } +}`); + }); +}); + +async function getFormattedDocument(browser: CompassBrowser): Promise { + const document = await browser.$(Selectors.DocumentListEntry); + await document.waitForDisplayed(); + return (await document.getText()) + .replace(/\n/g, ' ') + .replace(/\s+?:/g, ':') + .replace(/\s+/g, ' '); +}