File size: 2,370 Bytes
1749a26 6ac1f78 1749a26 6ac1f78 1749a26 6ac1f78 1749a26 6ac1f78 1749a26 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 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([]);
});
});
|