/** * Guarded consultation-only Form A browser regression. * Run after an explicitly gated isolated-test build. Every Jotform request is * fulfilled or aborted locally; no Jotform request is transmitted. */ import { randomBytes } from 'node:crypto'; import { encryptPortalStream, portalAlgorithm } from '../src/utils/portal-crypto.mjs'; import assert from 'node:assert/strict'; import fs from 'node:fs/promises'; import http from 'node:http'; import net from 'node:net'; import path from 'node:path'; import { spawn } from 'node:child_process'; import { fileURLToPath, pathToFileURL } from 'node:url'; import { setTimeout as delay } from 'node:timers/promises'; const root = fileURLToPath(new URL('../', import.meta.url)); const moduleName = process.env.PLAYWRIGHT_MODULE ? pathToFileURL(path.resolve(process.env.PLAYWRIGHT_MODULE)).href : 'playwright'; const output = await fs.mkdtemp('/tmp/aia-service-portal-'); const routes = [ { route: '/client-consultation', locale: 'en', drawer: false, screenshot: 'client-consultation' }, { route: '/es/client-consultation', locale: 'es', drawer: false, screenshot: 'es-client-consultation' }, { route: '/schedule-consultation', locale: 'en', drawer: false, screenshot: 'schedule-consultation' }, { route: '/aba-therapy', locale: 'en', drawer: true, screenshot: 'aba-therapy' }, { route: '/autism-evaluations', locale: 'en', drawer: true, screenshot: 'autism-evaluations' }, { route: '/learner-social-club', locale: 'en', drawer: true, screenshot: 'learner-social-club' }, { route: '/es/aba-therapy', locale: 'es', drawer: true, screenshot: 'es-aba-therapy' }, { route: '/es/autism-evaluations', locale: 'es', drawer: true, screenshot: 'es-autism-evaluations' }, { route: '/es/learner-social-club', locale: 'es', drawer: true, screenshot: 'es-learner-social-club' }, ]; const widths = [320, 390, 768, 1440]; const evidence = { routes, widths, checks: 0, blocked: [], jotformAttempts: [], screenshots: [], fallbackChecks: [], status: 'failed' }; const reserve = net.createServer(); await new Promise((resolve, reject) => { reserve.once('error', reject); reserve.listen(0, '127.0.0.1', resolve); }); const port = reserve.address().port; await new Promise((resolve) => reserve.close(resolve)); const origin = 'http://127.0.0.1:' + port; let browser; let preview; function expectedUrl(locale) { return 'https://form.jotform.com/262946078314059?formContext=consultation&language=' + locale; } try { const { chromium } = await import(moduleName); browser = await chromium.launch(process.env.CHROMIUM_EXECUTABLE ? { headless: true, executablePath: process.env.CHROMIUM_EXECUTABLE } : { headless: true }); preview = spawn(process.execPath, ['node_modules/astro/bin/astro.mjs', 'preview', '--host', '127.0.0.1', '--port', String(port)], { cwd: root, env: { ...process.env, ASTRO_TELEMETRY_DISABLED: '1' }, stdio: 'ignore', }); const reachable = () => new Promise((resolve) => { const request = http.get(origin + '/', (response) => { response.resume(); resolve(response.statusCode === 200); }); request.setTimeout(500, () => request.destroy()); request.on('error', () => resolve(false)); }); for (let i = 0; i < 60 && !(await reachable()); i++) await delay(250); assert.equal(await reachable(), true, 'Loopback preview did not become reachable'); const key = 'aia:service-inquiry:auto-suppressed-until'; const duration = 30 * 86400000; const staffCode = randomBytes(24).toString('hex'); const managementCode = randomBytes(24).toString('hex'); const payload = { alg: portalAlgorithm, streams: [ await encryptPortalStream('fixture-staff', '
Staff fixture only
Synthetic resourceManagement fixture only
', managementCode), ] }; const guard = async (context, inject = false) => { await context.routeWebSocket('**/*', (socket) => { evidence.blocked.push({ method: 'WEBSOCKET' }); socket.close(); }); await context.route('**/*', async (route) => { const req = route.request(), url = new URL(req.url()); if (url.origin === origin && ['GET', 'HEAD'].includes(req.method())) { if (inject && url.pathname === '/employee-portal') { const response = await route.fetch(); const html = (await response.text()).replace(/(