import assert from 'node:assert/strict'; import test from 'node:test'; import { normalizeMarkdownImageToken, renderSessionMarkdownImage, } from '../app/src/renderer/src/markdown-image-renderer.js'; // marked <= 14 calls renderer.image(href, title, text); marked >= 15 passes the // token. Getting this wrong degrades silently: every session image turns into // fallback text because the href is no longer a string. test('accepts the positional renderer signature', () => { assert.deepEqual( normalizeMarkdownImageToken('http://example.test/a.png', 'A title', 'Alt text'), { href: 'http://example.test/a.png', title: 'A title', text: 'Alt text' }, ); }); test('accepts the token renderer signature', () => { assert.deepEqual( normalizeMarkdownImageToken({ type: 'image', href: 'http://example.test/a.png', title: 'A title', text: 'Alt text', }), { href: 'http://example.test/a.png', title: 'A title', text: 'Alt text' }, ); }); test('fills in the fields marked leaves null', () => { assert.deepEqual( normalizeMarkdownImageToken({ href: 'http://example.test/a.png', title: null, text: '' }), { href: 'http://example.test/a.png', title: '', text: '' }, ); assert.deepEqual( normalizeMarkdownImageToken('http://example.test/a.png', null, null), { href: 'http://example.test/a.png', title: '', text: '' }, ); }); test('renders an allowed source as the session image element', () => { assert.equal( renderSessionMarkdownImage('http://example.test/a.png', '', 'Alt text'), '', ); assert.equal( renderSessionMarkdownImage('data:image/png;base64,AAAA', '', ''), '', ); }); test('carries the title through when marked supplies one', () => { assert.equal( renderSessionMarkdownImage('file:///shots/a.png', 'A title', 'Alt'), '', ); }); test('drops a source the app will not load, keeping one unavailable state', () => { for (const href of ['javascript:alert(1)', 'data:text/html,x', 'ftp://example.test/a.png', '']) { assert.equal( renderSessionMarkdownImage(href, '', 'Alt text'), '', `expected ${href || '(empty)'} to render without a src`, ); } }); test('decodes what marked escaped exactly once, then re-escapes it', () => { assert.equal( renderSessionMarkdownImage('http://example.test/a.png?x=1&y=2', '', '"quoted" & 'single''), '', ); // A single decoding pass, so text that was literally `<` in the source // does not decay into a real angle bracket. assert.equal( renderSessionMarkdownImage('http://example.test/a.png', '', '&lt;script&gt;'), '', ); }); test('never lets alt text break out of the attribute', () => { const html = renderSessionMarkdownImage('http://example.test/a.png', '', '">'); assert.equal(html.includes('onerror=alert(1)>'), false); assert.equal( html, '', ); });