tsx runs tests without type checking and tsconfig.json covers only src, so 71 type errors had accumulated unnoticed. tsconfig.tests.json now checks every test and helper, and npm run typecheck includes it. Fixtures gain the fields the DTOs have grown since they were written (manualQuantity, circuit apparent power/cos phi, downstream board loads, section totals, building, cover and board info fields). Repository lookups that return "row ?? null" now declare the null in their type, which their callers already handle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
206 lines
6.3 KiB
TypeScript
206 lines
6.3 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { describe, it } from "node:test";
|
|
import {
|
|
assertDistributionBoardSubtreeSnapshot,
|
|
cloneDistributionBoardSubtree,
|
|
type DistributionBoardSubtreeSnapshot,
|
|
} from "../src/domain/models/distribution-board-subtree-snapshot.model.js";
|
|
import {
|
|
createDistributionBoardDeleteSubtreeProjectCommand,
|
|
createDistributionBoardInsertSubtreeProjectCommand,
|
|
} from "../src/domain/models/distribution-board-subtree-project-command.model.js";
|
|
|
|
function createSnapshot(): DistributionBoardSubtreeSnapshot {
|
|
return {
|
|
distributionBoard: {
|
|
id: "board-1",
|
|
projectId: "project-1",
|
|
name: "UV 1",
|
|
floorId: "floor-1",
|
|
supplyType: "AV",
|
|
simultaneityFactor: 0.8,
|
|
feedingDistributionBoardId: "board-upstream",
|
|
feedingCircuitId: "circuit-upstream",
|
|
boardNumber: null,
|
|
location: null,
|
|
fedFrom: null,
|
|
remark: null,
|
|
},
|
|
circuitList: {
|
|
id: "list-1",
|
|
projectId: "project-1",
|
|
distributionBoardId: "board-1",
|
|
name: "UV 1 Stromkreisliste",
|
|
},
|
|
sections: [
|
|
{
|
|
id: "section-1",
|
|
circuitListId: "list-1",
|
|
key: "lighting",
|
|
displayName: "Beleuchtung 1",
|
|
prefix: "-1F1.",
|
|
sortOrder: 10,
|
|
category: "lighting",
|
|
groupNumber: 1,
|
|
},
|
|
],
|
|
components: [
|
|
{
|
|
component: {
|
|
id: "main-1",
|
|
circuitListId: "list-1",
|
|
sectionId: null,
|
|
equipmentIdentifier: "-Q0",
|
|
name: "Hauptschalter",
|
|
role: "main_switch",
|
|
placement: "header",
|
|
sortOrder: 10,
|
|
},
|
|
protectionDevice: null,
|
|
},
|
|
{
|
|
component: {
|
|
id: "rcd-1",
|
|
circuitListId: "list-1",
|
|
sectionId: "section-1",
|
|
equipmentIdentifier: "-1Q1.0",
|
|
name: "Gruppen-FI",
|
|
role: "group_residual_current_protection",
|
|
placement: "group",
|
|
sortOrder: 20,
|
|
},
|
|
protectionDevice: {
|
|
componentId: "rcd-1",
|
|
type: "FI",
|
|
ratedCurrentA: 40,
|
|
fuseUtilizationCategory: null,
|
|
tripCharacteristic: null,
|
|
rcdType: "A",
|
|
ratedResidualCurrentMa: 30,
|
|
},
|
|
},
|
|
],
|
|
circuits: [
|
|
{
|
|
id: "circuit-1",
|
|
circuitListId: "list-1",
|
|
sectionId: "section-1",
|
|
equipmentIdentifier: "-1F1.1",
|
|
displayName: "Licht",
|
|
sortOrder: 10,
|
|
cableType: "NYM-J",
|
|
cableCrossSection: "3x1,5 mm²",
|
|
cableLength: 10,
|
|
rcdAssignment: null,
|
|
terminalDesignation: null,
|
|
voltage: 230,
|
|
controlRequirement: null,
|
|
status: null,
|
|
isReserve: false,
|
|
remark: null,
|
|
deviceRows: [
|
|
{
|
|
id: "row-1",
|
|
circuitId: "circuit-1",
|
|
linkedProjectDeviceId: "device-1",
|
|
sortOrder: 10,
|
|
name: "Leuchte",
|
|
displayName: "Leuchte",
|
|
phaseType: "single_phase",
|
|
connectionKind: null,
|
|
costGroup: null,
|
|
category: null,
|
|
level: null,
|
|
roomId: "room-1",
|
|
roomNumberSnapshot: "1.01",
|
|
roomNameSnapshot: "Büro",
|
|
quantity: 1,
|
|
powerPerUnit: 0.1,
|
|
simultaneityFactor: 1,
|
|
cosPhi: 0.9,
|
|
remark: null,
|
|
overriddenFields: null,
|
|
},
|
|
],
|
|
protectionDevice: {
|
|
circuitId: "circuit-1",
|
|
type: "LS",
|
|
ratedCurrentA: 10,
|
|
fuseUtilizationCategory: null,
|
|
tripCharacteristic: "B",
|
|
rcdType: null,
|
|
ratedResidualCurrentMa: null,
|
|
},
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
describe("distribution-board subtree snapshot", () => {
|
|
it("validates complete populated board structures and commands", () => {
|
|
const snapshot = createSnapshot();
|
|
assert.doesNotThrow(() =>
|
|
assertDistributionBoardSubtreeSnapshot(snapshot)
|
|
);
|
|
assert.equal(
|
|
createDistributionBoardInsertSubtreeProjectCommand(snapshot).type,
|
|
"distribution-board.insert-subtree"
|
|
);
|
|
assert.equal(
|
|
createDistributionBoardDeleteSubtreeProjectCommand(snapshot).type,
|
|
"distribution-board.delete-subtree"
|
|
);
|
|
});
|
|
|
|
it("clones every owned id while preserving project links and values", () => {
|
|
const ids = Array.from({ length: 6 }, (_, index) => `new-${index + 1}`);
|
|
const clone = cloneDistributionBoardSubtree(
|
|
createSnapshot(),
|
|
"UV 1 Kopie",
|
|
() => ids.shift()!
|
|
);
|
|
|
|
assert.equal(clone.distributionBoard.id, "new-1");
|
|
assert.equal(clone.circuitList.id, "new-1");
|
|
assert.equal(clone.distributionBoard.name, "UV 1 Kopie");
|
|
assert.equal(
|
|
clone.distributionBoard.feedingDistributionBoardId,
|
|
"board-upstream"
|
|
);
|
|
assert.equal(clone.distributionBoard.feedingCircuitId, "circuit-upstream");
|
|
assert.equal(clone.circuitList.name, "UV 1 Kopie Stromkreisliste");
|
|
assert.equal(clone.sections[0].id, "new-2");
|
|
assert.equal(clone.circuits[0].id, "new-3");
|
|
assert.equal(clone.components[0].component.id, "new-4");
|
|
assert.equal(clone.components[1].component.id, "new-5");
|
|
assert.equal(clone.components[1].component.sectionId, "new-2");
|
|
assert.equal(clone.components[1].protectionDevice?.componentId, "new-5");
|
|
assert.equal(clone.circuits[0].sectionId, "new-2");
|
|
assert.equal(clone.circuits[0].deviceRows[0].id, "new-6");
|
|
assert.equal(clone.circuits[0].deviceRows[0].circuitId, "new-3");
|
|
assert.equal(
|
|
clone.circuits[0].deviceRows[0].linkedProjectDeviceId,
|
|
"device-1"
|
|
);
|
|
assert.equal(clone.circuits[0].deviceRows[0].roomId, "room-1");
|
|
assert.equal(clone.circuits[0].protectionDevice?.circuitId, "new-3");
|
|
assert.doesNotThrow(() => assertDistributionBoardSubtreeSnapshot(clone));
|
|
});
|
|
|
|
it("rejects broken ownership and duplicate equipment identifiers", () => {
|
|
const brokenOwnership = createSnapshot();
|
|
brokenOwnership.circuits[0].sectionId = "missing";
|
|
assert.throws(
|
|
() => assertDistributionBoardSubtreeSnapshot(brokenOwnership),
|
|
/ownership/
|
|
);
|
|
|
|
const duplicateIdentifier = createSnapshot();
|
|
duplicateIdentifier.components[0].component.equipmentIdentifier =
|
|
" -1f1.1 ";
|
|
assert.throws(
|
|
() => assertDistributionBoardSubtreeSnapshot(duplicateIdentifier),
|
|
/duplicate equipment identifier/
|
|
);
|
|
});
|
|
});
|