import { describe, it, expect } from 'vitest'; import { makeGraphClient } from '../src/lib/graph-client'; import type { Envelope } from '../src/types'; const env: Envelope = { source: { uri: 'github:o/r@a.md', content_hash: 'abc' }, extractor: { model: 'local-harvest', tier: 'shallow' }, triplets: [{ subject: 'A', predicate: 'p', object: 'B' }], }; function mockFetch(status: number, body: unknown): typeof fetch { return (async () => new Response(JSON.stringify(body), { status, headers: { 'Content-Type': 'application/json' } })) as any; } describe('makeGraphClient', () => { it('GRAPH_BASE_URL 未設 → 誠實回 ok:false,不假綠、不打網路', async () => { let called = false; const client = makeGraphClient(undefined, undefined, (async () => { called = true; return new Response('{}'); }) as any); const r = await client.postEnvelope(env); expect(r.ok).toBe(false); expect(r.error).toContain('未設'); expect(called).toBe(false); }); it('200 → ok + 帶 graph 回的 {skipped,ingested,deprecated}', async () => { const client = makeGraphClient('https://graph.example', 'tok', mockFetch(200, { skipped: false, ingested: 1, deprecated: 0 })); const r = await client.postEnvelope(env); expect(r.ok).toBe(true); expect((r.body as any).ingested).toBe(1); }); it('422 → ok:false 帶 issues(供修禁送欄位)', async () => { const client = makeGraphClient('https://graph.example', undefined, mockFetch(422, { error: 'invalid envelope', issues: [{ path: ['bridge_score'] }] })); const r = await client.postEnvelope(env); expect(r.ok).toBe(false); expect(r.status).toBe(422); expect((r.body as any).issues).toBeDefined(); }); });