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>
45 lines
1.9 KiB
TypeScript
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]);
|
|
});
|
|
});
|