Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
5 changes: 3 additions & 2 deletions packages/collaboration-manager/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ export default {
tsconfig: '<rootDir>/tsconfig.test.json',
},
},
testMatch: [ '<rootDir>/src/**/*.spec.ts' ],
modulePathIgnorePatterns: [ '<rootDir>/.*/__mocks__', '<rootDir>/.*/mocks' ],
testMatch: ['<rootDir>/src/**/*.spec.ts'],
modulePathIgnorePatterns: ['<rootDir>/.*/__mocks__', '<rootDir>/.*/mocks'],
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
'^codex-tooltip$': '<rootDir>/test/mocks/codex-tooltip.ts',
},
transform: {
...createDefaultEsmPreset().transform,
Expand Down
106 changes: 71 additions & 35 deletions packages/collaboration-manager/src/CollaborationManager.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */
import { createDataKey, IndexBuilder } from '@editorjs/model';
import { createDataKey, EventType, IndexBuilder } from '@editorjs/model';
import { EditorJSModel } from '@editorjs/model';
import type { CoreConfig } from '@editorjs/sdk';
import { CoreEventType, type CoreConfig } from '@editorjs/sdk';
import { beforeAll, jest } from '@jest/globals';
import { BatchedOperation } from './BatchedOperation.js';
import { CollaborationManager } from './CollaborationManager.js';
import { Operation, OperationType } from './Operation.js';
import { UndoRedoManager } from './UndoRedoManager.js';
import { createManager } from '../test/mocks/createManager.js';
import { OTClient } from './client/index.js';

const userId = 'user';
const remoteUserId = 'remote-user';
Expand All @@ -31,7 +32,7 @@ describe('CollaborationManager', () => {
it('should throw an error on unknown operation type', () => {
const model = new EditorJSModel(userId, { identifier: documentId });

const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;

// @ts-expect-error - for test purposes
expect(() => collaborationManager.applyOperation(new Operation('unknown', new IndexBuilder().build(), 'hello'))).toThrow('Unknown operation type');
Expand All @@ -51,7 +52,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 4])
Expand Down Expand Up @@ -92,7 +93,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([3, 5])
Expand Down Expand Up @@ -125,7 +126,7 @@ describe('CollaborationManager', () => {
model.initializeDocument({
blocks: [],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.build();
const operation = new Operation(OperationType.Insert, index, {
Expand Down Expand Up @@ -173,7 +174,7 @@ describe('CollaborationManager', () => {
model.initializeDocument({
blocks: [block],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.build();
const operation = new Operation(OperationType.Delete, index, {
Expand Down Expand Up @@ -202,7 +203,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 5])
Expand Down Expand Up @@ -249,7 +250,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 5])
Expand Down Expand Up @@ -279,7 +280,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const op1 = new Operation(OperationType.Insert, new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 0])
Expand Down Expand Up @@ -329,7 +330,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 3])
Expand Down Expand Up @@ -382,7 +383,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 4])
Expand Down Expand Up @@ -424,7 +425,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([
Expand Down Expand Up @@ -467,7 +468,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 4])
Expand Down Expand Up @@ -510,7 +511,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 4])
Expand Down Expand Up @@ -546,7 +547,7 @@ describe('CollaborationManager', () => {
model.initializeDocument({
blocks: [],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.build();
const operation = new Operation(OperationType.Insert, index, {
Expand Down Expand Up @@ -586,7 +587,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 5])
Expand Down Expand Up @@ -636,7 +637,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 3])
Expand Down Expand Up @@ -689,7 +690,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 3])
Expand Down Expand Up @@ -742,7 +743,7 @@ describe('CollaborationManager', () => {
model.initializeDocument({
blocks: [block],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.build();
const operation = new Operation(OperationType.Delete, index, {
Expand Down Expand Up @@ -778,7 +779,7 @@ describe('CollaborationManager', () => {
model.initializeDocument({
blocks: [block],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.build();
const operation = new Operation(OperationType.Delete, index, {
Expand Down Expand Up @@ -817,7 +818,7 @@ describe('CollaborationManager', () => {
model.initializeDocument({
blocks: [block],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.build();
const operation = new Operation(OperationType.Delete, index, {
Expand Down Expand Up @@ -859,7 +860,7 @@ describe('CollaborationManager', () => {
model.initializeDocument({
blocks: [block],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index = new IndexBuilder().addBlockIndex(0)
.build();
const operation = new Operation(OperationType.Delete, index, {
Expand Down Expand Up @@ -900,7 +901,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index1 = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 0])
Expand Down Expand Up @@ -952,7 +953,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const index1 = new IndexBuilder().addBlockIndex(0)
.addDataKey(createDataKey('text'))
.addTextRange([0, 0])
Expand Down Expand Up @@ -1005,7 +1006,7 @@ describe('CollaborationManager', () => {
},
}],
});
const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;

model.insertText('another-user', 0, createDataKey('text'), 'hello', 0);

Expand Down Expand Up @@ -1045,7 +1046,7 @@ describe('CollaborationManager', () => {
},
}],
});
void new CollaborationManager(config as Required<CoreConfig>, model);
createManager(config as Required<CoreConfig>, model);

model.insertText(userId, 0, createDataKey('text'), 'a', 0);

Expand Down Expand Up @@ -1076,7 +1077,7 @@ describe('CollaborationManager', () => {
}],
});

const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;

// Create local operation
const localIndex = new IndexBuilder().addBlockIndex(0)
Expand Down Expand Up @@ -1135,7 +1136,7 @@ describe('CollaborationManager', () => {
}],
});

const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;

model.insertText(userId, 0, createDataKey('text'), 'world', 0);
jest.advanceTimersByTime(500);
Expand Down Expand Up @@ -1176,8 +1177,8 @@ describe('CollaborationManager', () => {
}],
});

const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const remoteCollaborationManager = new CollaborationManager(remoteConfig as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const remoteCollaborationManager = createManager(remoteConfig as Required<CoreConfig>, model).manager;

// Char-by-char insert text 'hello' from local user
const localText = 'hello';
Expand Down Expand Up @@ -1244,8 +1245,8 @@ describe('CollaborationManager', () => {
}],
});

const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const remoteCollaborationManager = new CollaborationManager(remoteConfig as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;
const remoteCollaborationManager = createManager(remoteConfig as Required<CoreConfig>, model).manager;

// Isert line 'hello' from local user
const localIndex = new IndexBuilder().addBlockIndex(0)
Expand Down Expand Up @@ -1305,7 +1306,7 @@ describe('CollaborationManager', () => {
}],
});

const collaborationManager = new CollaborationManager(config as Required<CoreConfig>, model);
const collaborationManager = createManager(config as Required<CoreConfig>, model).manager;

// Create local delete operation
const localIndex = new IndexBuilder().addBlockIndex(0)
Expand Down Expand Up @@ -1342,4 +1343,39 @@ describe('CollaborationManager', () => {
});
});
});

describe('destroy', () => {
it('should unsubscribe model and core event listeners', () => {
const model = new EditorJSModel(userId, { identifier: documentId });
const removeModelListenerSpy = jest.spyOn(model, 'removeEventListener');
const { manager, eventBus } = createManager(config as Required<CoreConfig>, model);
const removeEventBusListenerSpy = jest.spyOn(eventBus, 'removeEventListener');

manager.destroy();

expect(removeModelListenerSpy).toHaveBeenCalledWith(EventType.Changed, expect.any(Function));
expect(removeEventBusListenerSpy).toHaveBeenCalledWith(`core:${CoreEventType.Undo}`, expect.any(Function));
expect(removeEventBusListenerSpy).toHaveBeenCalledWith(`core:${CoreEventType.Redo}`, expect.any(Function));
expect(removeEventBusListenerSpy).toHaveBeenCalledWith(`core:${CoreEventType.Ready}`, expect.any(Function));
});

it('should close ot client connection', async () => {
const model = new EditorJSModel(userId, { identifier: documentId });
const { manager, eventBus } = createManager({
...config,
collaborationServer: 'ws://test-collab.invalid/document',
} as Required<CoreConfig>, model);

eventBus.dispatchEvent(new CustomEvent(`core:${CoreEventType.Ready}`));
await Promise.resolve();

const closeSpy = jest.spyOn(OTClient.prototype, 'close');

manager.destroy();
await Promise.resolve();

expect(closeSpy).toHaveBeenCalledTimes(1);
closeSpy.mockRestore();
});
});
});
Loading
Loading