forked from jappel/leistungsbilanz-ts
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>
138 lines
3.4 KiB
TypeScript
138 lines
3.4 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { describe, it } from "node:test";
|
|
import {
|
|
buildCircuitDeviceRowMoveAssignments,
|
|
} from "../src/frontend/utils/circuit-device-row-move-command.js";
|
|
import type {
|
|
CircuitTreeCircuitDto,
|
|
CircuitTreeDeviceRowDto,
|
|
} from "../src/frontend/types.js";
|
|
|
|
function row(
|
|
id: string,
|
|
sortOrder: number
|
|
): CircuitTreeDeviceRowDto {
|
|
return {
|
|
id,
|
|
sortOrder,
|
|
name: id,
|
|
displayName: id,
|
|
quantity: 1,
|
|
manualQuantity: 1,
|
|
powerPerUnit: 0.1,
|
|
simultaneityFactor: 1,
|
|
rowTotalPower: 0.1,
|
|
};
|
|
}
|
|
|
|
function circuit(
|
|
id: string,
|
|
deviceRows: CircuitTreeDeviceRowDto[]
|
|
): CircuitTreeCircuitDto {
|
|
return {
|
|
id,
|
|
circuitListId: "list-1",
|
|
sectionId: "section-1",
|
|
equipmentIdentifier: id,
|
|
sortOrder: 10,
|
|
isReserve: deviceRows.length === 0,
|
|
circuitTotalPower: 0,
|
|
circuitApparentPower: 0,
|
|
circuitCosPhi: 1,
|
|
deviceRows,
|
|
downstreamBoardLoads: [],
|
|
};
|
|
}
|
|
|
|
describe("circuit device-row move command builder", () => {
|
|
it("records exact sources and appends rows in selection order", () => {
|
|
const targetRows = [row("target-row", 20)];
|
|
const circuits = [
|
|
circuit("source-1", [row("row-1", 30)]),
|
|
circuit("source-2", [row("row-2", 10)]),
|
|
circuit("target", targetRows),
|
|
];
|
|
|
|
assert.deepEqual(
|
|
buildCircuitDeviceRowMoveAssignments({
|
|
circuits,
|
|
rowIds: ["row-2", "row-1"],
|
|
targetCircuitId: "target",
|
|
targetDeviceRows: targetRows,
|
|
}),
|
|
[
|
|
{
|
|
rowId: "row-2",
|
|
expectedCircuitId: "source-2",
|
|
expectedSortOrder: 10,
|
|
targetCircuitId: "target",
|
|
targetSortOrder: 30,
|
|
},
|
|
{
|
|
rowId: "row-1",
|
|
expectedCircuitId: "source-1",
|
|
expectedSortOrder: 30,
|
|
targetCircuitId: "target",
|
|
targetSortOrder: 40,
|
|
},
|
|
]
|
|
);
|
|
});
|
|
|
|
it("starts a generated target circuit at sort order ten", () => {
|
|
assert.deepEqual(
|
|
buildCircuitDeviceRowMoveAssignments({
|
|
circuits: [circuit("source", [row("row-1", 40)])],
|
|
rowIds: ["row-1"],
|
|
targetCircuitId: "generated-target",
|
|
targetDeviceRows: [],
|
|
}),
|
|
[
|
|
{
|
|
rowId: "row-1",
|
|
expectedCircuitId: "source",
|
|
expectedSortOrder: 40,
|
|
targetCircuitId: "generated-target",
|
|
targetSortOrder: 10,
|
|
},
|
|
]
|
|
);
|
|
});
|
|
|
|
it("omits unchanged assignments during a same-circuit reorder", () => {
|
|
const rows = [row("row-1", 10), row("row-2", 20)];
|
|
assert.deepEqual(
|
|
buildCircuitDeviceRowMoveAssignments({
|
|
circuits: [circuit("target", rows)],
|
|
rowIds: ["row-1", "row-2"],
|
|
targetCircuitId: "target",
|
|
targetDeviceRows: rows,
|
|
}),
|
|
[]
|
|
);
|
|
});
|
|
|
|
it("rejects duplicate or missing selected rows", () => {
|
|
const circuits = [circuit("source", [row("row-1", 10)])];
|
|
assert.throws(
|
|
() =>
|
|
buildCircuitDeviceRowMoveAssignments({
|
|
circuits,
|
|
rowIds: ["row-1", "row-1"],
|
|
targetCircuitId: "target",
|
|
targetDeviceRows: [],
|
|
}),
|
|
/mehrfach/
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
buildCircuitDeviceRowMoveAssignments({
|
|
circuits,
|
|
rowIds: ["missing"],
|
|
targetCircuitId: "target",
|
|
targetDeviceRows: [],
|
|
}),
|
|
/nicht gefunden/
|
|
);
|
|
});
|
|
});
|