import { loadI18n } from '../test-support/i18n.js'; import assert from 'node:assert/strict'; import fs from 'node:fs/promises'; import path from 'node:path'; import test from 'node:test'; import vm from 'node:vm'; import { localizeHtml } from '../scripts/localize-html.js'; const root = path.resolve(import.meta.dirname, '..'); test('checked-in HTML has synchronized German defaults and accessible headings, labels and links before scripts load', async () => { const i18n = await loadI18n({}); const html = await fs.readFile(path.join(root, 'public/index.html'), 'utf8'); assert.equal(localizeHtml(html, key => i18n.t(key)), html, 'Run node scripts/localize-html.js after editing German texts'); for (const match of html.matchAll(/]*>([\s\S]*?)<\/h[1-6]>/g)) assert.ok(match[1].replaceAll(/<[^>]*>/g, '').trim(), match[0]); for (const match of html.matchAll(/\baria-label="([^"]*)"/g)) assert.ok(match[1].trim(), 'Empty accessible label'); for (const match of html.matchAll(/]*>([\s\S]*?)<\/a>/g)) assert.ok(match[1].replaceAll(/<[^>]*>/g, '').trim(), match[0]); for (const match of html.matchAll(/]*)>/g)) { const control = /\bfor="([^"]+)"/.exec(match[1])?.[1]; assert.ok(control, `Missing label association: ${match[0]}`); assert.ok(html.includes(`id="${control}"`), `Missing control: ${control}`); } }); test('HTML generation escapes text and attributes, preserves i18n markers and updates existing defaults', () => { const source = '

Old title

'; const messages = { heading: '', label: 'A "label" & $&' }; const translate = key => messages[key]; const result = localizeHtml(source, translate); assert.equal(result, '

<New & title>

'); assert.equal(localizeHtml(result, translate), result); }); test('translations support placeholders, plurals and German fallback without treating text as HTML', async () => { const context = {}; const i18n = await loadI18n(context); assert.equal(i18n.t('app.choose-route'), 'Strecke wählen'); assert.equal(i18n.t('media.image.count', { count: 1 }), '1 Bild'); assert.equal(i18n.t('media.image.count', { count: 2 }), '2 Bilder'); assert.equal(i18n.t('app.next-station-summary', { value1: '