import { beforeEach, describe, expect, it, vi } from "vitest"; import { CHAT_PERMISSIONS } from "@hivegrid/chat"; const mocks = vi.hoisted(() => ({ list: vi.fn() })); vi.mock("@hivegrid/chat/message-discovery.server", () => ({ listChatMessageDiscovery: (...args: unknown[]) => mocks.list(...args), })); import { loadChatMessageDiscovery } from "./ChatMessageDiscoveryService.server"; const context = { tenantId: "tenant_1", userId: "viewer_1", tenantUserId: "tenant_user_1", permissions: [CHAT_PERMISSIONS.readOwnChannels], hasModule: true, } as const; const labels = { directMessage: "Direct message", unnamedGroup: "Unnamed group", unnamedProject: "Project chat", unknownUser: "Unknown user", } as const; describe("ChatMessageDiscoveryService", () => { beforeEach(() => { vi.clearAllMocks(); mocks.list.mockResolvedValue({ messages: [], nextCursor: null }); }); it("maps repository records to pure VM rows and resolves a DM counterpart", async () => { mocks.list.mockResolvedValue({ nextCursor: "cursor_1", messages: [ { id: "message_1", chatId: "chat_dm", channelKind: "dm", channelName: null, projectId: null, authorUserId: "peer_1", body: "Heat pump update", parentMessageId: null, createdAtIso: "2026-07-16T11:00:00.000Z", participants: [ { userId: "viewer_1", displayName: "Raffael Sheikh", avatarUrl: null }, { userId: "peer_1", displayName: "Ada Lovelace", avatarUrl: "/avatars/ada" }, ], }, ], }); const vm = await loadChatMessageDiscovery({ context, tenantSlug: "demo", mode: "search", query: "heat", labels }); expect(mocks.list).toHaveBeenCalledWith({ tenantId: "tenant_1", userId: "viewer_1", permissions: [CHAT_PERMISSIONS.readOwnChannels], mode: "search", query: "heat", }); expect(vm).toMatchObject({ status: "ready", data: { nextCursor: "cursor_1", rows: [ { channelTitle: "Ada Lovelace", authorLabel: "Ada Lovelace", authorAvatar: { imageUrl: "/avatars/ada", fallbackLabel: "AL" }, detailHref: "/demo/chat/chat_dm?message=message_1#message-message_1", }, ], }, }); }); it("uses localized fallbacks without exposing unresolved identities", async () => { mocks.list.mockResolvedValue({ nextCursor: null, messages: [ { id: "message_2", chatId: "chat_project", channelKind: "project", channelName: null, projectId: "project_1", authorUserId: "former_user", body: "Archived author stays readable", parentMessageId: "parent_1", createdAtIso: "2026-07-16T10:00:00.000Z", participants: [], }, ], }); const vm = await loadChatMessageDiscovery({ context, tenantSlug: "demo", mode: "mentions", labels }); expect(vm.status === "ready" && vm.data.rows[0]).toMatchObject({ channelTitle: "Project chat", authorLabel: "Unknown user", authorAvatar: { fallbackLabel: "UU" }, isThreadReply: true, detailHref: "/demo/chat/chat_project/thread/parent_1?message=message_2#message-message_2", }); }); });