/** * Smoke-test the same API routes the Vite client uses. * Usage: node scripts/test-api.mjs * $env:API_BASE="http://127.0.0.1:5173"; node scripts/test-api.mjs # via Vite proxy */ const base = (process.env.API_BASE ?? 'http://127.0.0.1:8080').replace(/\/$/, '') const tests = [ ['GET', '/up', null], ['GET', '/api/v1/health', null], ['GET', '/api/v1/auth/register/captcha', null], ['GET', '/api/v1/policies/school', null], ['GET', '/api/docs/public', null], [ 'POST', '/api/v1/auth/login', JSON.stringify({ email: 'nosuch@example.org', password: 'wrong-password' }), ], ] async function main() { console.log(`API_BASE=${base}\n`) for (const [method, path, body] of tests) { const url = `${base}${path}` try { const init = { method, headers: { Accept: 'application/json', ...(body ? { 'Content-Type': 'application/json' } : {}), }, ...(body ? { body } : {}), } const res = await fetch(url, init) const text = await res.text() let snippet = text.slice(0, 280).replace(/\s+/g, ' ') let fatal = false let dbError = false try { const j = JSON.parse(text) const msg = typeof j.message === 'string' ? j.message : typeof j.exception === 'string' ? j.exception : '' if (j.exception?.includes?.('FatalError') || /FatalError/i.test(j.message ?? '')) { fatal = true snippet = `PHP FatalError: ${(j.message ?? '').slice(0, 100)}` } else if (j.message && typeof j.message === 'string') { snippet = j.message.slice(0, 120) } if (/SQLSTATE/i.test(msg) || /SQLSTATE/i.test(text)) { dbError = true snippet = `${snippet.slice(0, 80)}… (DB unavailable?)` } if (j.ok === true && path.includes('captcha')) { snippet = `ok=true captcha=<${String(j.captcha ?? '').length} chars>` } if (j.status === true && path.includes('docs/public')) { snippet = `title=${j.title ?? 'n/a'} openapi=${!!j.openapi_url}` } if (j.data?.policy && path.includes('policies/school')) { snippet = `policy content len=${String(j.data.policy.content ?? '').length}` } } catch { /* not JSON */ } const ok = !fatal && !dbError && (res.ok || (path.endsWith('/login') && (res.status === 401 || res.status === 400)) || res.status === 422) console.log( `${method} ${path} → ${res.status} ${ok ? '✓' : '✗'} ${snippet}`, ) } catch (e) { console.log(`${method} ${path} → ERROR ${e instanceof Error ? e.message : e}`) } } } main()