import { describe, it, expect } from 'vitest'; import { harvestCard, parseEntities, parseEdges, parseFrontmatter } from '../src/lib/harvest'; const CARD = `--- tags: [掛載架構, 架構設計] gloss: ingest 在 KBDB 堆疊裡的位置。 --- # 掛載架構 ← [[ingest/00-INDEX]] ## 摘要 KBDB 是三層堆疊。 ## 實體 - **kbdb-ingest-plugin**(餵食器) — 最薄一層,純 POST 候選。 - **base KBDB**(arcrun/kbdb/基本盤) — 最底儲存層。 ## 關聯 ### 內文知識關係 - kbdb-ingest-plugin >> 掛載於 >> base KBDB ### 卡片關係 - [[掛載架構]] >> 受約束於 >> [[envelope-契約]] `; describe('parseFrontmatter', () => { it('抽出 gloss', () => { const { fm, body } = parseFrontmatter(CARD); expect(fm.gloss).toBe('ingest 在 KBDB 堆疊裡的位置。'); expect(body).toContain('# 掛載架構'); }); }); describe('parseEntities', () => { it('解析正規名 + aliases + gloss', () => { const { body } = parseFrontmatter(CARD); const nodes = parseEntities(body); expect(nodes.map((n) => n.name)).toEqual(['kbdb-ingest-plugin', 'base KBDB']); expect(nodes[1].aliases).toEqual(['arcrun/kbdb', '基本盤']); expect(nodes[0].gloss).toBe('最薄一層,純 POST 候選。'); expect(nodes[0].embed).toBe(true); }); }); describe('parseEdges', () => { it('解析 typed-edge、去 [[ ]]、標記卡對卡', () => { const { body } = parseFrontmatter(CARD); const edges = parseEdges(body); expect(edges).toContainEqual({ subject: 'kbdb-ingest-plugin', predicate: '掛載於', object: 'base KBDB', predicate_embed: true, subjectIsCard: false, objectIsCard: false }); expect(edges).toContainEqual({ subject: '掛載架構', predicate: '受約束於', object: 'envelope-契約', predicate_embed: true, subjectIsCard: true, objectIsCard: true }); }); }); describe('harvestCard', () => { it('卡標題 node 帶 frontmatter gloss、含內文 node', () => { const r = harvestCard(CARD); const titleNode = r.nodes.find((n) => n.name === '掛載架構'); expect(titleNode?.gloss).toBe('ingest 在 KBDB 堆疊裡的位置。'); expect(r.nodes.some((n) => n.name === 'base KBDB')).toBe(true); expect(r.triplets.length).toBe(2); }); it('內文端點對齊(無對不齊)', () => { const r = harvestCard(CARD); // kbdb-ingest-plugin / base KBDB 都在 ## 實體;卡對卡端點不要求 expect(r.unalignedEndpoints).toEqual([]); }); });