Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/utils/db/permissions/userGroups.db.server.test.ts
T

87 lines
3.7 KiB
TypeScript

// @vitest-environment node
import { beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("../../db.server", () => ({
db: {
groupUser: {
create: vi.fn(),
createMany: vi.fn(),
deleteMany: vi.fn(),
},
$transaction: vi.fn(),
},
}));
import { db } from "../../db.server";
import { createUserGroup, createUserGroups, deleteGroupUsers, deleteUserGroup, replaceGroupUsers } from "./userGroups.db.server";
const dbMock = vi.mocked(db);
describe("user group persistence", () => {
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(dbMock.$transaction).mockImplementation((async (callback: (tx: typeof dbMock) => Promise<unknown>) => callback(dbMock)) as never);
});
it("creates and deletes single group memberships", async () => {
vi.mocked(dbMock.groupUser.create).mockResolvedValueOnce({ id: "group_user_1" } as never);
vi.mocked(dbMock.groupUser.deleteMany).mockResolvedValueOnce({ count: 1 } as never);
vi.mocked(dbMock.groupUser.deleteMany).mockResolvedValueOnce({ count: 2 } as never);
await expect(createUserGroup("user_1", "group_1")).resolves.toEqual({ id: "group_user_1" });
await expect(deleteUserGroup("user_1", "group_1")).resolves.toEqual({ count: 1 });
await expect(deleteGroupUsers("group_1", "tenant_1")).resolves.toEqual({ count: 2 });
expect(dbMock.groupUser.create).toHaveBeenCalledWith({ data: { userId: "user_1", groupId: "group_1" } });
expect(dbMock.groupUser.deleteMany).toHaveBeenNthCalledWith(1, { where: { userId: "user_1", groupId: "group_1" } });
expect(dbMock.groupUser.deleteMany).toHaveBeenNthCalledWith(2, { where: { groupId: "group_1", group: { tenantId: "tenant_1" } } });
});
it("bulk-creates deduplicated group memberships with database duplicate protection", async () => {
vi.mocked(dbMock.groupUser.createMany).mockResolvedValueOnce({ count: 2 } as never);
await expect(createUserGroups("group_1", ["user_1", "user_2", "user_1"])).resolves.toEqual({ count: 2 });
expect(dbMock.groupUser.createMany).toHaveBeenCalledWith({
data: [
{ userId: "user_1", groupId: "group_1" },
{ userId: "user_2", groupId: "group_1" },
],
skipDuplicates: true,
});
});
it("skips bulk membership writes when no users are selected", async () => {
await expect(createUserGroups("group_1", [])).resolves.toEqual({ count: 0 });
expect(dbMock.groupUser.createMany).not.toHaveBeenCalled();
});
it("replaces group memberships inside one transaction", async () => {
vi.mocked(dbMock.groupUser.deleteMany).mockResolvedValueOnce({ count: 3 } as never);
vi.mocked(dbMock.groupUser.createMany).mockResolvedValueOnce({ count: 2 } as never);
await expect(replaceGroupUsers("group_1", "tenant_1", ["user_1", "user_2", "user_1"])).resolves.toEqual({ count: 2 });
expect(dbMock.$transaction).toHaveBeenCalledTimes(1);
expect(dbMock.groupUser.deleteMany).toHaveBeenCalledWith({ where: { groupId: "group_1", group: { tenantId: "tenant_1" } } });
expect(dbMock.groupUser.createMany).toHaveBeenCalledWith({
data: [
{ userId: "user_1", groupId: "group_1" },
{ userId: "user_2", groupId: "group_1" },
],
skipDuplicates: true,
});
});
it("replaces group memberships with an empty set without bulk insert", async () => {
vi.mocked(dbMock.groupUser.deleteMany).mockResolvedValueOnce({ count: 3 } as never);
await expect(replaceGroupUsers("group_1", "tenant_1", [])).resolves.toEqual({ count: 0 });
expect(dbMock.$transaction).toHaveBeenCalledTimes(1);
expect(dbMock.groupUser.deleteMany).toHaveBeenCalledWith({ where: { groupId: "group_1", group: { tenantId: "tenant_1" } } });
expect(dbMock.groupUser.createMany).not.toHaveBeenCalled();
});
});