145 lines
3.7 KiB
TypeScript
145 lines
3.7 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { describe, it } from "node:test";
|
|
import { buildCircuitStructureProjection } from "../src/frontend/utils/circuit-structure-projection.js";
|
|
import type {
|
|
CircuitTreeCircuitDto,
|
|
CircuitTreeComponentDto,
|
|
CircuitTreeSectionDto,
|
|
} from "../src/frontend/types.js";
|
|
|
|
function component(
|
|
id: string,
|
|
placement: CircuitTreeComponentDto["placement"],
|
|
sortOrder: number,
|
|
sectionId?: string
|
|
): CircuitTreeComponentDto {
|
|
return {
|
|
id,
|
|
circuitListId: "list-1",
|
|
sectionId,
|
|
equipmentIdentifier: `-${id}`,
|
|
name: id,
|
|
role:
|
|
placement === "header"
|
|
? "main_switch"
|
|
: placement === "footer"
|
|
? "auxiliary"
|
|
: "group_residual_current_protection",
|
|
placement,
|
|
sortOrder,
|
|
};
|
|
}
|
|
|
|
function circuit(
|
|
id: string,
|
|
sectionId: string
|
|
): CircuitTreeCircuitDto {
|
|
return {
|
|
id,
|
|
circuitListId: "list-1",
|
|
sectionId,
|
|
equipmentIdentifier: `-${id}`,
|
|
sortOrder: 10,
|
|
isReserve: true,
|
|
circuitTotalPower: 0,
|
|
deviceRows: [],
|
|
};
|
|
}
|
|
|
|
function section(
|
|
id: string,
|
|
sortOrder: number
|
|
): CircuitTreeSectionDto {
|
|
return {
|
|
id,
|
|
key: id,
|
|
displayName: id,
|
|
prefix: "-1F1.",
|
|
sortOrder,
|
|
category: "lighting",
|
|
groupNumber: sortOrder / 10,
|
|
sectionTotalPower: 0,
|
|
components: [
|
|
component(`${id}-rcd-late`, "group", 20, id),
|
|
component(`${id}-rcd-first`, "group", 10, id),
|
|
],
|
|
circuits: [circuit(`${id}-circuit`, id)],
|
|
};
|
|
}
|
|
|
|
describe("circuit structure projection", () => {
|
|
it("projects fixed header, complete groups and auxiliary footer in stable order", () => {
|
|
const rows = buildCircuitStructureProjection({
|
|
headerComponents: [
|
|
component("surge", "header", 20),
|
|
component("main", "header", 10),
|
|
],
|
|
sections: [section("group-2", 20), section("group-1", 10)],
|
|
footerComponents: [
|
|
component("actor-2", "footer", 20),
|
|
component("actor-1", "footer", 10),
|
|
],
|
|
});
|
|
assert.deepEqual(
|
|
rows.map((row) => row.rowKey),
|
|
[
|
|
"header-component:main",
|
|
"header-component:surge",
|
|
"group:group-1",
|
|
"group-component:group-1-rcd-first",
|
|
"group-component:group-1-rcd-late",
|
|
"circuit-block:group-1-circuit",
|
|
"group-placeholder:group-1",
|
|
"group:group-2",
|
|
"group-component:group-2-rcd-first",
|
|
"group-component:group-2-rcd-late",
|
|
"circuit-block:group-2-circuit",
|
|
"group-placeholder:group-2",
|
|
"footer-component:actor-1",
|
|
"footer-component:actor-2",
|
|
]
|
|
);
|
|
});
|
|
|
|
it("keeps structural rows around an empty group", () => {
|
|
const empty = section("group-empty", 10);
|
|
empty.components = [];
|
|
empty.circuits = [];
|
|
assert.deepEqual(
|
|
buildCircuitStructureProjection({
|
|
headerComponents: [],
|
|
sections: [empty],
|
|
footerComponents: [],
|
|
}).map((row) => row.rowType),
|
|
["groupHeader", "groupPlaceholder"]
|
|
);
|
|
});
|
|
|
|
it("keeps circuit device rows inside their circuit block", () => {
|
|
const grouped = section("group-1", 10);
|
|
grouped.circuits[0].deviceRows = [
|
|
{
|
|
id: "device-1",
|
|
sortOrder: 10,
|
|
name: "Leuchte",
|
|
displayName: "Leuchte",
|
|
quantity: 1,
|
|
powerPerUnit: 0.1,
|
|
simultaneityFactor: 1,
|
|
rowTotalPower: 0.1,
|
|
},
|
|
];
|
|
const block = buildCircuitStructureProjection({
|
|
headerComponents: [],
|
|
sections: [grouped],
|
|
footerComponents: [],
|
|
}).find((row) => row.rowType === "circuitBlock");
|
|
assert.equal(
|
|
block?.rowType === "circuitBlock"
|
|
? block.circuit.deviceRows[0].id
|
|
: null,
|
|
"device-1"
|
|
);
|
|
});
|
|
});
|