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" ); }); });