Files
learnharness/tests/graph-view-filters.test.ts
T
amosblomqvist 54f88f37e1 Strip the transitional node-state classes (2026-09-08)
The five-class NodeStateClass (taught/known/missed/dont-know/candidate)
was transitional scaffelage from the 2026-09-02 redesign, deriving state
by latest-quiz-wins — exactly what the philosophy rejects: understanding
is inferred at read time from the real state model (still pending
ideation), never encoded as quiz-derived classes.

- contracts: NodeStateClass deleted; GraphSnapshot no longer carries
  nodeStates (objective graph + sessions only).
- core: deriveNodeStates replaced by latestQuizOutcomes — the raw
  event fact (nodeId -> latest quiz kind), consumed ONLY by the
  teacher's graph-as-context selection, never by the home renderer.
- graph-context: hotspot selection re-keyed to outcomes — groups are
  now 'Hotspots (last answer wrong or don-t-know) / Answered correctly /
  Never probed'. Same diagnostic selection, no state taxonomy.
- graph-view: nodes render uniformly (accent color, size 8); the panel
  is search-only; the detail card's state badge is gone. Quiz outcomes
  remain ledger data for the future state model.

Verified live (headless): uniform discs (single color/size, zero state
pixels), search-only panel, card = name + statement + sessions, no
console errors.
2026-09-09 01:24:08 +03:00

39 lines
1.2 KiB
TypeScript

/**
* Legend/filters predicate tests — the pure half of the graph-view filters
* panel (isNodeVisible); the sigma reducers just consume its verdict.
*/
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { isNodeVisible } from "../components/graph-view.tsx";
const node = {
name: "Money multiplier",
statement: "The maximum ratio of broad money a bank can create from each unit of base money.",
};
describe("isNodeVisible (search predicate)", () => {
it("is visible with an empty query", () => {
assert.equal(isNodeVisible(node, ""), true);
});
it("search matches the statement case-insensitively", () => {
assert.equal(isNodeVisible(node, "MONEY multiplier"), true);
});
it("search matches the statement when the name does not", () => {
assert.equal(isNodeVisible(node, "MAXIMUM ratio"), true);
assert.equal(isNodeVisible(node, " velocity"), false);
});
it("search matches the name when the statement does not", () => {
assert.equal(isNodeVisible(node, "money MULTIPLIER"), true);
assert.equal(isNodeVisible(node, " banking"), false);
});
it("whitespace-only query is no filter", () => {
assert.equal(isNodeVisible(node, " "), true);
});
});