Files
nexarch/web/dms-browser/lib/versionsApi.test.ts
T
patrickandClaude Sonnet 5 64af627495 VER-02: Versionsansicht & Wiederherstellung
versioning.go ergaenzt Restore (stellt eine fruehere Revision ueber
denselben CheckOut/CheckIn-Mechanismus als NEUE Revision wieder her, kein
separater Codepfad) und GetRevisionContent (beliebige, nicht nur die
aktuelle Revision). Revision.CreatedBy ergaenzt fuer Autor-Anzeige.

internal/versioningapi: Liste/Content/Restore als HTTP-Endpunkte.
OwnerChecker ist eine minimale, echte PermissionChecker-Implementierung
(Dokument- oder Revisions-Ersteller) - keine zentrale RBAC-Anbindung fuer
dieses Modul vorhanden (VER-01/VER-05-Praezedenzfall), der Aufrufvertrag
ist aber so geschnitten, dass eine spaetere echte Rollenpruefung diesen
Handler nicht aendern muss.

web/dms-browser: Versionsliste (Autor/Zeitpunkt/Kommentar, Download- und
Wiederherstellen-Aktion je Zeile), nutzt dieselbe bei DOC-10 gegen 10.000
Zeilen bewiesene Virtualisierungs-Logik.

Pruefungen:
1. Wiederherstellung veraendert Historie nicht - alle felder der alten
   revisionen unveraendert, wiederhergestellter inhalt real entschluesselt
   und verglichen
2. 100 revisionen bleiben uebersichtlich - dieselbe bei doc-10 bewiesene
   virtualisierung, weit unterhalb des bewiesenen 10.000er-bereichs
3. berechtigung wird JE revision geprueft - nicht-ersteller sieht
   accessible:false und bekommt 403, ersteller kann zugreifen (200)

Regressionsfrei: go test ./... -p 1 alle pakete PASS, 22/22 vitest-tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 21:26:15 +02:00

40 lines
1.8 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { fetchRevisions, restoreRevision, revisionContentUrl } from "./versionsApi";
const ORIGINAL_ENV = process.env;
beforeEach(() => {
process.env = { ...ORIGINAL_ENV, NEXT_PUBLIC_VERSIONING_API_URL: "http://backend.test", NEXT_PUBLIC_USER_ID: "user-a" };
});
afterEach(() => {
process.env = ORIGINAL_ENV;
vi.restoreAllMocks();
});
describe("versionsApi", () => {
it("fetchRevisions ruft den erwarteten Endpunkt mit caller-Parameter auf", async () => {
const fetchMock = vi.fn().mockResolvedValue(new Response("[]", { status: 200 }));
vi.stubGlobal("fetch", fetchMock);
await fetchRevisions("doc-1");
expect(fetchMock.mock.calls[0][0]).toBe("http://backend.test/documents/doc-1/revisions?caller=user-a");
});
it("revisionContentUrl baut die Download-URL fuer eine bestimmte Revision", () => {
expect(revisionContentUrl("doc-1", "rev-2")).toBe(
"http://backend.test/documents/doc-1/revisions/rev-2/content?caller=user-a"
);
});
it("restoreRevision wirft bei 403 eine verstaendliche Fehlermeldung", async () => {
vi.stubGlobal("fetch", vi.fn().mockResolvedValue(new Response(null, { status: 403 })));
await expect(restoreRevision("doc-1", "rev-1")).rejects.toThrow(/Berechtigung/);
});
it("restoreRevision liefert die neue Revision bei Erfolg", async () => {
const newRev = { id: "rev-2", revision_number: 2, size_bytes: 10, mime_type: "application/pdf", comment: "x", created_by: "user-a", created_at: "2026-09-17T00:00:00Z", accessible: true };
vi.stubGlobal("fetch", vi.fn().mockResolvedValue(new Response(JSON.stringify(newRev), { status: 200, headers: { "Content-Type": "application/json" } })));
await expect(restoreRevision("doc-1", "rev-1")).resolves.toEqual(newRev);
});
});