110 lines
3.3 KiB
TypeScript
110 lines
3.3 KiB
TypeScript
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",
|
|
});
|
|
});
|
|
});
|