import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { getCircuitTree, isMissingCircuitTreeSchemaError, } from "../src/server/controllers/circuit-tree.controller.js"; import { circuitDeviceRowRepository, circuitListRepository, circuitProtectionDeviceRepository, circuitRepository, circuitSectionRepository, distributionBoardComponentRepository, distributionBoardRepository, projectRepository, } from "../src/server/composition/application-repositories.js"; describe("circuit tree controller", () => { it("detects missing circuit-first schema errors", () => { assert.equal( isMissingCircuitTreeSchemaError(new Error("SqliteError: no such table: circuit_sections")), true ); assert.equal(isMissingCircuitTreeSchemaError(new Error("SqliteError: no such table: circuits")), true); assert.equal( isMissingCircuitTreeSchemaError(new Error("SqliteError: no such table: circuit_device_rows")), true ); assert.equal( isMissingCircuitTreeSchemaError( new Error("SqliteError: no such table: distribution_board_components") ), true ); assert.equal(isMissingCircuitTreeSchemaError(new Error("Some other error")), false); }); it("returns header, grouped and footer components with both protection layers", async () => { const originals = { findList: circuitListRepository.findById, findProject: projectRepository.findById, findBoard: distributionBoardRepository.findById, listSections: circuitSectionRepository.listByCircuitList, listCircuits: circuitRepository.listByCircuitList, listRows: circuitDeviceRowRepository.listByCircuitList, listComponents: distributionBoardComponentRepository.listByCircuitList, listComponentProtection: distributionBoardComponentRepository.listProtectionByComponentIds, listCircuitProtection: circuitProtectionDeviceRepository.listByCircuitIds, }; circuitListRepository.findById = async () => ({ id: "list-1", projectId: "project-1", distributionBoardId: "board-1", name: "UV-01", }) as never; projectRepository.findById = async () => ({ id: "project-1", name: "Projekt", currentRevision: 4, singlePhaseVoltageV: 230, threePhaseVoltageV: 400, }) as never; distributionBoardRepository.findById = async () => ({ id: "board-1", simultaneityFactor: 0.8 }) as never; circuitSectionRepository.listByCircuitList = async () => [ { id: "group-1", circuitListId: "list-1", key: "lighting", displayName: "Beleuchtung 1", prefix: "-1F1.", sortOrder: 10, category: "lighting", groupNumber: 1, }, ] as never; circuitRepository.listByCircuitList = async () => [ { id: "circuit-1", circuitListId: "list-1", sectionId: "group-1", equipmentIdentifier: "-1F1.1", displayName: "Licht", sortOrder: 10, isReserve: 0, }, ] as never; circuitDeviceRowRepository.listByCircuitList = async () => []; distributionBoardComponentRepository.listByCircuitList = async () => [ { id: "main", circuitListId: "list-1", sectionId: null, equipmentIdentifier: "-Q0", name: "Hauptschalter", role: "main_switch", placement: "header", sortOrder: 10, }, { id: "rcd", circuitListId: "list-1", sectionId: "group-1", equipmentIdentifier: "-1Q1.0", name: "Gruppen-FI", role: "group_residual_current_protection", placement: "group", sortOrder: 10, }, { id: "actor", circuitListId: "list-1", sectionId: null, equipmentIdentifier: "-K1", name: "KNX Aktor", role: "auxiliary", placement: "footer", sortOrder: 10, }, ] as never; distributionBoardComponentRepository.listProtectionByComponentIds = async () => [ { componentId: "rcd", type: "FI", ratedCurrentA: 40, fuseUtilizationCategory: null, tripCharacteristic: null, rcdType: "A", ratedResidualCurrentMa: 30, }, ] as never; circuitProtectionDeviceRepository.listByCircuitIds = async () => [ { circuitId: "circuit-1", type: "LS", ratedCurrentA: 10, fuseUtilizationCategory: null, tripCharacteristic: "B", rcdType: null, ratedResidualCurrentMa: null, }, ] as never; let responseBody: unknown; const response = { status() { return this; }, json(value: unknown) { responseBody = value; return this; }, }; try { await getCircuitTree( { params: { projectId: "project-1", circuitListId: "list-1" } } as never, response as never ); } finally { circuitListRepository.findById = originals.findList; projectRepository.findById = originals.findProject; distributionBoardRepository.findById = originals.findBoard; circuitSectionRepository.listByCircuitList = originals.listSections; circuitRepository.listByCircuitList = originals.listCircuits; circuitDeviceRowRepository.listByCircuitList = originals.listRows; distributionBoardComponentRepository.listByCircuitList = originals.listComponents; distributionBoardComponentRepository.listProtectionByComponentIds = originals.listComponentProtection; circuitProtectionDeviceRepository.listByCircuitIds = originals.listCircuitProtection; } const tree = responseBody as { headerComponents: Array<{ equipmentIdentifier: string }>; footerComponents: Array<{ equipmentIdentifier: string }>; sections: Array<{ category: string; groupNumber: number; components: Array<{ protectionDevice: { ratedResidualCurrentMa: number }; }>; circuits: Array<{ protectionDevice: { tripCharacteristic: string }; }>; }>; }; assert.equal(tree.headerComponents[0].equipmentIdentifier, "-Q0"); assert.equal(tree.footerComponents[0].equipmentIdentifier, "-K1"); assert.equal(tree.sections[0].category, "lighting"); assert.equal(tree.sections[0].groupNumber, 1); assert.equal( tree.sections[0].components[0].protectionDevice .ratedResidualCurrentMa, 30 ); assert.equal( tree.sections[0].circuits[0].protectionDevice .tripCharacteristic, "B" ); }); });