mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-13 22:54:42 -04:00

Signed-off-by: Philip Molares <philip.molares@udo.edu> Signed-off-by: Erik Michelson <github@erik.michelson.eu> Co-authored-by: Erik Michelson <github@erik.michelson.eu> Co-authored-by: Philip Molares <philip.molares@udo.edu> Co-authored-by: Tilman Vatteroth <git@tilmanvatteroth.de> Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
190 lines
5.7 KiB
TypeScript
190 lines
5.7 KiB
TypeScript
/*
|
|
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
import * as hedgedocRealtimeModule from '@hedgedoc/realtime';
|
|
import { WebsocketTransporter } from '@hedgedoc/realtime';
|
|
import { Mock } from 'ts-mockery';
|
|
import WebSocket from 'ws';
|
|
import * as yProtocolsAwarenessModule from 'y-protocols/awareness';
|
|
|
|
import { User } from '../../users/user.entity';
|
|
import * as realtimeNoteModule from './realtime-note';
|
|
import { RealtimeNote } from './realtime-note';
|
|
import { mockAwareness } from './test-utils/mock-awareness';
|
|
import { mockRealtimeNote } from './test-utils/mock-realtime-note';
|
|
import { mockWebsocketDoc } from './test-utils/mock-websocket-doc';
|
|
import { mockWebsocketTransporter } from './test-utils/mock-websocket-transporter';
|
|
import * as websocketAwarenessModule from './websocket-awareness';
|
|
import { ClientIdUpdate, WebsocketAwareness } from './websocket-awareness';
|
|
import { WebsocketConnection } from './websocket-connection';
|
|
import * as websocketDocModule from './websocket-doc';
|
|
import { WebsocketDoc } from './websocket-doc';
|
|
|
|
import SpyInstance = jest.SpyInstance;
|
|
|
|
describe('websocket connection', () => {
|
|
let mockedDoc: WebsocketDoc;
|
|
let mockedAwareness: WebsocketAwareness;
|
|
let mockedRealtimeNote: RealtimeNote;
|
|
let mockedWebsocket: WebSocket;
|
|
let mockedUser: User;
|
|
let mockedWebsocketTransporter: WebsocketTransporter;
|
|
let removeAwarenessSpy: SpyInstance;
|
|
|
|
beforeEach(() => {
|
|
jest.resetAllMocks();
|
|
jest.resetModules();
|
|
mockedDoc = mockWebsocketDoc();
|
|
mockedAwareness = mockAwareness();
|
|
mockedRealtimeNote = mockRealtimeNote(mockedDoc, mockedAwareness);
|
|
mockedWebsocket = Mock.of<WebSocket>({});
|
|
mockedUser = Mock.of<User>({});
|
|
mockedWebsocketTransporter = mockWebsocketTransporter();
|
|
|
|
jest
|
|
.spyOn(realtimeNoteModule, 'RealtimeNote')
|
|
.mockImplementation(() => mockedRealtimeNote);
|
|
jest
|
|
.spyOn(websocketDocModule, 'WebsocketDoc')
|
|
.mockImplementation(() => mockedDoc);
|
|
jest
|
|
.spyOn(websocketAwarenessModule, 'WebsocketAwareness')
|
|
.mockImplementation(() => mockedAwareness);
|
|
jest
|
|
.spyOn(hedgedocRealtimeModule, 'WebsocketTransporter')
|
|
.mockImplementation(() => mockedWebsocketTransporter);
|
|
|
|
removeAwarenessSpy = jest
|
|
.spyOn(yProtocolsAwarenessModule, 'removeAwarenessStates')
|
|
.mockImplementation();
|
|
});
|
|
|
|
afterAll(() => {
|
|
jest.resetAllMocks();
|
|
jest.resetModules();
|
|
});
|
|
|
|
it('sets up the websocket in the constructor', () => {
|
|
const setupWebsocketSpy = jest.spyOn(
|
|
mockedWebsocketTransporter,
|
|
'setupWebsocket',
|
|
);
|
|
|
|
new WebsocketConnection(mockedWebsocket, mockedUser, mockedRealtimeNote);
|
|
|
|
expect(setupWebsocketSpy).toBeCalledWith(mockedWebsocket);
|
|
});
|
|
|
|
it('forwards sent messages to the transporter', () => {
|
|
const sut = new WebsocketConnection(
|
|
mockedWebsocket,
|
|
mockedUser,
|
|
mockedRealtimeNote,
|
|
);
|
|
|
|
const sendFunctionSpy = jest.spyOn(mockedWebsocketTransporter, 'send');
|
|
const sendContent = new Uint8Array();
|
|
sut.send(sendContent);
|
|
expect(sendFunctionSpy).toBeCalledWith(sendContent);
|
|
});
|
|
|
|
it('forwards disconnect calls to the transporter', () => {
|
|
const sut = new WebsocketConnection(
|
|
mockedWebsocket,
|
|
mockedUser,
|
|
mockedRealtimeNote,
|
|
);
|
|
|
|
const disconnectFunctionSpy = jest.spyOn(
|
|
mockedWebsocketTransporter,
|
|
'disconnect',
|
|
);
|
|
sut.disconnect();
|
|
expect(disconnectFunctionSpy).toBeCalled();
|
|
});
|
|
|
|
it('forwards isSynced checks to the transporter', () => {
|
|
const sut = new WebsocketConnection(
|
|
mockedWebsocket,
|
|
mockedUser,
|
|
mockedRealtimeNote,
|
|
);
|
|
|
|
const isSyncedFunctionSpy = jest.spyOn(
|
|
mockedWebsocketTransporter,
|
|
'isSynced',
|
|
);
|
|
|
|
expect(sut.isSynced()).toBe(false);
|
|
|
|
isSyncedFunctionSpy.mockReturnValue(true);
|
|
expect(sut.isSynced()).toBe(true);
|
|
});
|
|
|
|
it('removes the client from the note on transporter disconnect', () => {
|
|
const sut = new WebsocketConnection(
|
|
mockedWebsocket,
|
|
mockedUser,
|
|
mockedRealtimeNote,
|
|
);
|
|
|
|
const removeClientSpy = jest.spyOn(mockedRealtimeNote, 'removeClient');
|
|
|
|
mockedWebsocketTransporter.emit('disconnected');
|
|
|
|
expect(removeClientSpy).toBeCalledWith(sut);
|
|
});
|
|
|
|
it('remembers the controlled awareness-ids on awareness update', () => {
|
|
const sut = new WebsocketConnection(
|
|
mockedWebsocket,
|
|
mockedUser,
|
|
mockedRealtimeNote,
|
|
);
|
|
|
|
const update: ClientIdUpdate = { added: [0], removed: [1], updated: [2] };
|
|
mockedAwareness.emit('update', [update, sut]);
|
|
|
|
expect(sut.getControlledAwarenessIds()).toEqual(new Set([0]));
|
|
});
|
|
|
|
it("doesn't remembers the controlled awareness-ids of other connections on awareness update", () => {
|
|
const sut = new WebsocketConnection(
|
|
mockedWebsocket,
|
|
mockedUser,
|
|
mockedRealtimeNote,
|
|
);
|
|
|
|
const update: ClientIdUpdate = { added: [0], removed: [1], updated: [2] };
|
|
mockedAwareness.emit('update', [update, Mock.of<WebsocketConnection>()]);
|
|
|
|
expect(sut.getControlledAwarenessIds()).toEqual(new Set([]));
|
|
});
|
|
|
|
it('removes the controlled awareness ids on transport disconnect', () => {
|
|
const sut = new WebsocketConnection(
|
|
mockedWebsocket,
|
|
mockedUser,
|
|
mockedRealtimeNote,
|
|
);
|
|
|
|
const update: ClientIdUpdate = { added: [0], removed: [1], updated: [2] };
|
|
mockedAwareness.emit('update', [update, sut]);
|
|
|
|
mockedWebsocketTransporter.emit('disconnected');
|
|
|
|
expect(removeAwarenessSpy).toBeCalledWith(mockedAwareness, [0], sut);
|
|
});
|
|
|
|
it('saves the correct user', () => {
|
|
const sut = new WebsocketConnection(
|
|
mockedWebsocket,
|
|
mockedUser,
|
|
mockedRealtimeNote,
|
|
);
|
|
|
|
expect(sut.getUser()).toBe(mockedUser);
|
|
});
|
|
});
|