import assert from 'node:assert/strict'; import { access, readFile } from 'node:fs/promises'; import { test } from 'node:test'; import { loadTypescript } from './support/load-typescript.mjs'; const moduleURL = new URL('../src/ui/ArrivalCount.ts', import.meta.url); assert.equal(await access(moduleURL).then(() => true, () => false), true, 'arrival count presentation module must exist'); const { renderArrivalCount } = await loadTypescript(moduleURL); const element = () => ({ hidden: false, textContent: '', set innerHTML(_value) { assert.fail('numeric copy must use textContent'); } }); test('unknown initial count hides all count nodes without inventing zero', () => { const elements = [element(), element()]; renderArrivalCount(elements, undefined); assert.ok(elements.every(node => node.hidden)); assert.ok(elements.every(node => node.textContent === '')); }); test('server zero is a real visible zero with the exact Korean copy', () => { const elements = [element(), element()]; renderArrivalCount(elements, 0); for (const node of elements) { assert.equal(node.hidden, false); assert.equal(node.textContent, '지금까지 0번 도착했어요'); } }); test('arrival count groups using Korean locale and updates both placements', () => { const elements = [element(), element()]; renderArrivalCount(elements, 1234); for (const node of elements) { assert.equal(node.hidden, false); assert.equal(node.textContent, '지금까지 1,234번 도착했어요'); } }); test('failed or invalid reads preserve the last valid count text and visibility', () => { const elements = [element(), element()]; renderArrivalCount(elements, 1234); for (const count of [undefined, -1, 0.5, '0', Number.MAX_SAFE_INTEGER + 1, NaN]) { renderArrivalCount(elements, count); for (const node of elements) { assert.equal(node.hidden, false); assert.equal(node.textContent, '지금까지 1,234번 도착했어요'); } } }); test('malformed initial count is hidden rather than displayed', () => { for (const count of [-1, 0.5, '0', Number.MAX_SAFE_INTEGER + 1, NaN]) { const node = element(); renderArrivalCount([node], count); assert.equal(node.hidden, true); assert.equal(node.textContent, ''); } }); test('count presentation has no animation, polling or render-demand dependency', async () => { const source = await readFile(moduleURL, 'utf8'); assert.doesNotMatch(source, /innerHTML|requestAnimationFrame|setInterval|setTimeout|RenderDemand|invalidate/); });