import { strict as assert } from "node:assert"; import { test } from "node:test"; import { AnnouncementAudience as A, EventParticipationStatus as S, RsvpMode, TerminType, UserRole, } from "@prisma/client"; import { announcementRecipientWhere, visibleAnnouncementAudiences, } from "../src/lib/announcement-access"; import { hasMissingRsvp, rsvpSubmissionSchema, suggestedRsvpMode, type RsvpEventDto, } from "../src/lib/rsvp"; const family = { eventId: "event", mode: RsvpMode.FAMILY, status: S.ATTENDING, adultCount: 2, }; test("Familienzusage braucht eine positive ganze Erwachsenenanzahl", () => { assert.equal(rsvpSubmissionSchema.safeParse(family).success, true); for (const adultCount of [0, -1, 1.5, 2147483648, NaN]) { assert.equal( rsvpSubmissionSchema.safeParse({ ...family, adultCount }).success, false, ); } }); test("Familienabsage setzt Erwachsenenanzahl auf null", () => { assert.equal( rsvpSubmissionSchema.safeParse({ ...family, status: S.NOT_ATTENDING, adultCount: 0, }).success, true, ); assert.equal( rsvpSubmissionSchema.safeParse({ ...family, status: S.NOT_ATTENDING }) .success, false, ); }); test("Kinderantworten dürfen verschiedene Zusagen enthalten, keine Duplikate oder leere Liste", () => { const payload = { eventId: "event", mode: RsvpMode.CHILD, responses: [ { childId: "a", status: S.ATTENDING }, { childId: "b", status: S.NOT_ATTENDING }, ], }; assert.equal(rsvpSubmissionSchema.safeParse(payload).success, true); assert.equal( rsvpSubmissionSchema.safeParse({ ...payload, responses: [] }).success, false, ); assert.equal( rsvpSubmissionSchema.safeParse({ ...payload, responses: [payload.responses[0], payload.responses[0]], }).success, false, ); }); test("Eltern sehen Elternmeldungen und gemeinsame Meldungen", () => { assert.deepEqual( visibleAnnouncementAudiences({ role: UserRole.ELTERN, familyId: "f" }), [A.ALLE, A.ELTERN], ); assert.deepEqual( visibleAnnouncementAudiences({ role: UserRole.KOORDINATOR, familyId: "f" }), [A.ALLE, A.ELTERN], ); }); test("Erzieherkonto erhält auch mit Haushaltszuordnung keine Elternmeldungen", () => { assert.deepEqual( visibleAnnouncementAudiences({ role: UserRole.ERZIEHER, familyId: "f" }), [A.ALLE, A.ERZIEHER], ); }); test("Admin darf alle Meldungen verwalten", () => { assert.deepEqual( new Set(visibleAnnouncementAudiences({ role: UserRole.ADMIN })), new Set(Object.values(A)), ); }); test("E-Mail-Gruppen schließen Erzieher aus Elternempfängern aus", () => { assert.deepEqual(announcementRecipientWhere(A.ERZIEHER), { role: UserRole.ERZIEHER, }); assert.deepEqual(announcementRecipientWhere(A.ELTERN), { role: { not: UserRole.ERZIEHER }, OR: [{ familyId: { not: null } }, { role: UserRole.ELTERN }], }); }); test("Die Rückmeldekarte verschwindet erst, wenn jedes Kind geantwortet hat", () => { const event: RsvpEventDto = { id: "e", title: "Ausflug", startDate: "2030-01-01", rsvpDeadline: null, mode: RsvpMode.CHILD, canReply: true, familyResponse: null, children: [ { id: "a", name: "A", status: S.ATTENDING }, { id: "b", name: "B", status: null }, ], }; assert.equal(hasMissingRsvp(event), true); assert.equal( hasMissingRsvp({ ...event, children: event.children.map((child) => ({ ...child, status: S.NOT_ATTENDING, })), }), false, ); assert.equal(hasMissingRsvp({ ...event, mode: RsvpMode.FAMILY }), true); assert.equal( hasMissingRsvp({ ...event, mode: RsvpMode.FAMILY, familyResponse: { status: S.NOT_ATTENDING, adultCount: 0 }, }), false, ); }); test("Antwortart wird passend zur Terminart vorgeschlagen", () => { assert.equal(suggestedRsvpMode(TerminType.ELTERNABEND), RsvpMode.FAMILY); assert.equal(suggestedRsvpMode(TerminType.SONSTIGES), RsvpMode.CHILD); });