import { test, afterEach } from 'node:test' import assert from 'node:assert/strict' import { api } from '../src/api/client.js' import { onDemoLocked, reportIfDemoLocked, formatResetTime, isDemoLocked } from '../src/lib/demoNotice.js' // The public demo's refusal reaches the one toast from req() itself, so every // screen and every installed module gets it without handling the code — and // the caller still gets its ApiError, so a form's own error line is unchanged. const realFetch = global.fetch afterEach(() => { global.fetch = realFetch }) function replyOnce(status, body) { global.fetch = async () => ({ ok: status >= 200 && status < 300, status, statusText: 'Forbidden', text: async () => JSON.stringify(body), }) } test('a DEMO_LOCKED answer is reported once and still thrown to the caller', async () => { const heard = [] const off = onDemoLocked((m) => heard.push(m)) replyOnce(403, { code: 'DEMO_LOCKED', message: 'This is turned off on the demo site.' }) await assert.rejects(() => api.publicSettings(), (err) => err.status === 403 && err.message === 'This is turned off on the demo site.') off() assert.deepEqual(heard, ['This is turned off on the demo site.']) }) test('any other refusal is not a demo refusal', async () => { const heard = [] const off = onDemoLocked((m) => heard.push(m)) replyOnce(403, { message: 'Admin role required' }) await assert.rejects(() => api.publicSettings()) off() assert.deepEqual(heard, []) }) test('reportIfDemoLocked recognises the code alone and survives a broken listener', () => { const off1 = onDemoLocked(() => { throw new Error('boom') }) const heard = [] const off2 = onDemoLocked((m) => heard.push(m)) assert.equal(reportIfDemoLocked({ code: 'DEMO_LOCKED' }), true) assert.equal(reportIfDemoLocked({ code: 'OTHER' }), false) assert.equal(reportIfDemoLocked('text'), false) assert.equal(reportIfDemoLocked(null), false) off1() off2() assert.deepEqual(heard, ['This is turned off on the demo site.']) }) test('isDemoLocked tells the demo refusal from a role 403', async () => { replyOnce(403, { code: 'DEMO_LOCKED', message: 'This is turned off on the demo site.' }) const locked = await api.publicSettings().catch((e) => e) replyOnce(403, { message: 'Admin role required' }) const role = await api.publicSettings().catch((e) => e) assert.equal(isDemoLocked(locked), true) assert.equal(isDemoLocked(role), false) assert.equal(isDemoLocked(null), false) }) test('the reset time is said in UTC, as the wipe runs', () => { assert.equal(formatResetTime('2026-10-24T14:00:00.000Z'), '14:00 UTC') assert.equal(formatResetTime('2026-10-24T09:05:00+02:00'), '07:05 UTC') assert.equal(formatResetTime('nope'), null) })