FN-018: fix KnowledgeGraphPanel hop typing
Normalize absent path hop counts for the typed graph path interpolation while preserving zero-hop results. - Use undefined for non-found path hop counts to satisfy the typed interpolation contract. - Add regression coverage that renders a found zero-hop path. Files changed: packages/dashboard/app/components/KnowledgeGraphPanel.tsx | 3 ++- .../dashboard/app/components/__tests__/KnowledgeGraphPanel.test.tsx | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-018 Fusion-Task-Lineage: 28254bbd-967b-463e-87de-8dfa847ca42d Co-authored-by: Fusion <noreply@runfusion.ai>
This commit is contained in:
@@ -42,7 +42,8 @@ export function KnowledgeGraphPanel({ projectId, addToast }: { projectId?: strin
|
||||
const selected = graph.selectedId;
|
||||
const limits = graph.status.pathLimits;
|
||||
const foundPath = graph.pathResult?.outcome === "found" ? graph.pathResult.path : null;
|
||||
const foundHops = graph.pathResult?.outcome === "found" ? graph.pathResult.hops : null;
|
||||
/* FNXC:KnowledgeGraphDashboard 2026-08-18-22:31: The typed i18n interpolation treats absent hop counts as optional; keep successful zero-hop paths numeric while normalizing non-found results to undefined. */
|
||||
const foundHops = graph.pathResult?.outcome === "found" ? graph.pathResult.hops : undefined;
|
||||
|
||||
return <section className="knowledge-graph-panel" data-testid="knowledge-graph-panel">
|
||||
<header className="knowledge-graph-status card"><div><strong>{graph.status.nodeCount} {t("memory.graphNodes", "nodes")} · {graph.status.edgeCount} {t("memory.graphEdges", "edges")}</strong><span>{graph.status.graphDir}</span></div><dl><div><dt>{t("knowledgeGraph.nodeKinds", "Node kinds")}</dt><dd>{Object.entries(graph.status.nodeKindCounts ?? {}).map(([kind, count]) => `${kind}: ${count}`).join(" · ") || "—"}</dd></div><div><dt>{t("knowledgeGraph.edgeKinds", "Edge kinds")}</dt><dd>{Object.entries(graph.status.edgeKindCounts ?? {}).map(([kind, count]) => `${kind}: ${count}`).join(" · ") || "—"}</dd></div><div><dt>{t("knowledgeGraph.provenance", "Provenance")}</dt><dd>{Object.entries(graph.status.provenanceCounts ?? {}).map(([kind, count]) => `${kind}: ${count}`).join(" · ") || "—"}</dd></div></dl><label className="knowledge-graph-toggle"><input type="checkbox" checked={force} onChange={(event) => setForce(event.target.checked)} /> {t("memory.graphForce", "Force rebuild")}</label><button type="button" className="btn" disabled={graph.rebuilding} onClick={() => void graph.rebuild(force)}>{graph.rebuilding ? t("memory.graphRebuilding", "Rebuilding…") : t("memory.graphRebuild", "Rebuild")}</button></header>
|
||||
|
||||
@@ -42,7 +42,10 @@ describe("KnowledgeGraphPanel", () => {
|
||||
rerender(<KnowledgeGraphPanel addToast={vi.fn()} />);
|
||||
expect(screen.getByTestId("knowledge-graph-no-results")).toBeInTheDocument();
|
||||
for (const [result, id] of [[{ outcome: "found", path: { nodes: [node], edges: [] }, hops: 0, maxHops: 2, expansions: 1, truncated: false }, "knowledge-graph-path-found"], [{ outcome: "not-found", path: null, maxHops: 2, expansions: 2, truncated: false }, "knowledge-graph-path-not-found"], [{ outcome: "limit-reached", path: null, maxHops: 2, expansions: 2, truncated: true, limit: "max-hops" }, "knowledge-graph-path-limit-reached"]] as const) {
|
||||
useKnowledgeGraph.mockReturnValue(graph({ pathResult: result })); rerender(<KnowledgeGraphPanel addToast={vi.fn()} />); expect(screen.getByTestId(id)).toBeInTheDocument();
|
||||
useKnowledgeGraph.mockReturnValue(graph({ pathResult: result }));
|
||||
rerender(<KnowledgeGraphPanel addToast={vi.fn()} />);
|
||||
expect(screen.getByTestId(id)).toBeInTheDocument();
|
||||
if (id === "knowledge-graph-path-found") expect(screen.getByTestId(id)).toHaveTextContent("0 hops");
|
||||
}
|
||||
useKnowledgeGraph.mockReturnValue(graph({ error: "Unknown graph node" })); rerender(<KnowledgeGraphPanel addToast={vi.fn()} />); expect(screen.getByTestId("knowledge-graph-path-error")).toHaveTextContent("Unknown graph node");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user