Expose project version history
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import { createElement } from "react";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { ProjectVersionHistory } from "../src/frontend/components/project-version-history.js";
|
||||
import type { ProjectRevisionSummaryDto } from "../src/frontend/types.js";
|
||||
import {
|
||||
createNamedProjectSnapshot,
|
||||
listProjectRevisions,
|
||||
listProjectSnapshots,
|
||||
restoreProjectSnapshot,
|
||||
} from "../src/frontend/utils/api.js";
|
||||
import {
|
||||
getProjectRevisionDescription,
|
||||
getProjectRevisionSourceLabel,
|
||||
mergeProjectRevisionPages,
|
||||
} from "../src/frontend/utils/project-version-history.js";
|
||||
|
||||
function revision(
|
||||
revisionNumber: number,
|
||||
overrides: Partial<ProjectRevisionSummaryDto> = {}
|
||||
): ProjectRevisionSummaryDto {
|
||||
return {
|
||||
revisionId: `revision-${revisionNumber}`,
|
||||
changeSetId: `change-${revisionNumber}`,
|
||||
revisionNumber,
|
||||
createdAtIso: "2026-07-25T12:00:00.000Z",
|
||||
actorId: null,
|
||||
source: "user",
|
||||
description: null,
|
||||
commandType: "circuit.update",
|
||||
payloadSchemaVersion: 1,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe("project version history presentation", () => {
|
||||
it("renders a compact collapsed German entry point", () => {
|
||||
const markup = renderToStaticMarkup(
|
||||
createElement(ProjectVersionHistory, {
|
||||
projectId: "project-1",
|
||||
currentRevision: 42,
|
||||
onRestoreComplete: () => undefined,
|
||||
})
|
||||
);
|
||||
assert.match(markup, /Versionen und Sicherungspunkte/);
|
||||
assert.match(markup, /Aktuelle Revision 42/);
|
||||
assert.match(markup, /Anzeigen/);
|
||||
assert.doesNotMatch(markup, /Stand speichern/);
|
||||
});
|
||||
|
||||
it("uses German source and command descriptions", () => {
|
||||
assert.equal(getProjectRevisionSourceLabel("user"), "Bearbeitung");
|
||||
assert.equal(getProjectRevisionSourceLabel("undo"), "Rückgängig");
|
||||
assert.equal(getProjectRevisionSourceLabel("redo"), "Wiederholt");
|
||||
assert.equal(
|
||||
getProjectRevisionSourceLabel("restore"),
|
||||
"Wiederherstellung"
|
||||
);
|
||||
assert.equal(getProjectRevisionSourceLabel("migration"), "Migration");
|
||||
assert.equal(
|
||||
getProjectRevisionDescription(revision(1)),
|
||||
"Stromkreis bearbeitet"
|
||||
);
|
||||
assert.equal(
|
||||
getProjectRevisionDescription(
|
||||
revision(2, { description: " Eigene Beschreibung " })
|
||||
),
|
||||
"Eigene Beschreibung"
|
||||
);
|
||||
assert.equal(
|
||||
getProjectRevisionDescription(
|
||||
revision(3, { commandType: "future.command" })
|
||||
),
|
||||
"future.command"
|
||||
);
|
||||
});
|
||||
|
||||
it("merges paginated revisions without duplicates in descending order", () => {
|
||||
assert.deepEqual(
|
||||
mergeProjectRevisionPages(
|
||||
[revision(5), revision(4)],
|
||||
[revision(4), revision(3)]
|
||||
).map((entry) => entry.revisionNumber),
|
||||
[5, 4, 3]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("project version history API", () => {
|
||||
it("uses the revision-safe timeline and snapshot routes", async () => {
|
||||
const requests: Array<{
|
||||
url: string;
|
||||
method: string;
|
||||
body: unknown;
|
||||
}> = [];
|
||||
const originalFetch = globalThis.fetch;
|
||||
globalThis.fetch = async (input, init) => {
|
||||
requests.push({
|
||||
url: String(input),
|
||||
method: init?.method ?? "GET",
|
||||
body: init?.body ? JSON.parse(String(init.body)) : null,
|
||||
});
|
||||
return new Response(JSON.stringify({}), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
await listProjectRevisions("project-1", {
|
||||
limit: 10,
|
||||
beforeRevision: 21,
|
||||
});
|
||||
await listProjectSnapshots("project-1");
|
||||
await createNamedProjectSnapshot(
|
||||
"project-1",
|
||||
22,
|
||||
"Planfreigabe",
|
||||
"Vor Ausführung"
|
||||
);
|
||||
await restoreProjectSnapshot("project-1", "snapshot-1", 22);
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
}
|
||||
|
||||
assert.deepEqual(requests, [
|
||||
{
|
||||
url: "/api/projects/project-1/history/revisions?limit=10&beforeRevision=21",
|
||||
method: "GET",
|
||||
body: null,
|
||||
},
|
||||
{
|
||||
url: "/api/projects/project-1/snapshots",
|
||||
method: "GET",
|
||||
body: null,
|
||||
},
|
||||
{
|
||||
url: "/api/projects/project-1/snapshots",
|
||||
method: "POST",
|
||||
body: {
|
||||
expectedRevision: 22,
|
||||
name: "Planfreigabe",
|
||||
description: "Vor Ausführung",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "/api/projects/project-1/snapshots/snapshot-1/restore",
|
||||
method: "POST",
|
||||
body: { expectedRevision: 22 },
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user