internal/folderapi: neue Backend-Voraussetzung - GET /folders/{id}/
children (lazy Baum-Ladung), .../breadcrumb (ueber DOC-09s Materialized
Path), .../documents (Dokumentenliste, whitelisted Sortierspalten).
folder.go ergaenzt ListChildren/Breadcrumb (additiv, keine bestehende
Funktion geaendert).
web/dms-browser: Next.js/React/TypeScript. Navigationsbaum laedt Kinder
lazy je Ebene, Dokumentenliste ist virtualisiert (lib/virtualization.ts,
abhaengigkeitsfrei - nur sichtbarer Ausschnitt + Overscan wird gerendert),
Mehrfachauswahl (lib/selection.ts: Klick/Strg/Umschalt), Tastatur-
navigation im Baum (lib/treeKeyboard.ts). Aktueller Ordner steckt in der
URL (Catch-all-Route /browse/[[...path]]) statt nur im React-State - der
Browser verwaltet Vor-/Zurueck-Navigation selbst.
Echter Bug beim Schreiben der Virtualisierungs-Tests gefunden und
behoben: startIndex war bei scrollTop jenseits des tatsaechlichen Inhalts
nicht auf totalRows geklemmt (haette zu ungueltigem slice() gefuehrt).
Pruefungen:
1. Liste mit 10.000 Zeilen scrollt ruckelfrei - Virtualisierung rendert
nachweislich nur ~20 statt 10.000 Zeilen
2. Navigation vollstaendig per Tastatur - 5 Vitest-Tests fuer Pfeiltasten/
Enter im Baum
3. Zustand bleibt beim Zurueck-Navigieren erhalten - Ordner-ID in der URL,
Browser-History uebernimmt die Wiederherstellung
Regressionsfrei: alle bestehenden Go-Pakete PASS.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
37 lines
1.4 KiB
TypeScript
37 lines
1.4 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { fetchChildren, fetchDocuments } from "./api";
|
|
|
|
const ORIGINAL_ENV = process.env;
|
|
|
|
beforeEach(() => {
|
|
process.env = { ...ORIGINAL_ENV, NEXT_PUBLIC_FOLDER_API_URL: "http://backend.test" };
|
|
});
|
|
|
|
afterEach(() => {
|
|
process.env = ORIGINAL_ENV;
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe("api client", () => {
|
|
it("fetchChildren(null) ruft den Wurzel-Endpunkt auf", async () => {
|
|
const fetchMock = vi.fn().mockResolvedValue(new Response("[]", { status: 200 }));
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
await fetchChildren(null);
|
|
expect(fetchMock.mock.calls[0][0]).toBe("http://backend.test/folders/children");
|
|
});
|
|
|
|
it("fetchChildren(id) ruft den ordnerspezifischen Endpunkt auf", async () => {
|
|
const fetchMock = vi.fn().mockResolvedValue(new Response("[]", { status: 200 }));
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
await fetchChildren("abc");
|
|
expect(fetchMock.mock.calls[0][0]).toBe("http://backend.test/folders/abc/children");
|
|
});
|
|
|
|
it("fetchDocuments gibt Sortierparameter weiter", async () => {
|
|
const fetchMock = vi.fn().mockResolvedValue(new Response("[]", { status: 200 }));
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
await fetchDocuments("abc", { sort: "title", order: "desc" });
|
|
expect(fetchMock.mock.calls[0][0]).toBe("http://backend.test/folders/abc/documents?sort=title&order=desc");
|
|
});
|
|
});
|