import { beforeEach, describe, expect, it, vi } from "vitest"; const mocks = vi.hoisted(() => ({ tenantUserFindMany: vi.fn(), groupFindMany: vi.fn(), createGroupChat: vi.fn(), getOrCreateDirectMessage: vi.fn(), })); vi.mock("~/utils/db/.server/tenantRls.server", () => ({ withTenantRLS: vi.fn(async (_tenantId: string, operation: (tx: unknown) => Promise) => operation({ tenantUser: { findMany: mocks.tenantUserFindMany }, group: { findMany: mocks.groupFindMany } }) ), })); vi.mock("@hivegrid/chat/lifecycle.server", () => ({ createGroupChat: mocks.createGroupChat, getOrCreateDirectMessage: mocks.getOrCreateDirectMessage, })); import { createChatChannel, loadChatChannelCreatePage } from "./ChatChannelCreateService.server"; const context = { tenantId: "tenant_1", userId: "user_current", tenantUserId: "tenant_user_current", permissions: ["chat.create_channel", "chat.create_dm"], hasModule: true as const, }; describe("AK-P15b chat channel create service", () => { beforeEach(() => { vi.clearAllMocks(); mocks.tenantUserFindMany.mockResolvedValue([ { userId: "user_current", user: { email: "raffael@example.test", firstName: "Raffael", lastName: "Sheikh", avatar: null }, }, { userId: "user_mara", user: { email: "mara@example.test", firstName: "Mara", lastName: "Klein", avatar: " https://example.test/mara.png " }, }, ]); mocks.groupFindMany.mockResolvedValue([ { id: "group_south", name: "Team Süd", description: "Montage", users: [{ userId: "user_mara" }], }, ]); mocks.createGroupChat.mockResolvedValue({ chatId: "chat_group" }); mocks.getOrCreateDirectMessage.mockResolvedValue({ chatId: "chat_dm", dmPairKey: "pair", created: true }); }); it("loads only active tenant users inside tenant RLS and excludes the viewer from options", async () => { const vm = await loadChatChannelCreatePage({ context, requestedMode: "group" }); expect(mocks.tenantUserFindMany).toHaveBeenCalledWith({ where: { tenantId: "tenant_1", status: 2, user: { active: true, pendingDeletion: false, pseudonymized: false }, }, select: { userId: true, user: { select: { email: true, firstName: true, lastName: true, avatar: true } }, }, orderBy: [{ user: { firstName: "asc" } }, { user: { lastName: "asc" } }, { user: { email: "asc" } }], }); expect(mocks.groupFindMany).toHaveBeenCalledWith({ where: { tenantId: "tenant_1" }, select: { id: true, name: true, description: true, users: { where: { user: { active: true, pendingDeletion: false, pseudonymized: false, tenants: { some: { tenantId: "tenant_1", status: 2 } }, }, }, select: { userId: true }, }, }, orderBy: [{ name: "asc" }, { id: "asc" }], }); expect(vm.status).toBe("ready"); if (vm.status !== "ready") throw new Error("fixture must be ready"); expect(vm.data.userOptions).toEqual([ { userId: "user_mara", displayName: "Mara Klein", email: "mara@example.test", avatar: { imageUrl: "https://example.test/mara.png", fallbackLabel: "MK" }, isCurrentUser: false, }, ]); expect(vm.data.groupOptions).toEqual([ { groupId: "group_south", name: "Team Süd", description: "Montage", memberCount: 1 }, ]); }); it("passes group privacy and initial members into the atomic lifecycle", async () => { await expect( createChatChannel({ context, requestId: "request_group", submission: { mode: "group", name: "Montage Nord", description: "Abstimmung", privacy: "private", initialUserIds: ["user_mara"], initialGroupIds: ["group_south"], syncGroupMembership: true, }, }) ).resolves.toEqual({ chatId: "chat_group" }); expect(mocks.createGroupChat).toHaveBeenCalledWith({ tenantId: "tenant_1", userId: "user_current", permissions: context.permissions, requestId: "request_group", name: "Montage Nord", description: "Abstimmung", isPrivate: true, notificationDefault: "all_messages", initialMemberUserIds: ["user_mara"], initialGroupIds: ["group_south"], syncGroupMembership: true, }); }); it("uses the canonical get-or-create lifecycle for direct messages", async () => { await expect( createChatChannel({ context, requestId: "request_dm", submission: { mode: "dm", peerUserId: "user_mara" }, }) ).resolves.toEqual({ chatId: "chat_dm", dmPairKey: "pair", created: true }); expect(mocks.getOrCreateDirectMessage).toHaveBeenCalledWith({ tenantId: "tenant_1", userId: "user_current", permissions: context.permissions, requestId: "request_dm", peerUserId: "user_mara", }); }); });