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>
193 lines
4.9 KiB
TypeScript
193 lines
4.9 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { describe, it } from "node:test";
|
|
import {
|
|
createCircuitSectionsReorderProjectCommand,
|
|
} from "../src/domain/models/circuit-sections-reorder-project-command.model.js";
|
|
import {
|
|
buildCircuitSectionReorderAssignments,
|
|
} from "../src/frontend/utils/circuit-section-reorder-command.js";
|
|
import {
|
|
reorderCircuitSectionCommand,
|
|
reorderCircuitSectionsCommand,
|
|
} from "../src/frontend/utils/api.js";
|
|
import type { CircuitTreeCircuitDto } from "../src/frontend/types.js";
|
|
|
|
function circuit(
|
|
id: string,
|
|
sortOrder: number
|
|
): CircuitTreeCircuitDto {
|
|
return {
|
|
id,
|
|
circuitListId: "list-1",
|
|
sectionId: "section-1",
|
|
equipmentIdentifier: id,
|
|
sortOrder,
|
|
isReserve: true,
|
|
circuitTotalPower: 0,
|
|
circuitApparentPower: 0,
|
|
circuitCosPhi: 1,
|
|
deviceRows: [],
|
|
downstreamBoardLoads: [],
|
|
};
|
|
}
|
|
|
|
describe("circuit section reorder command adapters", () => {
|
|
it("builds complete exact assignments for a requested order", () => {
|
|
const circuits = [
|
|
circuit("circuit-1", 10),
|
|
circuit("circuit-2", 20),
|
|
circuit("circuit-3", 30),
|
|
];
|
|
|
|
assert.deepEqual(
|
|
buildCircuitSectionReorderAssignments(circuits, [
|
|
"circuit-3",
|
|
"circuit-1",
|
|
"circuit-2",
|
|
]),
|
|
[
|
|
{
|
|
circuitId: "circuit-3",
|
|
expectedSortOrder: 30,
|
|
targetSortOrder: 10,
|
|
},
|
|
{
|
|
circuitId: "circuit-1",
|
|
expectedSortOrder: 10,
|
|
targetSortOrder: 20,
|
|
},
|
|
{
|
|
circuitId: "circuit-2",
|
|
expectedSortOrder: 20,
|
|
targetSortOrder: 30,
|
|
},
|
|
]
|
|
);
|
|
});
|
|
|
|
it("omits unchanged orders and rejects incomplete orders", () => {
|
|
const circuits = [
|
|
circuit("circuit-1", 10),
|
|
circuit("circuit-2", 20),
|
|
];
|
|
assert.deepEqual(
|
|
buildCircuitSectionReorderAssignments(circuits, [
|
|
"circuit-1",
|
|
"circuit-2",
|
|
]),
|
|
[]
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
buildCircuitSectionReorderAssignments(circuits, [
|
|
"circuit-1",
|
|
]),
|
|
/jeden Stromkreis/
|
|
);
|
|
});
|
|
|
|
it("validates atomic multi-section reorder envelopes", () => {
|
|
const assignments = [
|
|
{
|
|
circuitId: "circuit-1",
|
|
expectedSortOrder: 10,
|
|
targetSortOrder: 20,
|
|
},
|
|
{
|
|
circuitId: "circuit-2",
|
|
expectedSortOrder: 20,
|
|
targetSortOrder: 10,
|
|
},
|
|
];
|
|
const command = createCircuitSectionsReorderProjectCommand([
|
|
{ sectionId: "section-1", assignments },
|
|
{
|
|
sectionId: "section-2",
|
|
assignments: assignments.map((assignment) => ({
|
|
...assignment,
|
|
circuitId: `${assignment.circuitId}-other`,
|
|
})),
|
|
},
|
|
]);
|
|
assert.equal(command.type, "circuit.reorder-sections");
|
|
assert.throws(
|
|
() =>
|
|
createCircuitSectionsReorderProjectCommand([
|
|
{ sectionId: "section-1", assignments },
|
|
{ sectionId: "section-1", assignments },
|
|
]),
|
|
/duplicate section ids/
|
|
);
|
|
});
|
|
|
|
it("sends single and multi-section commands through project history", async () => {
|
|
const requests: Array<Record<string, unknown>> = [];
|
|
const originalFetch = globalThis.fetch;
|
|
globalThis.fetch = async (_input, init) => {
|
|
requests.push(
|
|
JSON.parse(String(init?.body)) as Record<string, unknown>
|
|
);
|
|
return new Response(
|
|
JSON.stringify({
|
|
revision: {
|
|
revisionId: "revision-1",
|
|
changeSetId: "change-1",
|
|
projectId: "project-1",
|
|
revisionNumber: requests.length,
|
|
createdAtIso: "2026-07-25T00:00:00.000Z",
|
|
},
|
|
history: {
|
|
projectId: "project-1",
|
|
currentRevision: requests.length,
|
|
undoDepth: requests.length,
|
|
redoDepth: 0,
|
|
undoChangeSetId: "change-1",
|
|
redoChangeSetId: null,
|
|
},
|
|
}),
|
|
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
);
|
|
};
|
|
|
|
const assignments = [
|
|
{
|
|
circuitId: "circuit-1",
|
|
expectedSortOrder: 10,
|
|
targetSortOrder: 20,
|
|
},
|
|
{
|
|
circuitId: "circuit-2",
|
|
expectedSortOrder: 20,
|
|
targetSortOrder: 10,
|
|
},
|
|
];
|
|
try {
|
|
await reorderCircuitSectionCommand(
|
|
"project-1",
|
|
0,
|
|
"section-1",
|
|
assignments,
|
|
"single"
|
|
);
|
|
await reorderCircuitSectionsCommand(
|
|
"project-1",
|
|
1,
|
|
[{ sectionId: "section-1", assignments }],
|
|
"multiple"
|
|
);
|
|
} finally {
|
|
globalThis.fetch = originalFetch;
|
|
}
|
|
|
|
assert.deepEqual(
|
|
requests.map((request) => {
|
|
const command = request.command as { type: string };
|
|
return [request.expectedRevision, command.type];
|
|
}),
|
|
[
|
|
[0, "circuit.reorder-section"],
|
|
[1, "circuit.reorder-sections"],
|
|
]
|
|
);
|
|
});
|
|
});
|