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 { 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); }); });