const { test } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs/promises'); const path = require('node:path'); let modulePromise; async function loadCitationModule() { if (!modulePromise) { modulePromise = fs.readFile(path.join(__dirname, '..', 'public', 'js', 'assistant', 'citations.js'), 'utf8') .then((source) => import('data:text/javascript;charset=utf-8,' + encodeURIComponent(source))); } return modulePromise; } const sources = [ { title: 'Nelson Textbook of Pediatrics' }, { title: 'Pediatric Asthma Guideline' }, { resource: 'Emergency Medicine Review' } ]; test('renders citation clusters as links to matching source cards', async () => { const { renderAssistantMarkdown } = await loadCitationModule(); const html = renderAssistantMarkdown('Give magnesium for severe exacerbation [1, 2].', sources); assert.match(html, /href="#assistant-source-1"/); assert.match(html, /href="#assistant-source-2"/); assert.match(html, /title="Nelson Textbook of Pediatrics"/); assert.match(html, /\[]*>1<\/a>, ]*>2<\/a>\]/); }); test('leaves unknown citation clusters untouched rather than guessing', async () => { const { renderAssistantMarkdown } = await loadCitationModule(); const html = renderAssistantMarkdown('Dose statement [4].', sources); assert.match(html, /\[4\]/); assert.doesNotMatch(html, /assistant-source-4/); }); test('does not merge separate citations across separate claims', async () => { const { renderAssistantMarkdown } = await loadCitationModule(); const html = renderAssistantMarkdown('Use oxygen [1]. Give bronchodilator [2].', sources); assert.match(html, /oxygen \[]*>1<\/a>\]/); assert.match(html, /bronchodilator \[]*>2<\/a>\]/); assert.doesNotMatch(html, />1<\/a>, ]*>2<\/a>/); }); test('sorts adjacent citation tokens into one safe Vancouver cluster', async () => { const { renderAssistantMarkdown } = await loadCitationModule(); const html = renderAssistantMarkdown('Deteriorating course [1][4][2][3].', [ { title: 'A' }, { title: 'B' }, { title: 'C' }, { title: 'D' } ]); assert.match(html, />1<\/a>, ]*>2<\/a>, ]*>3<\/a>, ]*>4<\/a>/); assert.doesNotMatch(html, /\] { const { renderAssistantMarkdown } = await loadCitationModule(); const html = renderAssistantMarkdown('Deteriorating course [1][4][2][3', [ { title: 'A' }, { title: 'B' }, { title: 'C' }, { title: 'D' } ]); assert.match(html, />1<\/a>, ]*>2<\/a>, ]*>3<\/a>, ]*>4<\/a>/); }); test('does not normalize adjacent citations if any source number is unknown', async () => { const { renderAssistantMarkdown } = await loadCitationModule(); const html = renderAssistantMarkdown('Unsupported claim [1][9].', sources); assert.match(html, /\[9\]/); assert.doesNotMatch(html, /assistant-source-9/); }); test('escapes source titles inside citation link titles', async () => { const { renderAssistantMarkdown } = await loadCitationModule(); const html = renderAssistantMarkdown('Unsafe title [1].', [{ title: 'Bad "Title"