Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
7.4 kB · 210 lines
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211// Chat Tests, 25.11.28// Tests for the ChatManager multi-instance chat system
import { describe, it, expect, beforeAll, afterAll, vi } from "vitest";import { WebSocket } from "ws";import { ChatManager, chatInstances } from "../chat-manager.mjs";
describe("ChatManager", () => { let chatManager;
beforeAll(async () => { // Create ChatManager without MongoDB for testing chatManager = new ChatManager({ dev: true, mongoConnectionString: null, // Explicitly disable MongoDB }); // Don't call init() - it would try to connect to MongoDB });
describe("Instance Configuration", () => { it("should have three chat instances configured", () => { const instances = Object.keys(chatInstances); expect(instances).toContain("chat-system.aesthetic.computer"); expect(instances).toContain("chat-clock.aesthetic.computer"); expect(instances).toContain("chat.sotce.net"); });
it("should identify chat hosts correctly", () => { expect(chatManager.isChatHost("chat-system.aesthetic.computer")).toBe(true); expect(chatManager.isChatHost("chat-clock.aesthetic.computer")).toBe(true); expect(chatManager.isChatHost("chat.sotce.net")).toBe(true); expect(chatManager.isChatHost("session-server.aesthetic.computer")).toBe(false); expect(chatManager.isChatHost("random.com")).toBe(false); });
it("should get correct instance for host", () => { const instance = chatManager.getInstance("chat-system.aesthetic.computer"); expect(instance).toBeDefined(); expect(instance.config.name).toBe("chat-system"); }); });
describe("Message Packing", () => { it("should pack messages with type and content", () => { const packed = chatManager.pack("test", { hello: "world" }, 1); const parsed = JSON.parse(packed); expect(parsed.type).toBe("test"); expect(parsed.id).toBe(1); expect(JSON.parse(parsed.content)).toEqual({ hello: "world" }); });
it("should handle string content", () => { const packed = chatManager.pack("test", "hello", 1); const parsed = JSON.parse(packed); expect(parsed.content).toBe("hello"); }); });
describe("Chat Status", () => { it("should return status for all instances", () => { const status = chatManager.getStatus(); expect(Array.isArray(status)).toBe(true); expect(status.length).toBe(3); const names = status.map(s => s.name); expect(names).toContain("chat-system"); expect(names).toContain("chat-clock"); expect(names).toContain("chat-sotce"); });
it("should return status for specific host", () => { const status = chatManager.getStatus("chat-system.aesthetic.computer"); expect(status).toBeDefined(); expect(status.name).toBe("chat-system"); expect(status.connections).toBe(0); expect(status.messages).toBe(0); }); });});
describe("Filter Integration", () => { it("should filter profanity", async () => { const { filter } = await import("../filter.mjs"); // Clean text should pass through expect(filter("hello world")).toBe("hello world"); // Profanity should be filtered (replaced with underscores) // Note: actual profanity filtering is tested in the obscenity library });});
describe("Redact Module", () => { it("should redact message text", async () => { const { redact, unredact } = await import("../redact.mjs"); const msg = { text: "hello world", from: "@user" }; redact(msg); expect(msg.text).toBe("_____ _____"); expect(msg.redactedText).toBe("hello world"); });
it("should unredact message text", async () => { const { redact, unredact } = await import("../redact.mjs"); const msg = { text: "hello world", from: "@user" }; redact(msg); unredact(msg); expect(msg.text).toBe("hello world"); });});
describe("Message Editing", () => { // A ChatManager with no MongoDB: auth comes from the pre-authorized // connection cache, and every DB write is skipped by its own guard. const manager = new ChatManager({ dev: true, mongoConnectionString: null }); const instance = manager.getInstance("chat-clock.aesthetic.computer");
function seed() { instance.messages.length = 0; instance.messages.push({ id: "m1", sub: "user1", from: "@klok", text: "goddag klok", when: new Date("2026-08-14T12:00:00Z"), }); instance.connections = {}; instance.authorizedConnections = { c1: { token: "tok1", user: { sub: "user1" } }, c2: { token: "tok2", user: { sub: "user2" } }, }; }
function wsFor() { return { send: vi.fn() }; }
it("edits your own message in place and broadcasts message:edit", async () => { seed(); const ws = wsFor(); const listener = { readyState: WebSocket.OPEN, send: vi.fn() }; instance.connections = { c9: listener };
await manager.handleEditMessage(instance, ws, "c1", { content: { token: "tok1", sub: "user1", id: "m1", text: "farvel klok " }, });
expect(instance.messages[0].text).toBe("farvel klok"); // trailing space trimmed expect(instance.messages[0].edited).toBe(true); expect(ws.send).not.toHaveBeenCalled(); // no error packets back
expect(listener.send).toHaveBeenCalledTimes(1); const packet = JSON.parse(listener.send.mock.calls[0][0]); expect(packet.type).toBe("message:edit"); const content = JSON.parse(packet.content); expect(content).toMatchObject({ id: "m1", text: "farvel klok", edited: true }); });
it("refuses to edit someone else's message", async () => { seed(); const ws = wsFor(); await manager.handleEditMessage(instance, ws, "c2", { content: { token: "tok2", sub: "user2", id: "m1", text: "hijacked" }, }); expect(instance.messages[0].text).toBe("goddag klok"); const packet = JSON.parse(ws.send.mock.calls[0][0]); expect(packet.type).toBe("error"); });
it("refuses a token/sub mismatch", async () => { seed(); const ws = wsFor(); await manager.handleEditMessage(instance, ws, "c2", { content: { token: "tok2", sub: "user1", id: "m1", text: "spoofed" }, }); expect(instance.messages[0].text).toBe("goddag klok"); const packet = JSON.parse(ws.send.mock.calls[0][0]); expect(packet.type).toBe("unauthorized"); });
it("refuses to edit a deleted message", async () => { seed(); instance.messages[0].deleted = true; const ws = wsFor(); await manager.handleEditMessage(instance, ws, "c1", { content: { token: "tok1", sub: "user1", id: "m1", text: "necromancy" }, }); expect(instance.messages[0].text).toBe("goddag klok"); const packet = JSON.parse(ws.send.mock.calls[0][0]); expect(packet.type).toBe("error"); });
it("rejects over-length and empty edits", async () => { seed(); const ws = wsFor(); await manager.handleEditMessage(instance, ws, "c1", { content: { token: "tok1", sub: "user1", id: "m1", text: "x".repeat(129) }, }); expect(JSON.parse(ws.send.mock.calls[0][0]).type).toBe("too-long");
await manager.handleEditMessage(instance, ws, "c1", { content: { token: "tok1", sub: "user1", id: "m1", text: " " }, }); expect(JSON.parse(ws.send.mock.calls[1][0]).type).toBe("error"); expect(instance.messages[0].text).toBe("goddag klok"); });});