mirror of
https://github.com/outline/outline.git
synced 2026-01-05 02:30:05 -06:00
111 lines
2.9 KiB
TypeScript
111 lines
2.9 KiB
TypeScript
import { Server } from "@hocuspocus/server";
|
|
import WebSocket from "ws";
|
|
import EDITOR_VERSION from "@shared/editor/version";
|
|
import { sleep } from "@shared/utils/timers";
|
|
import { ConnectionLimitExtension } from "./ConnectionLimitExtension";
|
|
import { EditorVersionExtension } from "./EditorVersionExtension";
|
|
|
|
jest.mock("@server/env", () => ({
|
|
COLLABORATION_MAX_CLIENTS_PER_DOCUMENT: 2,
|
|
}));
|
|
|
|
describe("ConnectionLimitExtension", () => {
|
|
let server: typeof Server;
|
|
let extension: ConnectionLimitExtension;
|
|
const port = 12345;
|
|
const url = `ws://localhost:${port}`;
|
|
const documentName = "test";
|
|
|
|
beforeEach(async () => {
|
|
extension = new ConnectionLimitExtension();
|
|
server = Server.configure({
|
|
port,
|
|
extensions: [extension, new EditorVersionExtension()],
|
|
quiet: true,
|
|
});
|
|
await server.listen();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await server.destroy();
|
|
});
|
|
|
|
const getConnections = () =>
|
|
extension.connectionsByDocument.get(documentName)?.size ?? 0;
|
|
|
|
const createWebSocket = (editorVersion = EDITOR_VERSION) =>
|
|
new Promise<WebSocket>((resolve, reject) => {
|
|
const ws = new WebSocket(
|
|
`${url}/${documentName}?editorVersion=${editorVersion}`
|
|
);
|
|
ws.on("open", () => resolve(ws));
|
|
ws.on("error", reject);
|
|
});
|
|
|
|
it("should allow connections within limit", async () => {
|
|
const ws1 = await createWebSocket();
|
|
const ws2 = await createWebSocket();
|
|
|
|
expect(ws1.readyState).toBe(WebSocket.OPEN);
|
|
expect(ws2.readyState).toBe(WebSocket.OPEN);
|
|
expect(getConnections()).toBe(2);
|
|
|
|
ws1.close();
|
|
ws2.close();
|
|
|
|
await sleep(250);
|
|
expect(getConnections()).toBe(0);
|
|
});
|
|
|
|
it("should close connections exceeding limit", async () => {
|
|
const ws1 = await createWebSocket();
|
|
const ws2 = await createWebSocket();
|
|
|
|
const ws3 = await createWebSocket();
|
|
await sleep(250);
|
|
|
|
expect(ws3.readyState).toBe(WebSocket.CLOSED);
|
|
expect(ws2.readyState).toBe(WebSocket.OPEN);
|
|
expect(ws1.readyState).toBe(WebSocket.OPEN);
|
|
expect(getConnections()).toBe(2);
|
|
|
|
ws1.close();
|
|
ws2.close();
|
|
|
|
await sleep(250);
|
|
expect(getConnections()).toBe(0);
|
|
});
|
|
|
|
it("should handle connections closed by other extensions", async () => {
|
|
const ws1 = await createWebSocket();
|
|
|
|
// Create a connection that will be closed by the EditorVersionExtension
|
|
const ws2 = await createWebSocket("1.0.0");
|
|
|
|
ws1.close();
|
|
ws2.close();
|
|
|
|
await sleep(250);
|
|
expect(getConnections()).toBe(0);
|
|
});
|
|
|
|
it("should allow new connection after disconnect", async () => {
|
|
const ws1 = await createWebSocket();
|
|
const ws2 = await createWebSocket();
|
|
|
|
ws1.close();
|
|
await sleep(250);
|
|
expect(getConnections()).toBe(1);
|
|
|
|
const ws3 = await createWebSocket();
|
|
expect(ws3.readyState).toBe(WebSocket.OPEN);
|
|
expect(getConnections()).toBe(2);
|
|
|
|
ws2.close();
|
|
ws3.close();
|
|
|
|
await sleep(250);
|
|
expect(getConnections()).toBe(0);
|
|
});
|
|
});
|