import { describe, it, expect } from 'vitest'; import { splitCitations } from './citations'; const REFS = [ { id: 'r1', short: 'Carnall 2018', year: 2018, corpusMatch: true }, { id: 'r2', short: 'Behroozi 2019', year: 2019, corpusMatch: false }, { id: 'r3', short: 'Stark 2016', year: 2016, corpusMatch: true }, ]; const IDX = { 'carnall:2018': ['r1'], 'behroozi:2019': ['r2'], 'stark:2016': ['r3'], }; describe('splitCitations', () => { it('narrative cite: Carnall et al. (2018)', () => { const segs = splitCitations('From Carnall et al. (2018) we know this.', IDX, REFS); const cite = segs.find((s) => s.t === 'cite'); expect(cite).toBeTruthy(); expect(cite.refs[0].id).toBe('r1'); expect(cite.refs[0].corpusMatch).toBe(true); }); it('parenthetical multi-cite: each unit is its own cite segment', () => { const segs = splitCitations('Results (Behroozi et al. 2019; Stark 2016) agree.', IDX, REFS); const cites = segs.filter((s) => s.t === 'cite'); // Two separate cite segments, not one combined expect(cites).toHaveLength(2); expect(cites[0].refs[0].id).toBe('r2'); expect(cites[1].refs[0].id).toBe('r3'); // Surrounding punctuation preserved as text const texts = segs.filter((s) => s.t === 'text').map((s) => s.s); expect(texts.some((s) => s.includes('('))).toBe(true); expect(texts.some((s) => s.includes(')'))).toBe(true); expect(texts.some((s) => s.includes(';'))).toBe(true); }); it('unmatched cite gets a cite span with empty refs (for visual styling)', () => { const segs = splitCitations('See Hubble (1929) for early evidence.', IDX, REFS); const cite = segs.find((s) => s.t === 'cite'); expect(cite).toBeTruthy(); expect(cite.s).toContain('Hubble'); expect(cite.refs).toHaveLength(0); }); it('no citations → single text segment', () => { const segs = splitCitations('No references here at all.', IDX, REFS); expect(segs).toHaveLength(1); expect(segs[0].t).toBe('text'); }); it('surname & Other (year) narrative form', () => { const segs = splitCitations('Carnall & McLure (2018) showed this.', IDX, REFS); const cite = segs.find((s) => s.t === 'cite'); expect(cite?.refs[0].id).toBe('r1'); }); it('empty string returns empty array', () => { expect(splitCitations('', IDX, REFS)).toEqual([]); }); });