import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; const events = globalThis.__apiEvents = []; let source = readFileSync('static/js/api.js', 'utf8') .replace('import { logDebug, logError, logWarn } from "@rustpad/logger";', 'const logDebug = () => {}; const logError = (...args) => globalThis.__apiEvents.push(["error", ...args]); const logWarn = (...args) => globalThis.__apiEvents.push(["warn", ...args]);') .replace('import { formatNumber, restoreGuestLanguage, translateApiMessage } from "@rustpad/i18n";', 'const formatNumber = value => String(value); const restoreGuestLanguage = () => {}; const translateApiMessage = message => message;') .replace('import { restoreGuestTheme } from "@rustpad/theme";', 'const restoreGuestTheme = () => {};'); const { api } = await import('data:text/javascript;charset=utf-8,' + encodeURIComponent(source)); globalThis.window = {}; globalThis.fetch = async () => new Response(JSON.stringify({ error: 'Access denied.' }), { status: 403, headers: { 'content-type': 'application/json' }, }); await assert.rejects(api('/api/auth/resources/mentions?kind=pad&slug=test'), error => error.status === 403); assert.equal(events.filter(([level, name]) => level === 'warn' && name === 'api.failed').length, 1); assert.equal(events.filter(([level, name]) => level === 'error' && name === 'api.network_error').length, 0); events.length = 0; globalThis.fetch = async () => new Response(JSON.stringify({ users: [] }), { status: 200, headers: { 'content-type': 'application/json' }, }); assert.deepEqual(await api('/api/auth/resources/mentions?kind=pad&slug=test'), { users: [] }); assert.equal(events.length, 0); events.length = 0; globalThis.fetch = async () => { throw new TypeError('Network down'); }; await assert.rejects(api('/api/auth/resources/mentions?kind=pad&slug=test'), TypeError); assert.equal(events.filter(([level, name]) => level === 'error' && name === 'api.network_error').length, 1); console.log('PASS: HTTP 403 logged once, empty mentions succeeds, transport failures logged as network errors');