Files
nexarch/web/mail-postfach/lib/api.test.ts
patrickandClaude Sonnet 5 9b1661d6ff UX-01: postfach-ordneransicht
Postfach- und Ordneransicht fuer archivierte Mails (Next.js/React/TS,
@nexarch/shl). Ordnerbaum (aus der flachen Postfachliste der Mail-API
clientseitig aufgebaut), virtualisierte Nachrichtenliste mit Sortierung
nach Datum/Absender/Betreff, Grundsuche. Aufbau nach etabliertem Muster
(web/mail-search fuer die App-Struktur, web/dms-browser fuer Ordnerbaum/
virtualisierte Liste), bewusst schlicht gehalten (Mailpit/MailHog als
Vorbild, nicht die Komplexitaet eines nativen Mailprogramms).

Automatisierte Tests je Akzeptanzkriterium, inkl. eines echten
Backend-Integrationstests (e2e/ux01.e2e.test.ts) gegen den echten
mailapi.Server (mail/cmd/mailpostfach-fixture) mit zwei Mandanten und
einem gleichnamigen Ordner — keine Mandanten-Isolationslogik wird
gemockt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-16 06:54:40 +00:00

45 lines
1.9 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import { fetchMailboxes, fetchMessages, type Fetcher } from "./api";
function fakeFetcher(body: unknown, status = 200): Fetcher {
return vi.fn().mockResolvedValue(new Response(JSON.stringify(body), { status }));
}
describe("fetchMailboxes", () => {
it("ruft /mailboxes auf und entpackt die Liste", async () => {
const fetcher = fakeFetcher({ mailboxes: [{ name: "posteingang", messageCount: 3 }] });
const result = await fetchMailboxes(fetcher);
expect(result).toEqual([{ name: "posteingang", messageCount: 3 }]);
expect(fetcher).toHaveBeenCalledWith(expect.stringContaining("/mailboxes"));
});
it("wirft bei Fehlerstatus", async () => {
const fetcher = fakeFetcher({ error: "nicht angemeldet" }, 401);
await expect(fetchMailboxes(fetcher)).rejects.toThrow();
});
});
describe("fetchMessages", () => {
it("haengt mailbox und q als Query-Parameter an, wenn gesetzt", async () => {
const fetcher = fakeFetcher({ messages: [] });
await fetchMessages({ mailbox: "archiv", q: "rechnung" }, fetcher);
const url = new URL((fetcher as ReturnType<typeof vi.fn>).mock.calls[0][0] as string);
expect(url.searchParams.get("mailbox")).toBe("archiv");
expect(url.searchParams.get("q")).toBe("rechnung");
});
it("laesst mailbox/q weg, wenn nicht gesetzt", async () => {
const fetcher = fakeFetcher({ messages: [] });
await fetchMessages({}, fetcher);
const url = new URL((fetcher as ReturnType<typeof vi.fn>).mock.calls[0][0] as string);
expect(url.searchParams.has("mailbox")).toBe(false);
expect(url.searchParams.has("q")).toBe(false);
});
it("entpackt die Nachrichtenliste aus der Antwort", async () => {
const message = { messageId: "m1", subject: "Betreff", sender: "a@b.test", mailbox: "posteingang", sentAt: 100 };
const fetcher = fakeFetcher({ messages: [message] });
expect(await fetchMessages({}, fetcher)).toEqual([message]);
});
});