Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 51 additions & 10 deletions packages/compass-crud/src/components/bulk-actions-toasts.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from './bulk-actions-toasts';
import { expect } from 'chai';
import sinon from 'sinon';
import { MongoNetworkError } from 'mongodb';

function renderToastPortal() {
return render(<ToastArea></ToastArea>);
Expand Down Expand Up @@ -67,30 +68,51 @@ describe('Bulk Action Toasts', function () {
{
modal: openBulkDeleteFailureToast,
affected: undefined,
expected: 'The delete operation failed.',
error: new Error('Test error'),
expected: ['The delete operation failed.', 'Test error'],
},
{
modal: openBulkDeleteFailureToast,
affected: 1,
expected: '1 document could not been deleted.',
error: new Error('Another test error'),
expected: [
'1 document could not been deleted.',
'Another test error',
],
},
{
modal: openBulkDeleteFailureToast,
affected: 2,
expected: '2 documents could not been deleted.',
error: new Error('Another failure'),
expected: ['2 documents could not been deleted.', 'Another failure'],
},
{
modal: openBulkDeleteFailureToast,
affected: 2,
error: new MongoNetworkError('Connection lost'),
expected: [
'Delete operation - network error occurred.',
'Connection lost',
],
},
];

for (const useCase of USE_CASES) {
it(`${useCase.modal.name} shows the text '${useCase.expected}' when affected document/s is/are '${useCase.affected}'`, async function () {
useCase.modal({
affectedDocuments: useCase.affected,
error: useCase.error,
onRefresh: () => {},
});

await waitFor(async function () {
const node = await screen.findByText(useCase.expected);
expect(node).to.exist;
if (!Array.isArray(useCase.expected)) {
expect(await screen.findByText(useCase.expected)).to.exist;
} else {
for (const expectedText of useCase.expected) {
expect(await screen.findByText(expectedText)).to.exist;
}
}
});
});
}
Expand Down Expand Up @@ -160,30 +182,49 @@ describe('Bulk Action Toasts', function () {
{
modal: openBulkUpdateFailureToast,
affected: undefined,
expected: 'The update operation failed.',
error: new Error('Test error'),
expected: ['The update operation failed.', 'Test error'],
},
{
modal: openBulkUpdateFailureToast,
affected: 1,
expected: '1 document could not been updated.',
error: new Error('Could not update'),
expected: ['1 document could not been updated.', 'Could not update'],
},
{
modal: openBulkUpdateFailureToast,
affected: 2,
expected: '2 documents could not been updated.',
error: new Error('Update failed'),
expected: ['2 documents could not been updated.', 'Update failed'],
},

{
modal: openBulkUpdateFailureToast,
affected: 2,
error: new MongoNetworkError('Connection lost'),
expected: [
'Update operation - network error occurred.',
'Connection lost',
],
},
];

for (const useCase of USE_CASES) {
it(`${useCase.modal.name} shows the text '${useCase.expected}' when ${useCase.affected} document/s affected`, async function () {
useCase.modal({
affectedDocuments: useCase.affected,
error: useCase.error,
onRefresh: () => {},
});

await waitFor(async function () {
const node = await screen.findByText(useCase.expected);
expect(node).to.exist;
if (!Array.isArray(useCase.expected)) {
expect(await screen.findByText(useCase.expected)).to.exist;
} else {
for (const expectedText of useCase.expected) {
expect(await screen.findByText(expectedText)).to.exist;
}
}
});
});
}
Expand Down
65 changes: 39 additions & 26 deletions packages/compass-crud/src/components/bulk-actions-toasts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
closeToast,
ToastBody,
} from '@mongodb-js/compass-components';
import { MongoNetworkError } from 'mongodb';

type BulkDeleteSuccessToastProps = {
affectedDocuments?: number;
Expand Down Expand Up @@ -74,28 +75,35 @@ export function openBulkDeleteProgressToast({

type BulkDeleteFailureToastProps = {
affectedDocuments?: number;
error: any;
};

const isNetworkError = (error: any) => error instanceof MongoNetworkError;

export function openBulkDeleteFailureToast({
affectedDocuments,
error,
}: BulkDeleteFailureToastProps): void {
let text;
switch (affectedDocuments) {
case undefined:
text = 'The delete operation failed.';
break;
case 1:
text = `${affectedDocuments} document could not been deleted.`;
break;
default:
text = `${affectedDocuments} documents could not been deleted.`;
}
let title: string;
if (isNetworkError(error)) {
title = 'Delete operation - network error occurred.';
} else
switch (affectedDocuments) {
case undefined:
title = 'The delete operation failed.';
break;
case 1:
title = `${affectedDocuments} document could not been deleted.`;
break;
default:
title = `${affectedDocuments} documents could not been deleted.`;
}

openToast('bulk-delete-toast', {
title: '',
title,
variant: 'warning',
dismissible: true,
description: <ToastBody statusMessage={text} />,
description: <ToastBody statusMessage={error.message} />,
});
}

Expand Down Expand Up @@ -168,27 +176,32 @@ export function openBulkUpdateProgressToast({

type BulkUpdateFailureToastProps = {
affectedDocuments?: number;
error: any;
};

export function openBulkUpdateFailureToast({
affectedDocuments,
error,
}: BulkUpdateFailureToastProps): void {
let text;
switch (affectedDocuments) {
case undefined:
text = 'The update operation failed.';
break;
case 1:
text = `${affectedDocuments} document could not been updated.`;
break;
default:
text = `${affectedDocuments} documents could not been updated.`;
}
let title: string;
if (isNetworkError(error)) {
title = 'Update operation - network error occurred.';
} else
switch (affectedDocuments) {
case undefined:
title = 'The update operation failed.';
break;
case 1:
title = `${affectedDocuments} document could not been updated.`;
break;
default:
title = `${affectedDocuments} documents could not been updated.`;
}

openToast('bulk-update-toast', {
title: '',
title,
variant: 'warning',
dismissible: true,
description: <ToastBody statusMessage={text} />,
description: <ToastBody statusMessage={error.message} />,
});
}
3 changes: 2 additions & 1 deletion packages/compass-crud/src/stores/crud-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { Listenable, Store } from 'reflux';
import Reflux from 'reflux';
import toNS from 'mongodb-ns';
import { findIndex, isEmpty, isEqual } from 'lodash';
import type { MongoServerError } from 'mongodb';
import semver from 'semver';
import StateMixin from '@mongodb-js/reflux-state-mixin';
import type { Element } from 'hadron-document';
Expand Down Expand Up @@ -1243,6 +1242,7 @@ class CrudStoreImpl
} catch (err: any) {
openBulkUpdateFailureToast({
affectedDocuments: this.state.bulkUpdate.affected,
error: err,
});

this.logger.log.error(
Expand Down Expand Up @@ -1899,6 +1899,7 @@ class CrudStoreImpl
bulkDeleteFailed(ex: Error) {
openBulkDeleteFailureToast({
affectedDocuments: this.state.bulkDelete.affected,
error: ex,
});

this.logger.log.error(
Expand Down
Loading