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>
35 lines
1.4 KiB
TypeScript
35 lines
1.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { computeVisibleRange, totalContentHeight } from "./virtualization";
|
|
|
|
describe("computeVisibleRange (Akzeptanzkriterium 3: mehrere tausend Nachrichten bleiben ruckelfrei)", () => {
|
|
it("rendert bei 3000 Zeilen nur einen kleinen sichtbaren Ausschnitt, nicht alle", () => {
|
|
const range = computeVisibleRange(0, 600, 32, 3000, 5);
|
|
const rendered = range.endIndex - range.startIndex;
|
|
expect(rendered).toBeLessThan(50);
|
|
expect(rendered).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("verschiebt den sichtbaren Bereich beim Scrollen", () => {
|
|
const top = computeVisibleRange(0, 600, 32, 3000, 0);
|
|
const scrolled = computeVisibleRange(3200, 600, 32, 3000, 0);
|
|
expect(scrolled.startIndex).toBeGreaterThan(top.startIndex);
|
|
});
|
|
|
|
it("bleibt am Ende der Liste innerhalb der Grenzen", () => {
|
|
const range = computeVisibleRange(1_000_000, 600, 32, 100, 5);
|
|
expect(range.endIndex).toBeLessThanOrEqual(100);
|
|
expect(range.startIndex).toBeLessThanOrEqual(100);
|
|
expect(range.startIndex).toBeLessThanOrEqual(range.endIndex);
|
|
});
|
|
|
|
it("liefert eine leere Range bei 0 Zeilen, kein Fehler", () => {
|
|
const range = computeVisibleRange(0, 600, 32, 0);
|
|
expect(range.startIndex).toBe(0);
|
|
expect(range.endIndex).toBe(0);
|
|
});
|
|
|
|
it("totalContentHeight ergibt Zeilenzahl mal Zeilenhoehe (fuer den Scroll-Spacer)", () => {
|
|
expect(totalContentHeight(3000, 32)).toBe(96000);
|
|
});
|
|
});
|