Add Linear XLSX initial import

This commit is contained in:
Julian Appel 2026-09-30 09:50:58 +02:00
parent c633e78cd4
commit bfdd048269
20 changed files with 932 additions and 85 deletions

View file

@ -2,7 +2,7 @@ import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { describe, it } from "node:test";
import { createDefaultExternalModelConfiguration } from "../src/external-model/configuration/external-model-configuration.js";
import { detectExternalModelWorkbook, getExternalModelConfiguration, updateExternalModelConfiguration } from "../src/frontend/utils/api.js";
import { applyExternalInitialImport, detectExternalModelWorkbook, getExternalInitialImportStatus, getExternalModelConfiguration, planExternalInitialImport, updateExternalModelConfiguration } from "../src/frontend/utils/api.js";
describe("Revit XLSX settings", () => {
it("uses the project-scoped configuration endpoint with expectedRevision", async () => {
@ -25,14 +25,41 @@ describe("Revit XLSX settings", () => {
} finally { globalThis.fetch = originalFetch; }
});
it("uses stateless preview and retransmits the workbook for apply", async () => {
const requests: Array<{ url: string; method: string; body: Record<string, unknown> | undefined }> = [];
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)) : undefined });
return new Response(JSON.stringify({ imported: false, familyGroups: [], sourceRooms: [], objects: [], warnings: [], issueCounts: {}, existing: {}, history: { currentRevision: 9 }, import: { objectCount: 2 } }), { status: 200, headers: { "Content-Type": "application/json" } });
};
try {
const configuration = createDefaultExternalModelConfiguration();
const file = new File([new Uint8Array([1, 2])], "linear.xlsx");
await getExternalInitialImportStatus("project-1");
await planExternalInitialImport("project-1", file, configuration, 8);
await applyExternalInitialImport("project-1", file, { expectedRevision: 8, expectedSha256: "a".repeat(64), sourceName: "Revit", configuration, objectsWithoutRoomDefaultDistributionBoardId: null, roomDecisions: [], familyProjectDeviceDecisions: [] });
assert.equal(requests[0].url, "/api/projects/project-1/external-model/import-status");
assert.equal(requests[1].url, "/api/projects/project-1/external-model/initial-import/plan");
assert.equal(requests[2].url, "/api/projects/project-1/external-model/initial-import/apply");
assert.equal(requests[1].body?.contentBase64, "AQI=");
assert.equal(requests[1].body?.expectedRevision, 8);
assert.equal(requests[2].body?.contentBase64, "AQI=");
assert.equal(requests[2].body?.expectedRevision, 8);
} finally { globalThis.fetch = originalFetch; }
});
it("exposes the Revit route and removes the old project modal", () => {
const projectPage = readFileSync("src/app/projects/[projectId]/page.tsx", "utf8");
const revitPage = readFileSync("src/app/projects/[projectId]/revit/page.tsx", "utf8");
const settings = readFileSync("src/frontend/components/revit-xlsx-settings-modal.tsx", "utf8");
const wizard = readFileSync("src/frontend/components/revit-initial-import-wizard.tsx", "utf8");
assert.match(projectPage, /href={`\/projects\/\$\{projectId\}\/revit`}/);
assert.doesNotMatch(projectPage, /RevitCsvModal|Revit-CSV/);
assert.match(revitPage, /Importstatus/);
assert.match(settings, /Musterdatei prüfen/);
assert.match(settings, /Kombinierte Stromkreisspalte/);
assert.match(wizard, /Schritt.*von/);
assert.match(wizard, /keine Gerätezeilen, Stromkreise oder BMKs/);
assert.match(wizard, /GZF 1/);
});
});