Add Revit CSV preview API
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import {
|
||||
previewExternalCsvSchema,
|
||||
updateExternalCsvConfigurationSchema,
|
||||
} from "../src/shared/validation/external-csv.schemas.js";
|
||||
import { createDefaultExternalCsvConfiguration } from "../src/external-model/csv/external-csv-contracts.js";
|
||||
import { externalCsvTestColumns } from "./fixtures/revit-csv-fixtures.js";
|
||||
|
||||
describe("external CSV API contracts", () => {
|
||||
it("accepts strict update and preview request envelopes", () => {
|
||||
assert.equal(
|
||||
updateExternalCsvConfigurationSchema.safeParse({
|
||||
expectedRevision: 4,
|
||||
configuration: createDefaultExternalCsvConfiguration(externalCsvTestColumns),
|
||||
}).success,
|
||||
true
|
||||
);
|
||||
assert.equal(
|
||||
previewExternalCsvSchema.safeParse({
|
||||
fileName: "revit.csv",
|
||||
contentBase64: "YWJj",
|
||||
}).success,
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects stale-shaped, oversized and unknown request fields", () => {
|
||||
assert.equal(
|
||||
updateExternalCsvConfigurationSchema.safeParse({
|
||||
expectedRevision: -1,
|
||||
configuration: {},
|
||||
}).success,
|
||||
false
|
||||
);
|
||||
assert.equal(
|
||||
previewExternalCsvSchema.safeParse({
|
||||
fileName: "revit.csv",
|
||||
contentBase64: "YWJj",
|
||||
apply: true,
|
||||
}).success,
|
||||
false
|
||||
);
|
||||
assert.equal(
|
||||
previewExternalCsvSchema.safeParse({
|
||||
fileName: "revit.csv",
|
||||
contentBase64: "a".repeat(24_000_001),
|
||||
}).success,
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
type DatabaseContext,
|
||||
} from "../src/db/database-context.js";
|
||||
import { ExternalCsvConfigurationProjectCommandRepository } from "../src/db/repositories/external-csv-configuration-project-command.repository.js";
|
||||
import { ExternalCsvConfigurationRepository } from "../src/db/repositories/external-csv-configuration.repository.js";
|
||||
import { ProjectTransferRepository } from "../src/db/repositories/project-transfer.repository.js";
|
||||
import { ProjectStateRestoreCommandRepository } from "../src/db/repositories/project-state-restore-command.repository.js";
|
||||
import { readProjectStateSnapshot } from "../src/db/repositories/project-state-snapshot.persistence.js";
|
||||
@@ -169,6 +170,23 @@ describe("external CSV configuration project command", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("distinguishes projects without configuration from unknown projects", () => {
|
||||
const context = createTestDatabase();
|
||||
try {
|
||||
const reader = new ExternalCsvConfigurationRepository(context.db);
|
||||
assert.deepEqual(reader.getByProject("project-1"), {
|
||||
projectExists: true,
|
||||
configuration: null,
|
||||
});
|
||||
assert.deepEqual(reader.getByProject("missing"), {
|
||||
projectExists: false,
|
||||
configuration: null,
|
||||
});
|
||||
} finally {
|
||||
context.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("restores and undoes the complete configuration through snapshot history", () => {
|
||||
const context = createTestDatabase();
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import { createExternalCsvPreview } from "../src/external-model/application/external-csv-preview.js";
|
||||
import {
|
||||
externalCsvTestConfiguration,
|
||||
firstIfcGuid,
|
||||
quotedRevitCsv,
|
||||
utf8Bytes,
|
||||
} from "./fixtures/revit-csv-fixtures.js";
|
||||
|
||||
describe("external CSV preview", () => {
|
||||
it("projects transport statistics and mapped object source values without writes", () => {
|
||||
const configuration = structuredClone(externalCsvTestConfiguration);
|
||||
configuration.additionalSourceMappings.push({
|
||||
sourceColumn: "Raumname",
|
||||
targetField: "sourceRoomLabel",
|
||||
});
|
||||
// The additional mapping intentionally needs a distinct source column in
|
||||
// persisted configuration, so use a separately named synthetic header.
|
||||
configuration.additionalSourceMappings[0].sourceColumn = "Zusatzwert";
|
||||
const csv = quotedRevitCsv
|
||||
.replace('"Anzahl";"IfcGUID"', '"Anzahl";"Zusatzwert";"IfcGUID"')
|
||||
.replaceAll(';"2";"0Ab', ';"2";"A";"0Ab')
|
||||
.replaceAll(';"1";"1Ab', ';"1";"B";"1Ab')
|
||||
.replaceAll(';"1";""', ';"1";"C";""')
|
||||
.replaceAll(';"";""\r\n', ';"";"";""\r\n');
|
||||
|
||||
const preview = createExternalCsvPreview({
|
||||
fileName: "export.csv",
|
||||
bytes: utf8Bytes(csv, true),
|
||||
configuration,
|
||||
});
|
||||
|
||||
assert.equal(preview.fileName, "export.csv");
|
||||
assert.equal(preview.headerRowNumber, 2);
|
||||
assert.equal(preview.rowCount, 7);
|
||||
assert.equal(preview.objectCount, 2);
|
||||
assert.equal(preview.passthroughCount, 2);
|
||||
assert.equal(preview.nonEmptyPassthroughCount, 1);
|
||||
assert.equal(preview.suspectObjectCount, 1);
|
||||
assert.deepEqual(preview.suspectRowNumbers, [6]);
|
||||
assert.match(preview.sha256, /^[a-f0-9]{64}$/);
|
||||
assert.deepEqual(preview.objects[0], {
|
||||
rowNumber: 4,
|
||||
ifcGuid: firstIfcGuid,
|
||||
roomNumber: "01/101",
|
||||
roomName: "Technik",
|
||||
familyAndType: "Steckdose: Doppelsteckdose",
|
||||
selectionMarker: "Arbeitsplatz",
|
||||
circuitIdentifier: "UV_AV_01-2F1",
|
||||
power: "120,5",
|
||||
quantity: "2",
|
||||
additionalSourceValues: { sourceRoomLabel: "A" },
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user