// graph 查詢 — 圖在插件層記憶體組裝(不靠 DB VIEW),走 mock client。 import { describe, it, expect } from 'vitest'; import { createTriplet } from '../src/actions/triplet-crud'; import { listNodes, getNodeEdges, getNeighbors } from '../src/actions/graph-nodes'; import { findShortestPath } from '../src/actions/graph-path'; import { mockClient } from './mock-client'; import type { KbdbClient } from '../src/lib/kbdb-client'; async function seed(c: KbdbClient) { // A — B — C,D 孤立連 A await createTriplet(c, { subject: 'A', predicate: 'r', object: 'B' }); await createTriplet(c, { subject: 'B', predicate: 'r', object: 'C' }); await createTriplet(c, { subject: 'A', predicate: 'r', object: 'D' }); } describe('graph-nodes', () => { it('listNodes 統計 edge_count', async () => { const c = mockClient(); await seed(c); const nodes = await listNodes(c, {}); const a = nodes.find((n) => n.node === 'A'); expect(a?.edge_count).toBe(2); }); it('getNeighbors 收鄰居', async () => { const c = mockClient(); await seed(c); const neighbors = await getNeighbors(c, 'A'); expect(neighbors.sort()).toEqual(['B', 'D']); }); it('getNodeEdges 取邊', async () => { const c = mockClient(); await seed(c); const edges = await getNodeEdges(c, 'B'); expect(edges.length).toBe(2); }); }); describe('graph-path', () => { it('A→C 最短路經過 B', async () => { const c = mockClient(); await seed(c); const res = await findShortestPath(c, 'A', 'C'); expect(res.path).toEqual(['A', 'B', 'C']); }); });