import { beforeEach, describe, expect, test } from "vitest"; import { contactRequestSchema, submitContactRequest } from "@/lib/contact"; import { resetEnvCache } from "@/lib/env"; import { db, resetDb, SECRET, setupCamp } from "./support/db"; const NOW = new Date("2026-11-15T10:00:00Z"); const ctx = { now: NOW, secret: SECRET }; function request(overrides: Record = {}) { return contactRequestSchema.parse({ name: "Lena Beispiel", email: "lena@example.org", phone: "+49 170 1234567", availability: "abends", message: "Passt das Camp für Einsteigerinnen?", privacy: true, website: "", ...overrides, }); } beforeEach(async () => { await resetDb(); await setupCamp({ organizerEmail: "veranstalter@example.org" }); delete process.env.ADMIN_NOTIFY_EMAIL; resetEnvCache(); }); describe("Erstgespräch", () => { test("Anfrage landet als Mail beim Veranstalter, mit allen Angaben", async () => { expect(await submitContactRequest(db, request(), ctx)).toEqual({ ok: true, delivered: true }); const mails = await db.emailMessage.findMany(); expect(mails).toHaveLength(1); expect(mails[0]!.toAddress).toBe("veranstalter@example.org"); expect(mails[0]!.subject).toContain("Lena Beispiel"); expect(mails[0]!.textBody).toContain("lena@example.org"); expect(mails[0]!.textBody).toContain("Passt das Camp für Einsteigerinnen?"); expect(mails[0]!.htmlBody).toContain("mailto:lena%40example.org"); }); test("doppelt abgeschickt ergibt nur eine Mail", async () => { await submitContactRequest(db, request(), ctx); await submitContactRequest(db, request(), { ...ctx, now: new Date(NOW.getTime() + 10_000) }); expect(await db.emailMessage.count()).toBe(1); }); test("Bot im Honeypot: Erfolg vortäuschen, nichts verschicken", async () => { expect(await submitContactRequest(db, request({ website: "https://spam.example" }), ctx)).toEqual({ ok: true, delivered: false }); expect(await db.emailMessage.count()).toBe(0); }); test("ohne Empfänger nicht verfügbar, mit ADMIN_NOTIFY_EMAIL als Ersatz", async () => { await setupCamp({ organizerEmail: null }); expect(await submitContactRequest(db, request(), ctx)).toEqual({ ok: false, error: "NOT_CONFIGURED" }); process.env.ADMIN_NOTIFY_EMAIL = "admin@example.org"; resetEnvCache(); await submitContactRequest(db, request(), ctx); expect((await db.emailMessage.findFirstOrThrow()).toAddress).toBe("admin@example.org"); }); test("Pflichtangaben und Einwilligung werden serverseitig geprüft", () => { expect(contactRequestSchema.safeParse({ name: "L", email: "kein-mail", privacy: false }).success).toBe(false); expect(contactRequestSchema.safeParse({ name: "Lena", email: "lena@example.org", privacy: false }).success).toBe(false); const base = { name: "Lena", email: "lena@example.org", privacy: true }; expect(contactRequestSchema.safeParse(base).success).toBe(false); expect(contactRequestSchema.safeParse({ ...base, phone: " " }).success).toBe(false); expect(contactRequestSchema.safeParse({ ...base, phone: "abc123456" }).success).toBe(false); expect(request({ phone: " +49 170 1234567 " }).phone).toBe("+49 170 1234567"); }); });