Extract circuit grid projection
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import {
|
||||
buildVisibleGridRows,
|
||||
filterAndSortCircuitSections,
|
||||
getDistinctFilterValues,
|
||||
} from "../src/frontend/utils/circuit-grid-projection.js";
|
||||
import type {
|
||||
CircuitTreeCircuitDto,
|
||||
CircuitTreeDeviceRowDto,
|
||||
CircuitTreeSectionDto,
|
||||
} from "../src/frontend/types.js";
|
||||
|
||||
function makeDevice(
|
||||
id: string,
|
||||
displayName: string,
|
||||
roomNumberSnapshot: string,
|
||||
sortOrder: number
|
||||
): CircuitTreeDeviceRowDto {
|
||||
return {
|
||||
id,
|
||||
sortOrder,
|
||||
name: displayName,
|
||||
displayName,
|
||||
roomNumberSnapshot,
|
||||
quantity: 1,
|
||||
powerPerUnit: 0.1,
|
||||
simultaneityFactor: 1,
|
||||
rowTotalPower: 0.1,
|
||||
};
|
||||
}
|
||||
|
||||
function makeCircuit(
|
||||
id: string,
|
||||
equipmentIdentifier: string,
|
||||
displayName: string,
|
||||
deviceRows: CircuitTreeDeviceRowDto[],
|
||||
sortOrder: number
|
||||
): CircuitTreeCircuitDto {
|
||||
return {
|
||||
id,
|
||||
circuitListId: "list-1",
|
||||
sectionId: "section-1",
|
||||
equipmentIdentifier,
|
||||
displayName,
|
||||
sortOrder,
|
||||
isReserve: deviceRows.length === 0,
|
||||
circuitTotalPower: deviceRows.reduce((total, row) => total + row.rowTotalPower, 0),
|
||||
deviceRows,
|
||||
};
|
||||
}
|
||||
|
||||
const multiDeviceCircuit = makeCircuit(
|
||||
"circuit-multi",
|
||||
"-1F2",
|
||||
"Office lighting",
|
||||
[makeDevice("device-office", "Office light", "1.01", 10), makeDevice("device-store", "Store light", "1.02", 20)],
|
||||
20
|
||||
);
|
||||
const compactCircuit = makeCircuit(
|
||||
"circuit-compact",
|
||||
"-1F1",
|
||||
"Corridor lighting",
|
||||
[makeDevice("device-corridor", "Corridor light", "1.03", 10)],
|
||||
10
|
||||
);
|
||||
const reserveCircuit = makeCircuit("circuit-reserve", "-1F3", "Reserve", [], 30);
|
||||
|
||||
const sections: CircuitTreeSectionDto[] = [
|
||||
{
|
||||
id: "section-1",
|
||||
key: "lighting",
|
||||
displayName: "Lighting",
|
||||
prefix: "-1F",
|
||||
sortOrder: 10,
|
||||
circuits: [compactCircuit, multiDeviceCircuit, reserveCircuit],
|
||||
},
|
||||
];
|
||||
|
||||
describe("circuit grid projection", () => {
|
||||
it("keeps every device row in a circuit block when one device matches a filter", () => {
|
||||
const result = filterAndSortCircuitSections(sections, { roomNumberSnapshot: ["1.01"] }, null);
|
||||
|
||||
assert.deepEqual(result.map((section) => section.circuits.map((circuit) => circuit.id)), [["circuit-multi"]]);
|
||||
assert.deepEqual(result[0].circuits[0].deviceRows.map((row) => row.id), ["device-office", "device-store"]);
|
||||
});
|
||||
|
||||
it("combines column filters across the complete circuit block", () => {
|
||||
const result = filterAndSortCircuitSections(
|
||||
sections,
|
||||
{ equipmentIdentifier: ["-1F2"], roomNumberSnapshot: ["1.02"] },
|
||||
null
|
||||
);
|
||||
|
||||
assert.deepEqual(result[0].circuits.map((circuit) => circuit.id), ["circuit-multi"]);
|
||||
});
|
||||
|
||||
it("treats missing device values as missing without matching populated circuits", () => {
|
||||
const result = filterAndSortCircuitSections(sections, { roomNumberSnapshot: ["-"] }, null);
|
||||
|
||||
assert.deepEqual(result[0].circuits.map((circuit) => circuit.id), ["circuit-reserve"]);
|
||||
});
|
||||
|
||||
it("sorts complete circuit blocks without changing device row order", () => {
|
||||
const result = filterAndSortCircuitSections(sections, {}, { key: "equipmentIdentifier", direction: "desc" });
|
||||
|
||||
assert.deepEqual(result[0].circuits.map((circuit) => circuit.id), [
|
||||
"circuit-reserve",
|
||||
"circuit-multi",
|
||||
"circuit-compact",
|
||||
]);
|
||||
assert.deepEqual(result[0].circuits[1].deviceRows.map((row) => row.id), ["device-office", "device-store"]);
|
||||
});
|
||||
|
||||
it("builds the compact, grouped, reserve and placeholder row shapes", () => {
|
||||
const rows = buildVisibleGridRows(sections);
|
||||
|
||||
assert.deepEqual(rows.map((row) => row.rowType), [
|
||||
"section",
|
||||
"circuitCompact",
|
||||
"circuitSummary",
|
||||
"deviceRow",
|
||||
"deviceRow",
|
||||
"reserveCircuit",
|
||||
"placeholder",
|
||||
]);
|
||||
assert.equal(rows.at(-1)?.rowKey, "placeholder:section-1");
|
||||
assert.equal(
|
||||
rows.at(-1)?.cells.find((cell) => cell.cellKey === "equipmentIdentifier")?.value,
|
||||
"-frei-"
|
||||
);
|
||||
});
|
||||
|
||||
it("collects filter options from both circuit and device values", () => {
|
||||
const values = getDistinctFilterValues(sections, [
|
||||
{ key: "displayName", label: "Display name" },
|
||||
{ key: "roomNumberSnapshot", label: "Room number" },
|
||||
]);
|
||||
|
||||
assert.ok(values.displayName.includes("Office lighting"));
|
||||
assert.ok(values.displayName.includes("Store light"));
|
||||
assert.ok(values.roomNumberSnapshot.includes("1.03"));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user