Skip to content

Commit 2d0acb1

Browse files
committed
tests and cleanup
1 parent e8447d5 commit 2d0acb1

File tree

6 files changed

+56
-35
lines changed

6 files changed

+56
-35
lines changed

packages/compass-data-modeling/src/components/diagram-editor.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ const DiagramContent: React.FunctionComponent<{
128128
isNewlyCreatedDiagram?: boolean;
129129
model: StaticModel | null;
130130
isInRelationshipDrawingMode: boolean;
131-
editErrors?: string[];
132131
newCollection?: string;
133132
onAddFieldToObjectField: (ns: string, parentPath: string[]) => void;
134133
onAddNewFieldToCollection: (ns: string) => void;
@@ -526,7 +525,6 @@ export default connect(
526525
const { diagram, step } = state;
527526
return {
528527
step: step,
529-
editErrors: diagram?.editErrors,
530528
diagramId: diagram?.id,
531529
};
532530
},

packages/compass-data-modeling/src/store/diagram.spec.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type {
1818
StaticModel,
1919
} from '../services/data-model-storage';
2020
import { UUID } from 'bson';
21+
import Sinon from 'sinon';
2122

2223
const model: StaticModel = {
2324
collections: [
@@ -67,9 +68,11 @@ const loadedDiagram: MongoDBDataModelDescription = {
6768

6869
describe('Data Modeling store', function () {
6970
let store: DataModelingStore;
71+
let openToastSpy: Sinon.SinonSpy;
7072

7173
beforeEach(function () {
72-
store = setupStore();
74+
openToastSpy = Sinon.spy();
75+
store = setupStore({}, undefined, openToastSpy);
7376
});
7477

7578
describe('New Diagram', function () {
@@ -157,7 +160,7 @@ describe('Data Modeling store', function () {
157160

158161
const state = store.getState();
159162
const diagram = getCurrentDiagramFromState(state);
160-
expect(state.diagram?.editErrors).to.be.undefined;
163+
expect(openToastSpy).not.to.have.been.called;
161164
expect(diagram.edits).to.have.length(2);
162165
expect(diagram.edits[0]).to.deep.equal(loadedDiagram.edits[0]);
163166
expect(diagram.edits[1]).to.deep.include(edit);
@@ -193,7 +196,7 @@ describe('Data Modeling store', function () {
193196

194197
const state = store.getState();
195198
const diagram = getCurrentDiagramFromState(state);
196-
expect(state.diagram?.editErrors).to.be.undefined;
199+
expect(openToastSpy).not.to.have.been.called;
197200
expect(diagram.edits).to.have.length(2);
198201
expect(diagram.edits[0]).to.deep.equal(loadedDiagram.edits[0]);
199202
expect(diagram.edits[1]).to.deep.include({
@@ -217,9 +220,8 @@ describe('Data Modeling store', function () {
217220
} as unknown as Edit;
218221
store.dispatch(applyEdit(edit));
219222

220-
const editErrors = store.getState().diagram?.editErrors;
221-
expect(editErrors).to.have.length(1);
222-
expect(editErrors && editErrors[0]).to.equal(
223+
expect(openToastSpy).to.have.been.calledOnce;
224+
expect(openToastSpy.firstCall.args[1].description).to.include(
223225
"'relationship,relationship' is required"
224226
);
225227
const diagram = getCurrentDiagramFromState(store.getState());
@@ -353,7 +355,7 @@ describe('Data Modeling store', function () {
353355

354356
const state = store.getState();
355357
const diagram = getCurrentDiagramFromState(state);
356-
expect(state.diagram?.editErrors).to.be.undefined;
358+
expect(openToastSpy).not.to.have.been.called;
357359
expect(diagram.edits).to.have.length(2);
358360
expect(diagram.edits[0]).to.deep.equal(loadedDiagram.edits[0]);
359361
expect(diagram.edits[1]).to.deep.include(edit);
@@ -373,12 +375,22 @@ describe('Data Modeling store', function () {
373375
} as unknown as Edit;
374376
store.dispatch(applyEdit(edit));
375377

376-
const editErrors = store.getState().diagram?.editErrors;
377-
expect(editErrors).to.have.length(1);
378-
expect(editErrors && editErrors[0]).to.equal("'newPosition' is required");
378+
expect(openToastSpy).to.have.been.calledOnce;
379+
expect(openToastSpy.firstCall.args[1].description).to.include(
380+
"'newPosition' is required"
381+
);
379382
const diagram = getCurrentDiagramFromState(store.getState());
380383
expect(diagram.edits).to.deep.equal(loadedDiagram.edits);
381384
});
385+
386+
it('should handle an invalid RenameCollection edit', function () {
387+
store.dispatch(openDiagram(loadedDiagram));
388+
store.dispatch(renameCollection('nonExisting', 'newName'));
389+
expect(openToastSpy).to.have.been.calledOnce;
390+
expect(openToastSpy.firstCall.args[1].description).to.include(
391+
"Collection 'nonExisting' not found"
392+
);
393+
});
382394
});
383395

384396
it('undo & redo', function () {

packages/compass-data-modeling/src/store/diagram.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { memoize } from 'lodash';
1818
import type { DataModelingState, DataModelingThunkAction } from './reducer';
1919
import {
2020
getCoordinatesForNewNode,
21-
openToast,
21+
type openToast as _openToast,
2222
showConfirmation,
2323
showPrompt,
2424
} from '@mongodb-js/compass-components';
@@ -225,7 +225,6 @@ export const diagramReducer: Reducer<DiagramState> = (
225225
state.draftCollection,
226226
action.edit.toNS
227227
),
228-
editErrors: undefined,
229228
updatedAt: new Date().toISOString(),
230229
selectedItems: {
231230
type: 'collection',
@@ -242,7 +241,6 @@ export const diagramReducer: Reducer<DiagramState> = (
242241
current: [...state.edits.current, action.edit] as [Edit, ...Edit[]],
243242
next: [],
244243
},
245-
editErrors: undefined,
246244
updatedAt: new Date().toISOString(),
247245
selectedItems: updateSelectedItemsFromAppliedEdit(
248246
state.selectedItems,
@@ -501,7 +499,7 @@ export function redoEdit(): DataModelingThunkAction<void, RedoEditAction> {
501499
export function onAddNestedField(
502500
ns: string,
503501
parentFieldPath: string[]
504-
): DataModelingThunkAction<void, ApplyEditAction | ApplyEditFailedAction> {
502+
): DataModelingThunkAction<void, ApplyEditAction | RevertFailedEditAction> {
505503
return (dispatch, getState) => {
506504
const modelState = selectCurrentModelFromState(getState());
507505

@@ -532,7 +530,7 @@ export function onAddNestedField(
532530

533531
export function addNewFieldToCollection(
534532
ns: string
535-
): DataModelingThunkAction<void, ApplyEditAction | ApplyEditFailedAction> {
533+
): DataModelingThunkAction<void, ApplyEditAction | RevertFailedEditAction> {
536534
return (dispatch, getState) => {
537535
const modelState = selectCurrentModelFromState(getState());
538536

@@ -561,7 +559,7 @@ export function addNewFieldToCollection(
561559
export function moveCollection(
562560
ns: string,
563561
newPosition: [number, number]
564-
): DataModelingThunkAction<void, ApplyEditAction | ApplyEditFailedAction> {
562+
): DataModelingThunkAction<void, ApplyEditAction | RevertFailedEditAction> {
565563
const edit: Omit<
566564
Extract<Edit, { type: 'MoveCollection' }>,
567565
'id' | 'timestamp'
@@ -578,7 +576,7 @@ export function renameCollection(
578576
toNS: string
579577
): DataModelingThunkAction<
580578
void,
581-
ApplyEditAction | ApplyEditFailedAction | CollectionSelectedAction
579+
ApplyEditAction | RevertFailedEditAction | CollectionSelectedAction
582580
> {
583581
const edit: Omit<
584582
Extract<Edit, { type: 'RenameCollection' }>,
@@ -592,18 +590,21 @@ export function renameCollection(
592590
return applyEdit(edit);
593591
}
594592

595-
function handleError(messages: string[]) {
593+
function handleError(openToast: typeof _openToast, messages: string[]) {
596594
openToast('data-modeling-error', {
597595
variant: 'warning',
598596
title: 'Error opening diagram',
599597
description: messages.join(' '),
600598
});
601599
}
602600

601+
/**
602+
* Not intended to be called directly, only exported for testing.
603+
*/
603604
export function applyEdit(
604605
rawEdit: EditAction
605606
): DataModelingThunkAction<boolean, ApplyEditAction | RevertFailedEditAction> {
606-
return (dispatch, getState, { dataModelStorage }) => {
607+
return (dispatch, getState, { dataModelStorage, openToast }) => {
607608
const edit = {
608609
...rawEdit,
609610
id: new UUID().toString(),
@@ -612,7 +613,7 @@ export function applyEdit(
612613
const { result, errors } = validateEdit(edit);
613614
let isValid = result;
614615
if (!result) {
615-
handleError(errors);
616+
handleError(openToast, errors);
616617
return isValid;
617618
}
618619
dispatch({
@@ -624,7 +625,7 @@ export function applyEdit(
624625
try {
625626
selectCurrentModelFromState(getState());
626627
} catch (e) {
627-
handleError([
628+
handleError(openToast, [
628629
'Something went wrong when applying the changes.',
629630
(e as Error).message,
630631
]);
@@ -689,7 +690,7 @@ export function renameDiagram(
689690
export function openDiagramFromFile(
690691
file: File
691692
): DataModelingThunkAction<Promise<void>, OpenDiagramAction> {
692-
return async (dispatch, getState, { dataModelStorage, track }) => {
693+
return async (dispatch, getState, { dataModelStorage, track, openToast }) => {
693694
try {
694695
const { name, edits } = await getDiagramContentsFromFile(file);
695696

@@ -720,7 +721,7 @@ export function openDiagramFromFile(
720721

721722
export function updateRelationship(
722723
relationship: Relationship
723-
): DataModelingThunkAction<boolean, ApplyEditAction | ApplyEditFailedAction> {
724+
): DataModelingThunkAction<boolean, ApplyEditAction | RevertFailedEditAction> {
724725
return applyEdit({
725726
type: 'UpdateRelationship',
726727
relationship,
@@ -748,7 +749,7 @@ export function deleteRelationship(
748749

749750
export function deleteCollection(
750751
ns: string
751-
): DataModelingThunkAction<void, ApplyEditAction | ApplyEditFailedAction> {
752+
): DataModelingThunkAction<void, ApplyEditAction | RevertFailedEditAction> {
752753
return (dispatch, getState, { track }) => {
753754
track('Data Modeling Collection Removed', {
754755
source: 'side_panel',
@@ -761,14 +762,14 @@ export function deleteCollection(
761762
export function updateCollectionNote(
762763
ns: string,
763764
note: string
764-
): DataModelingThunkAction<void, ApplyEditAction | ApplyEditFailedAction> {
765+
): DataModelingThunkAction<void, ApplyEditAction | RevertFailedEditAction> {
765766
return applyEdit({ type: 'UpdateCollectionNote', ns, note });
766767
}
767768

768769
export function removeField(
769770
ns: string,
770771
field: FieldPath
771-
): DataModelingThunkAction<void, ApplyEditAction | ApplyEditFailedAction> {
772+
): DataModelingThunkAction<void, ApplyEditAction | RevertFailedEditAction> {
772773
return (dispatch, getState, { track }) => {
773774
track('Data Modeling Field Removed', {
774775
source: 'side_panel',
@@ -782,7 +783,7 @@ export function renameField(
782783
ns: string,
783784
field: FieldPath,
784785
newName: string
785-
): DataModelingThunkAction<void, ApplyEditAction | ApplyEditFailedAction> {
786+
): DataModelingThunkAction<void, ApplyEditAction | RevertFailedEditAction> {
786787
return (dispatch, getState, { track }) => {
787788
track('Data Modeling Field Renamed', {
788789
source: 'side_panel',
@@ -818,7 +819,7 @@ export function changeFieldType(
818819
ns: string,
819820
fieldPath: FieldPath,
820821
newTypes: string[]
821-
): DataModelingThunkAction<void, ApplyEditAction | ApplyEditFailedAction> {
822+
): DataModelingThunkAction<void, ApplyEditAction | RevertFailedEditAction> {
822823
return (dispatch, getState, { track }) => {
823824
const collectionSchema = selectCurrentModelFromState(
824825
getState()
@@ -886,7 +887,7 @@ export function addCollection(
886887
position?: [number, number]
887888
): DataModelingThunkAction<
888889
void,
889-
ApplyEditAction | ApplyEditFailedAction | CollectionSelectedAction
890+
ApplyEditAction | RevertFailedEditAction | CollectionSelectedAction
890891
> {
891892
return (dispatch, getState, { track }) => {
892893
const existingCollections = selectCurrentModelFromState(

packages/compass-data-modeling/src/store/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ import reducer from './reducer';
99
import type { DataModelingExtraArgs } from './reducer';
1010
import thunk from 'redux-thunk';
1111
import type { ActivateHelpers } from '@mongodb-js/compass-app-registry';
12+
import { openToast as _openToast } from '@mongodb-js/compass-components';
1213

13-
export type DataModelingStoreOptions = Record<string, unknown>;
14+
export type DataModelingStoreOptions = {
15+
openToast?: typeof _openToast;
16+
};
1417

1518
export type DataModelingStoreServices = {
1619
preferences: PreferencesAccess;
@@ -22,7 +25,7 @@ export type DataModelingStoreServices = {
2225
};
2326

2427
export function activateDataModelingStore(
25-
_: DataModelingStoreOptions,
28+
{ openToast = _openToast }: DataModelingStoreOptions,
2629
services: DataModelingStoreServices,
2730
{ cleanup }: ActivateHelpers
2831
) {
@@ -35,6 +38,7 @@ export function activateDataModelingStore(
3538
...services,
3639
cancelAnalysisControllerRef,
3740
cancelExportControllerRef,
41+
openToast,
3842
})
3943
)
4044
);

packages/compass-data-modeling/src/store/reducer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import type {
2020
ExportDiagramActions,
2121
} from './export-diagram';
2222
import { exportDiagramReducer } from './export-diagram';
23+
import { type openToast as _openToast } from '@mongodb-js/compass-components';
2324

2425
const reducer = combineReducers({
2526
step: stepReducer,
@@ -46,6 +47,7 @@ export type DataModelingState = ReturnType<typeof reducer>;
4647
export type DataModelingExtraArgs = DataModelingStoreServices & {
4748
cancelAnalysisControllerRef: { current: AbortController | null };
4849
cancelExportControllerRef: { current: AbortController | null };
50+
openToast: typeof _openToast;
4951
};
5052

5153
export type DataModelingThunkAction<R, A extends AnyAction> = ThunkAction<

packages/compass-data-modeling/test/setup-store.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { activateDataModelingStore } from '../src/store';
1010
import type { DataModelingStoreServices } from '../src/store';
1111
import { noopDataModelStorageService } from '../src/provider';
1212
import { Provider } from 'react-redux';
13+
import { openToast as _openToast } from '@mongodb-js/compass-components';
1314

1415
type ConnectionInfoWithMockData = ConnectionInfo & {
1516
databases: Array<{
@@ -136,10 +137,13 @@ const testConnections = [
136137

137138
export const setupStore = (
138139
services: Partial<DataModelingStoreServices> = {},
139-
connections: ConnectionInfoWithMockData[] = testConnections
140+
connections: ConnectionInfoWithMockData[] = testConnections,
141+
openToast: typeof _openToast = _openToast
140142
) => {
141143
return activateDataModelingStore(
142-
{},
144+
{
145+
openToast,
146+
},
143147
{
144148
logger: createNoopLogger('TEST'),
145149
track: createNoopTrack(),

0 commit comments

Comments
 (0)