import path from "node:path"; import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { migrate } from "drizzle-orm/better-sqlite3/migrator"; import { createDatabaseContext } from "../src/db/database-context.js"; import { parseExternalModelStateSnapshot } from "../src/domain/models/project-state-snapshot.model.js"; import { createDefaultExternalModelConfiguration } from "../src/external-model/configuration/external-model-configuration.js"; const lowerId = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-ffffffff"; const upperId = "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE-FFFFFFFF"; function fullBatch(id: string, importedAtIso: string) { return { id, projectId: "p", sourceId: "s", importKind: "follow_up" as const, importedAtIso, fileName: `${id}.xlsx`, sha256: "a".repeat(64), objectCount: 1, appliedProjectRevision: 3, configurationSnapshot: createDefaultExternalModelConfiguration(), originalContentBase64: "AA==", document: { sheetName: "Bauteilliste", headerRowNumber: 1, firstDataRowNumber: 3, firstDataColumnNumber: 1, columns: [], rows: [], issues: [], }, }; } describe("Linear XLSX external model foundation", () => { it("keeps only the newest batch complete", () => { const newest = fullBatch("new", "2026-02-01T00:00:00.000Z"); const older = { ...fullBatch("old", "2026-01-01T00:00:00.000Z"), appliedProjectRevision: null, configurationSnapshot: null, originalContentBase64: null, document: null, }; assert.doesNotThrow(() => parseExternalModelStateSnapshot({ source: { id: "s", projectId: "p", name: "Revit", sourceType: "revit_xlsx" }, importBatches: [older, newest], roomMappings: [], objects: [], })); assert.throws(() => parseExternalModelStateSnapshot({ source: { id: "s", projectId: "p", name: "Revit", sourceType: "revit_xlsx" }, importBatches: [newest, fullBatch("newer", "2026-03-01T00:00:00.000Z")], roomMappings: [], objects: [], }), /Nur der letzte Importbatch/); }); it("compares Worksharing-IDs exactly and allows duplicate IfcGUID values", () => { const context = createDatabaseContext(":memory:"); try { migrate(context.db, { migrationsFolder: path.resolve("src", "db", "migrations") }); context.sqlite.exec(` INSERT INTO projects (id, name) VALUES ('p', 'Projekt'); INSERT INTO external_model_sources (id, project_id, name) VALUES ('s', 'p', 'Revit'); INSERT INTO external_import_batches (id, project_id, source_id, import_kind, imported_at_iso, file_name, sha256, object_count) VALUES ('b', 'p', 's', 'initial', '2026-01-01T00:00:00.000Z', 'model.xlsx', '${"a".repeat(64)}', 2); `); const insert = context.sqlite.prepare(` INSERT INTO external_model_objects (id, project_id, source_id, worksharing_id, ifc_guid, device_type_id, last_seen_import_batch_id, last_accepted_import_batch_id, accepted_source_values, planning_values, overridden_fields) VALUES (?, 'p', 's', ?, 'same-IfcGUID', 'type', 'b', 'b', '{}', '{}', '[]') `); insert.run("o1", lowerId); insert.run("o2", upperId); assert.equal(context.sqlite.prepare("SELECT count(*) AS count FROM external_model_objects").get()!.count, 2); assert.throws(() => insert.run("o3", lowerId), /UNIQUE constraint failed/); } finally { context.close(); } }); });