Files
Entropyk/apps/web/src/lib/dofCoach.test.ts
sepehr 3358b74342 Add diagram workbench UI with Modelica DoF coaching and ISO glyphs.
Ship the Next.js cycle editor with CAD chrome, technical HX symbols, Fixed/Free boundary guidance, and secondary water/air pressure drop support in the solver stack.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-17 22:46:46 +02:00

66 lines
2.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { Edge, Node } from "@xyflow/react";
import type { EntropykNodeData } from "./configBuilder";
import { buildDofCoach } from "./dofCoach";
import { hxFamily, hxGlyphKey } from "./hxFamily";
function node(
id: string,
type: string,
params: EntropykNodeData["params"] = {},
): Node<EntropykNodeData> {
return {
id,
type: "entropyk",
position: { x: 0, y: 0 },
data: { type, name: id, circuit: 1, params },
};
}
describe("hxFamily", () => {
it("distinguishes DX / flooded / plate / coil / MCHX", () => {
expect(hxFamily("Evaporator")?.badge).toBe("DX");
expect(hxFamily("FloodedEvaporator")?.badge).toBe("Noyé");
expect(hxFamily("BphxCondenser")?.badge).toBe("Plaques");
expect(hxFamily("AirCooledCondenser")?.badge).toBe("Coil");
expect(hxFamily("MchxCondenser")?.badge).toBe("MCHX");
expect(hxFamily("Condenser")?.badge).toBe("Tubes");
expect(hxGlyphKey("FloodedEvaporator")).toBe("hx_flooded");
expect(hxGlyphKey("BphxEvaporator")).toBe("hx_plate");
});
});
describe("buildDofCoach", () => {
it("guides empty canvas", () => {
const coach = buildDofCoach([], []);
expect(coach.balance).toBe("empty");
expect(coach.tips[0]?.id).toBe("empty");
});
it("flags Fixed P + Fixed ṁ on MassFlowSource-style brine source", () => {
const nodes = [
node("src", "BrineSource", {
p_set_bar: 3,
t_set_c: 12,
m_flow_kg_s: 1.2,
fix_pressure: true,
fix_mass_flow: true,
}),
];
const coach = buildDofCoach(nodes, []);
expect(coach.tips.some((t) => t.id.startsWith("mflow-p"))).toBe(true);
});
it("suggests wiring secondary when HX has no secondary edges", () => {
const nodes = [
node("comp", "ScrollCompressor", {}),
node("cond", "Condenser", { ua: 1000 }),
node("exv", "ExpansionValve", {}),
node("evap", "Evaporator", { ua: 1000 }),
];
const edges: Edge[] = [];
const coach = buildDofCoach(nodes, edges);
expect(coach.tips.some((t) => t.id.startsWith("sec-"))).toBe(true);
});
});