import test from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { SECURITY_HEADERS, esc, evidenceHtml, heroCardHtml, injectApp, invoiceHtml, landingHtml, pageFor } from '../worker/src/pages.js'; import { MAINNET } from '../evidence/mainnet.js'; const index = readFileSync(new URL('../web/index.html', import.meta.url), 'utf8'); /** Roughly what a fetcher that ignores JavaScript reads: tags and scripts dropped. */ const visible = (html) => html.replace(/<(script|style|template|svg)\b[\s\S]*?<\/\1>/gi, ' ').replace(/<[^>]+>/g, ' ').replace(/&[a-z#0-9]+;/gi, ' ').replace(/\s+/g, ' ').trim(); const paidInvoice = { id: '1-3', number: 3, merchant: 'a'.repeat(64), amount: '1000000', due_now: '0', paid: '1000000', applied: '1000000', excess: '0', set_aside: '200000', refunded: '0', status: 'paid', issued_at_ms: '1793542081622', due_at_ms: '1794787199000', closed_at_ms: '1793542204756', payments: [{ amount: '1000000', at_ms: '1793542204756', block: '222579868', refund_to: 'base:USDC:0xA30bDf2ea82D86a5feF686999B0b6c3d80c788cD' }], }; test('the landing reads without JavaScript: what Duly is, the contract, every transaction', () => { const page = injectApp(index, landingHtml(), { title: 'Duly' }); const text = visible(page); assert.ok(text.length > 2000, `only ${text.length} visible characters`); assert.doesNotMatch(text, /\bloading\b/i); assert.match(text, /dulypay\.near/); assert.ok(text.includes(MAINNET.codeHash)); for (const t of [...MAINNET.near, ...MAINNET.base]) assert.ok(page.includes(t.hash), `missing ${t.key}`); assert.match(page, /href="\/test\/app"/); assert.match(page, /href="\/i\/1-4"/); }); test('live totals appear only when the chain answered, and are escaped', () => { assert.doesNotMatch(landingHtml(), /live-totals/); const html = landingHtml({ live: { at: 1793542204756, invoices: '3', received: '1250000', liabilities: '1100000', held: '1100000' } }); assert.match(html, /1\.25 USDC received/); assert.ok(html.includes('<b>3</b>')); }); test('the test-mode landing says so', () => { assert.match(landingHtml({ test: true }), /Test mode\. No real money\./); }); test('injectApp fills the app root, keeps the scripts and replaces the noscript notice', () => { const page = injectApp(index, '
hello
', { title: 'Ahello<\/p><\/div>/); assert.match(page, /' }] }; const html = invoiceHtml({ id: '1-3', inv: evil, payments: [{ near_tx: 'javascript:alert(1)', origin_tx: '">