Files
learnharness/tests/graph-view-filters.test.ts
T
amosblomqvist bdd9cac2b7 Node schema pivot: short name (label) + full-precision statement; description dropped
With real extracted data, full-sentence statements as canvas labels proved
unworkable: 10-line label blocks, illegible overprint clusters, bottom-edge
clipping. Per the user's 2026-09-08 decision:

- GraphNode/ExtractedProposition gain `name` — a very short, glanceable
  label (glossary-headword style: "Will to power"), presentational only:
  not unique, not identity, never precise. Set at creation; link-appends
  never change it (first line defines; labels stay stable across sessions).
- `statement` keeps its full precision and becomes the identity anchor;
  the detail card shows it under the name. `description` is dropped.
- Extractor coins the name (freshest session context); auditor carries it
  through on create, rewording only clearly unglanceable names; linked
  propositions keep the existing node's name.
- Renderer: canvas label = name; search matches name + statement;
  detail card = name (bold) + statement (muted).
- Store guard requires name (pre-pivot node lines are skipped as legacy);
  vision.md node-schema bullet + amendments table updated (2026-09-08).
2026-09-09 00:40:02 +03:00

56 lines
2.1 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";
import type { NodeStateClass } from "../src/core/index.ts";
const none: ReadonlySet<NodeStateClass> = new Set();
const node = {
name: "Money multiplier",
statement: "The maximum ratio of broad money a bank can create from each unit of base money.",
};
describe("isNodeVisible (legend/filters predicate)", () => {
it("is visible with no filters", () => {
assert.equal(isNodeVisible(node, "known", none, ""), true);
});
it("is hidden when its state is toggled off, even if the query matches", () => {
const hidden = new Set<NodeStateClass>(["known"]);
assert.equal(isNodeVisible(node, "known", hidden, "money"), false);
});
it("a toggled-off state does not affect other states", () => {
const hidden = new Set<NodeStateClass>(["known"]);
assert.equal(isNodeVisible(node, "taught", hidden, ""), true);
});
it("search matches the statement case-insensitively", () => {
assert.equal(isNodeVisible(node, "candidate", none, "MONEY multiplier"), true);
});
it("search matches the statement when the name does not", () => {
assert.equal(isNodeVisible(node, "candidate", none, "MAXIMUM ratio"), true);
assert.equal(isNodeVisible(node, "candidate", none, " velocity"), false);
});
it("search matches the name when the statement does not", () => {
assert.equal(isNodeVisible(node, "candidate", none, "money MULTIPLIER"), true);
assert.equal(isNodeVisible(node, "candidate", none, " banking"), false);
});
it("whitespace-only query is no filter", () => {
assert.equal(isNodeVisible(node, "missed", none, " "), true);
});
it("a node with no state entry defaults to candidate", () => {
// candidate hidden → invisible; visible otherwise.
const hidden = new Set<NodeStateClass>(["candidate"]);
assert.equal(isNodeVisible(node, "candidate", hidden, ""), false);
assert.equal(isNodeVisible(node, "candidate", none, ""), true);
});
});