test.build/core/converters/graph.converter.test.ts
test.build/core/converters/graph.converter.test.ts is a file in Codebase Testing. 91 lines of code and 0 definitions.
import { CONTAINS_RELATION, EVIDENCE_RELATION_ID } from "@banes-lab/web/constants/graph.constants";
import { REFERENCED_BY, VOCABULARY, graphNode } from "./graph.fixture.ts";
import {
danglingEdges,
edgeIndexOf,
groundingSources,
inboundRelations,
mergeGraphs,
outboundRelations,
} from "@banes-lab/build-scripts/core/converters/graph.converter.ts";
import { describe, expect, it } from "vitest";
const A = "architecture:a";
const B = "architecture:b";
const GRAPH = { edges: [{ from: A, relation: "requires", to: B }], nodes: [graphNode(A, null), graphNode(B, null)] };
describe("inboundRelations", () => {
it("groups each node's inbound edges under the declared reverse, titled by the source", () => {
expect(inboundRelations(GRAPH, VOCABULARY.pairs).get(B)).toStrictEqual([
{ edges: [{ label: A, ref: A }], relation: REFERENCED_BY },
]);
expect(() =>
inboundRelations({ edges: [{ from: "a", relation: "invented", to: "b" }], nodes: [] }, VOCABULARY.pairs),
).toThrow('the relation "invented" from a has no reverse');
});
});
describe("outboundRelations", () => {
it("groups each node's outgoing edges under their own relation, titled by the target, once per target", () => {
const twice = { edges: [...GRAPH.edges, ...GRAPH.edges], nodes: GRAPH.nodes };
expect(outboundRelations(twice).get(A)).toStrictEqual([
{ edges: [{ label: B, ref: B }], relation: "requires" },
]);
expect(outboundRelations(GRAPH).get(B)).toBeUndefined();
});
});
describe("edgeIndexOf", () => {
it("answers each node's outgoing and incoming edges by relation", () => {
const index = edgeIndexOf(GRAPH);
expect(index.outgoing(A, "requires")).toStrictEqual([{ label: B, ref: B }]);
expect(index.incoming(B, "requires")).toStrictEqual([{ label: A, ref: A }]);
expect(index.incoming(A, "requires")).toStrictEqual([]);
});
});
describe("groundingSources", () => {
const SECTION = "chapter:/anatomy#f";
const FOLDER = "anatomy:f";
const FILE = "anatomy:f/x.ts";
const TEACHER = "chapter:/p#s";
const OTHER = "chapter:/p#t";
const graph = {
edges: [
{ from: TEACHER, relation: EVIDENCE_RELATION_ID, to: FOLDER },
{ from: FOLDER, relation: CONTAINS_RELATION, to: FILE },
{ from: OTHER, relation: EVIDENCE_RELATION_ID, to: FILE },
],
nodes: [
graphNode(SECTION, "/anatomy#f"),
graphNode(FOLDER, "/anatomy#f"),
graphNode(FILE, null),
graphNode(TEACHER, null),
graphNode(OTHER, null),
],
};
it("reads evidence into every node that shares the ref's page address, so a folder cited as evidence grounds its section", () => {
const sources = groundingSources(graph, edgeIndexOf(graph), (ref) => (ref === SECTION ? "/anatomy#f" : null));
expect(sources(SECTION)).toStrictEqual([{ label: TEACHER, ref: TEACHER }]);
});
it("reads evidence into the parts a node contains, and lists each source once", () => {
const sources = groundingSources(graph, edgeIndexOf(graph), () => null);
expect(sources(FOLDER)).toStrictEqual([
{ label: TEACHER, ref: TEACHER },
{ label: OTHER, ref: OTHER },
]);
expect(sources(TEACHER)).toStrictEqual([]);
});
});
describe("mergeGraphs", () => {
it("keeps the first node per ref, stores each edge once and reports a ref claimed by two kinds", () => {
const clash = { ...graphNode(B, null), kind: "other" };
const merged = mergeGraphs([GRAPH, { edges: GRAPH.edges, nodes: [clash] }]);
expect(merged.nodes).toHaveLength(2);
expect(merged.edges).toHaveLength(1);
expect(merged.duplicates).toHaveLength(1);
});
});
describe("danglingEdges", () => {
it("names an edge whose end no node carries", () => {
expect(danglingEdges(GRAPH)).toStrictEqual([]);
expect(
danglingEdges({ edges: [{ from: A, relation: "requires", to: "gone" }], nodes: GRAPH.nodes }),
).toHaveLength(1);
});
});