Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/apps/web/app/modules/chat/services/ChatChannelCreateService.server.test.ts
T

157 lines
5.0 KiB
TypeScript

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<unknown>) =>
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",
});
});
});