import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { buildCableSizingAlerts, calculateCableSizing, isCableSizingDataVerified, type CableSizingInput, } from "../src/cable-sizing/domain/cable-sizing-calculation.js"; const BASE_INPUT: CableSizingInput = { phase: 1, mode: "power", powerKw: 5, cosPhi: 1, voltage: 230, lengthM: 30, layingMethod: "C", conductorMaterial: "copper", insulation: "pvc", ambientTemperatureC: 30, groupingCircuits: 1, maxVoltageDropPercent: 3, harmonicNeutralLoad: "none", }; describe("calculateCableSizing", () => { it("matches the verified reference case (1~, 5 kW, 230 V, 30 m, method C, copper)", () => { const result = calculateCableSizing(BASE_INPUT); assert.equal(result.dataVerified, true); assert.ok(Math.abs(result.operatingCurrentA - 21.739) < 0.01); assert.equal(result.crossSectionByCapacityMm2, 2.5); assert.equal(result.crossSectionByVoltageDropMm2, 4); assert.equal(result.recommendedCrossSectionMm2, 4); }); it("returns dataVerified: false and no numeric result for an unverified laying method", () => { const result = calculateCableSizing({ ...BASE_INPUT, layingMethod: "A2" }); assert.equal(result.dataVerified, false); assert.equal(result.recommendedCrossSectionMm2, null); assert.equal(result.rows.length, 0); // The operating current itself does not depend on the capacity table // and is still reported so the UI can show at least that much. assert.ok(Math.abs(result.operatingCurrentA - 21.739) < 0.01); }); it("returns dataVerified: false for xlpe regardless of method", () => { const result = calculateCableSizing({ ...BASE_INPUT, insulation: "xlpe" }); assert.equal(result.dataVerified, false); }); it("isCableSizingDataVerified matches the six ported, verified methods only", () => { for (const method of ["A1", "B2", "C", "E", "D1", "D2"] as const) { assert.equal(isCableSizingDataVerified(method, "pvc"), true, method); } for (const method of ["A2", "B1", "F", "G"] as const) { assert.equal(isCableSizingDataVerified(method, "pvc"), false, method); } }); it("applies the 0.86 harmonic reduction factor only for three-phase + 15to33Percent", () => { const threePhase: CableSizingInput = { ...BASE_INPUT, phase: 3, mode: "current", currentA: 10, powerKw: undefined, voltage: 400, }; const base = calculateCableSizing({ ...threePhase, harmonicNeutralLoad: "none" }); const derated = calculateCableSizing({ ...threePhase, harmonicNeutralLoad: "15to33Percent", }); assert.equal(base.harmonicReductionApplied, false); assert.equal(derated.harmonicReductionApplied, true); assert.ok( Math.abs(derated.combinedDerationFactor - base.combinedDerationFactor * 0.86) < 1e-9 ); const singlePhaseWithHarmonics = calculateCableSizing({ ...BASE_INPUT, harmonicNeutralLoad: "15to33Percent", }); assert.equal(singlePhaseWithHarmonics.harmonicReductionApplied, false); }); it("flags a simplified protection coordination mismatch", () => { const result = calculateCableSizing({ ...BASE_INPUT, existingProtectionRatedCurrentA: 1000, }); assert.ok(result.protectionCoordination); assert.equal(result.protectionCoordination?.coordinated, false); const alerts = buildCableSizingAlerts( { ...BASE_INPUT, existingProtectionRatedCurrentA: 1000 }, result ); assert.ok(alerts.some((alert) => alert.text.includes("Koordination prüfen"))); }); }); describe("buildCableSizingAlerts", () => { it("returns a single critical alert for an unverified combination, no numeric claims", () => { const input: CableSizingInput = { ...BASE_INPUT, layingMethod: "G" }; const result = calculateCableSizing(input); const alerts = buildCableSizingAlerts(input, result); assert.equal(alerts.length, 1); assert.equal(alerts[0].kind, "critical"); assert.ok(alerts[0].text.includes("keine geprüften")); }); it("returns a single ok alert for a clean, unremarkable case", () => { const input: CableSizingInput = { ...BASE_INPUT, mode: "current", currentA: 15, powerKw: undefined, lengthM: 3, }; const result = calculateCableSizing(input); const alerts = buildCableSizingAlerts(input, result); assert.equal(alerts.length, 1); assert.equal(alerts[0].kind, "ok"); }); });