Kuma/tests/rooms/room-actions.test.ts
2026-10-02 00:41:54 +02:00

133 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, it, expect, vi, beforeEach } from "vitest";
vi.mock("@/src/lib/prisma", () => ({
prisma: {
room: { findUnique: vi.fn(), update: vi.fn() },
courseBooking: { findMany: vi.fn() },
course: { findMany: vi.fn(), updateMany: vi.fn() },
},
}));
vi.mock("@/src/lib/auth/getUser", () => ({
getUserData: vi.fn(),
isManager: (u: { role: string }) => u?.role === "manager",
isEmployee: (u: { role: string }) => u?.role === "employee",
getEffectiveManagerId: (u: { role: string; id: string }) => u.id,
}));
vi.mock("next/cache", () => ({ revalidatePath: vi.fn() }));
vi.mock("@/src/modules/courses/lib/public-courses-cache", () => ({
refreshPublicCourses: vi.fn(),
}));
import { prisma } from "@/src/lib/prisma";
import { getUserData } from "@/src/lib/auth/getUser";
import { updateRoom } from "@/src/modules/rooms/actions/room-actions";
import { refreshPublicCourses } from "@/src/modules/courses/lib/public-courses-cache";
import type { FloorPlan, FloorPlanItem } from "@/src/modules/rooms/lib/floor-plan";
const reformer = (id: string, label: string, x: number): FloorPlanItem => ({
id,
type: "reformer",
x,
y: 1.5,
rotation: 0,
label,
});
const plan = (items: FloorPlanItem[]): FloorPlan => ({ width: 8, depth: 6, items });
const threeReformers = plan([
reformer("r1", "1", 1),
reformer("r2", "2", 2),
reformer("r3", "3", 3),
]);
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(getUserData).mockResolvedValue({ id: "mgr-1", role: "manager" } as never);
vi.mocked(prisma.room.findUnique).mockResolvedValue({
id: "room-1",
createdBy: "mgr-1",
floorPlan: threeReformers,
} as never);
vi.mocked(prisma.courseBooking.findMany).mockResolvedValue([]);
vi.mocked(prisma.course.findMany).mockResolvedValue([]);
});
describe("updateRoom – gebuchte Plätze", () => {
it("verhindert das Entfernen eines Geräts mit kommender Buchung", async () => {
vi.mocked(prisma.courseBooking.findMany).mockResolvedValue([{ spotId: "r3" }] as never);
const result = await updateRoom("room-1", {
name: "Reformer-Raum",
floorPlan: plan([reformer("r1", "1", 1), reformer("r2", "2", 2)]),
});
expect(result).toMatchObject({ success: false });
expect(result.error).toContain("Reformer 3");
expect(prisma.room.update).not.toHaveBeenCalled();
});
it("verhindert das Umnummerieren eines gebuchten Geräts", async () => {
vi.mocked(prisma.courseBooking.findMany).mockResolvedValue([{ spotId: "r1" }] as never);
const result = await updateRoom("room-1", {
name: "Reformer-Raum",
floorPlan: plan([reformer("r1", "9", 1), reformer("r2", "2", 2), reformer("r3", "3", 3)]),
});
expect(result.success).toBe(false);
expect(prisma.room.update).not.toHaveBeenCalled();
});
it("erlaubt das Verschieben gebuchter Geräte, ohne Buchungen zu prüfen", async () => {
const moved = plan([reformer("r1", "1", 5), reformer("r2", "2", 6), reformer("r3", "3", 7)]);
const result = await updateRoom("room-1", { name: "Reformer-Raum", floorPlan: moved });
expect(result.success).toBe(true);
expect(prisma.courseBooking.findMany).not.toHaveBeenCalled();
expect(vi.mocked(prisma.room.update).mock.calls[0][0].data.floorPlan).toEqual(moved);
});
});
describe("updateRoom – Teilnehmerzahl", () => {
it("senkt die Teilnehmerzahl kommender Platzwahl-Kurse auf die neue Platzanzahl", async () => {
vi.mocked(prisma.course.findMany).mockResolvedValue([
{ id: "c1", businessId: "biz-1", isStandingOrder: false },
{ id: "c2", businessId: "biz-1", isStandingOrder: false },
] as never);
const result = await updateRoom("room-1", {
name: "Reformer-Raum",
floorPlan: plan([reformer("r1", "1", 1), reformer("r2", "2", 2)]),
});
expect(result.success).toBe(true);
expect(result.message).toContain("2 kommende Kurse");
expect(vi.mocked(prisma.course.findMany).mock.calls[0][0]!.where).toMatchObject({
room: "room-1",
spotBooking: true,
maxParticipants: { gt: 2 },
});
expect(prisma.course.updateMany).toHaveBeenCalledWith({
where: { id: { in: ["c1", "c2"] } },
data: { maxParticipants: 2 },
});
expect(refreshPublicCourses).toHaveBeenCalledWith("biz-1", "biz-1");
});
it("lässt die Teilnehmerzahl in Ruhe, wenn der Grundriss ganz entfernt wird", async () => {
vi.mocked(prisma.room.findUnique).mockResolvedValue({
id: "room-1",
createdBy: "mgr-1",
floorPlan: null,
} as never);
const result = await updateRoom("room-1", { name: "Matten-Raum", floorPlan: null });
expect(result.success).toBe(true);
expect(prisma.course.findMany).not.toHaveBeenCalled();
});
});