import { describe, expect, it } from "vitest"; import { reconcileMessages } from "../../src/reconcile"; import { sessionMemory } from "../../src/session"; import { SingleFlight } from "../../src/single-flight"; import { websocketJwtProtocol } from "../../src/realtime"; import type { Message } from "../../src/types"; const message = (id: string, createdAt: string, status: Message["delivery_status"] = "accepted"): Message => ({ message_id: id, dialog_id: "dialog", sender_type: "client", content_kind: "text", text: "Тест", attachments: [], safety_status: "allowed", delivery_status: status, created_at: createdAt, }); describe("reconcileMessages", () => { it("устраняет дубли, обновляет статус и сортирует сообщения", () => { const result = reconcileMessages( [message("2", "2026-01-02T00:00:00Z"), message("1", "2026-01-01T00:00:00Z")], [message("2", "2026-01-02T00:00:00Z", "delivered"), message("3", "2026-01-03T00:00:00Z")], ); expect(result.map((item) => item.message_id)).toEqual(["1", "2", "3"]); expect(result[1]?.delivery_status).toBe("delivered"); }); }); describe("UX session memory", () => { it("хранит идентификатор только в памяти и очищает его", () => { sessionMemory.set("ux-test"); expect(sessionMemory.id).toBe("ux-test"); sessionMemory.clear(); expect(sessionMemory.id).toBeNull(); expect(localStorage.getItem("ux_session_id")).toBeNull(); }); }); describe("SingleFlight", () => { it("объединяет параллельные refresh операции", async () => { const flight = new SingleFlight(); let calls = 0; const operation = async () => { calls++; await Promise.resolve(); return 42; }; const [first, second, third] = await Promise.all([ flight.run(operation), flight.run(operation), flight.run(operation), ]); expect([first, second, third]).toEqual([42, 42, 42]); expect(calls).toBe(1); }); }); describe("WebSocket authentication protocol", () => { it("кодирует JWT как canonical han.jwt.", () => { const protocol = websocketJwtProtocol("header.payload.signature"); expect(protocol).toBe("han.jwt.aGVhZGVyLnBheWxvYWQuc2lnbmF0dXJl"); expect(protocol).not.toContain("="); }); });