import { decorateCitations, resolveMemoryCitationsMode, shouldIncludeCitations, type CitationCandidate, } from '../citations'; describe('resolveMemoryCitationsMode', () => { it('accepts on/off/auto', () => { expect(resolveMemoryCitationsMode('on')).toBe('on'); expect(resolveMemoryCitationsMode('off')).toBe('off'); expect(resolveMemoryCitationsMode('auto')).toBe('auto'); }); it('falls back to auto for anything else', () => { expect(resolveMemoryCitationsMode(undefined)).toBe('auto'); expect(resolveMemoryCitationsMode('nonsense')).toBe('auto'); }); }); describe('shouldIncludeCitations', () => { it('on → true, off → false, auto → true in direct chat', () => { expect(shouldIncludeCitations('on')).toBe(true); expect(shouldIncludeCitations('off')).toBe(false); expect(shouldIncludeCitations('auto')).toBe(true); }); }); describe('decorateCitations', () => { it('strips citation when include=false', () => { const hits = [ { path: 'memory/x.md', content: 'hello', citation: 'memory/x.md#L1' }, ]; const out = decorateCitations(hits, false); expect(out[0].citation).toBeUndefined(); }); it('formats single-line citation as #L1', () => { const hits: CitationCandidate[] = [ { path: 'memory/x.md', content: 'hello' }, ]; const out = decorateCitations(hits, true); expect(out[0].citation).toBe('memory/x.md#L1'); expect(out[0].content).toContain('Source: memory/x.md#L1'); }); it('formats multi-line citation as #L1-LN', () => { const hits: CitationCandidate[] = [ { path: 'memory/x.md', content: 'line1\nline2\nline3' }, ]; const out = decorateCitations(hits, true); expect(out[0].citation).toBe('memory/x.md#L1-L3'); }); it('preserves caller-provided line range', () => { const hits: CitationCandidate[] = [ { path: 'memory/x.md', content: 'ignored', startLine: 5, endLine: 12 }, ]; const out = decorateCitations(hits, true); expect(out[0].citation).toBe('memory/x.md#L5-L12'); }); });