// get_source + refresh(C 段)— 走 mock,零 SQL、不打真網路。 import { describe, it, expect } from 'vitest'; import { ingestEnvelope } from '../src/actions/triplet-ingest'; import { getSource } from '../src/actions/graph-source'; import { refreshSource } from '../src/actions/graph-refresh'; import { mockClient } from './mock-client'; describe('getSource — 回節點的原文來源指標', () => { it('回觸及節點的 triplet 的 uri + anchor', async () => { const c = mockClient(); await ingestEnvelope(c, { source: { uri: 'github:u/w@a.md', content_hash: 'h1', anchor: '#graph-rag' }, extractor: { model: 'm', tier: 'deep' }, triplets: [{ subject: 'GraphRAG', predicate: '是', object: 'RAG 變體' }], }); const refs = await getSource(c, 'GraphRAG'); expect(refs.length).toBe(1); expect(refs[0].uri).toBe('github:u/w@a.md'); expect(refs[0].anchor).toBe('#graph-rag'); expect(refs[0].edge).toEqual({ subject: 'GraphRAG', predicate: '是', object: 'RAG 變體' }); }); it('deprecated triplet 不出現在 get_source(active-only)', async () => { const c = mockClient(); await ingestEnvelope(c, { source: { uri: 'github:u/w@a.md', content_hash: 'h1', anchor: '#old' }, extractor: { model: 'm', tier: 'deep' }, triplets: [{ subject: 'X', predicate: 'r', object: 'old' }], }); await ingestEnvelope(c, { source: { uri: 'github:u/w@a.md', content_hash: 'h2', anchor: '#new' }, extractor: { model: 'm', tier: 'deep' }, triplets: [{ subject: 'X', predicate: 'r', object: 'new' }], }); const refs = await getSource(c, 'X'); expect(refs.length).toBe(1); expect(refs[0].anchor).toBe('#new'); // 只見 active 批 }); }); describe('refreshSource — 代轉 ingest(人發起)', () => { it('KBDB_INGEST_URL 未設 → 誠實回 forwarded:false,不假裝成功', async () => { const res = await refreshSource({ uri: 'github:u/w@a.md' }, undefined); expect(res.forwarded).toBe(false); expect(res.note).toMatch(/未就緒|未設/); }); });