/** * ConversationTabs Component Tests * * Tests the connection status colour mapping and unread message detection * logic used by the ConversationTabs component. * * What this component does: * - Displays one tab per conversation * - Each tab shows a coloured dot for its connection state * - Inactive tabs with new messages show an animated blue dot badge * - Tabs can be renamed by double-clicking * - Tabs can be reordered by drag-and-drop * - New tabs created with Ctrl+T, closed with Ctrl+W * * Manual testing checklist: * - [ ] Connected tabs show a green dot * - [ ] Connecting tabs show a yellow dot * - [ ] Disconnected tabs show a red dot * - [ ] Active tab never shows the unread badge * - [ ] Inactive tab shows blue pulsing dot when it receives new messages * - [ ] Switching to a tab clears the unread indicator * - [ ] Double-clicking a tab name enables inline editing * - [ ] Tabs can be dragged to reorder */ import { describe, it, expect } from "vitest"; type ConnectionStatus = "connected" | "connecting" | "disconnected"; function getConnectionStatusColor(status: ConnectionStatus | string): string { switch (status) { case "connected": return "bg-green-500"; case "connecting": return "bg-yellow-500"; case "disconnected": return "bg-red-500"; default: return "bg-gray-500"; } } function hasUnreadMessages( id: string, conversationLineCount: number, activeConversationId: string | null, lastSeenMessageCount: Map ): boolean { if (id === activeConversationId) return false; const lastSeen = lastSeenMessageCount.get(id) ?? 0; return conversationLineCount > lastSeen; } // --- describe("getConnectionStatusColor", () => { it("returns green for connected status", () => { expect(getConnectionStatusColor("connected")).toBe("bg-green-500"); }); it("returns yellow for connecting status", () => { expect(getConnectionStatusColor("connecting")).toBe("bg-yellow-500"); }); it("returns red for disconnected status", () => { expect(getConnectionStatusColor("disconnected")).toBe("bg-red-500"); }); it("returns grey for unknown status (fallback)", () => { expect(getConnectionStatusColor("error")).toBe("bg-gray-500"); expect(getConnectionStatusColor("")).toBe("bg-gray-500"); }); }); describe("hasUnreadMessages", () => { it("returns false for the active conversation regardless of message count", () => { const lastSeen = new Map([["tab-1", 0]]); expect(hasUnreadMessages("tab-1", 10, "tab-1", lastSeen)).toBe(false); }); it("returns true when an inactive tab has more messages than last seen", () => { const lastSeen = new Map([["tab-1", 5]]); expect(hasUnreadMessages("tab-1", 10, "tab-2", lastSeen)).toBe(true); }); it("returns false when an inactive tab has no new messages", () => { const lastSeen = new Map([["tab-1", 10]]); expect(hasUnreadMessages("tab-1", 10, "tab-2", lastSeen)).toBe(false); }); it("returns false when an inactive tab has fewer messages than last seen", () => { const lastSeen = new Map([["tab-1", 15]]); expect(hasUnreadMessages("tab-1", 10, "tab-2", lastSeen)).toBe(false); }); it("treats a tab with no last-seen record as having 0 messages seen", () => { const lastSeen = new Map(); // Tab has 1 message but no entry in lastSeen → treated as 0 seen → unread expect(hasUnreadMessages("tab-1", 1, "tab-2", lastSeen)).toBe(true); }); it("returns false for an untracked tab with 0 messages", () => { const lastSeen = new Map(); expect(hasUnreadMessages("tab-1", 0, "tab-2", lastSeen)).toBe(false); }); it("handles null activeConversationId (no active tab)", () => { const lastSeen = new Map([["tab-1", 3]]); expect(hasUnreadMessages("tab-1", 10, null, lastSeen)).toBe(true); }); });