import assert from 'node:assert/strict'; import { mkdir, readFile, writeFile } from 'node:fs/promises'; import { chromium } from 'playwright'; const accounts = JSON.parse(await readFile(new URL('../../.work/frontend-accounts.json', import.meta.url), 'utf8')); const base = process.env.FRONTEND_URL || 'http://127.0.0.1:18762'; const browser = await chromium.launch({ headless: true, executablePath: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE }); const page = await browser.newPage(); page.setDefaultTimeout(10000); const started = Date.now(), errors = []; let opening, requests = 0, token; page.on('pageerror', error => errors.push(error.message)); page.on('request', request => { if (/\/(openapi|admin)\//.test(request.url())) requests++; if (request.url().endsWith('/events')) opening = Date.now(); }); const timeout = setTimeout(() => { void browser.close(); }, 30000); try { await page.goto(`${base}/#/customer/login`); await page.getByLabel('账户', { exact: true }).fill('customer01'); await page.getByLabel('密码', { exact: true }).fill(accounts.password); await page.getByRole('checkbox').check(); const login = page.waitForResponse(response => response.request().method() === 'POST' && response.url().endsWith('/auth/sessions')); const stream = page.waitForResponse(response => response.url().endsWith('/events')); await page.getByRole('button', { name: '登录并继续', exact: true }).click(); token = (await (await login).json()).access_token; const connected = await stream; const connectMs = Date.now() - opening; assert.equal(connected.status(), 200); assert.ok(connectMs < 5000, '空闲会话应在5秒内收到响应,无需等待15秒周期心跳'); await page.waitForFunction(() => [...document.querySelectorAll('.mobile button')].some(button => button.textContent === '发送' && !button.disabled)); assert.deepEqual(errors, []); requests++; const logout = await page.request.delete(`${base}/openapi/v1/auth/sessions/current`, { headers: { Authorization: `Bearer ${token}` } }); assert.equal(logout.status(), 204); token = null; await page.waitForURL('**/#/customer/login'); await mkdir(new URL('../../.work/frontend-verification/', import.meta.url), { recursive: true }); const report = { date: new Date().toISOString(), connectMs, seconds: (Date.now() - started) / 1000, requestCount: requests, browserErrors: errors, generatedModelCalls: 0, durationLimitSeconds: 30 }; await writeFile(new URL('../../.work/frontend-verification/customer-stream-connect.json', import.meta.url), JSON.stringify(report, null, 2)); console.log(JSON.stringify(report)); } finally { clearTimeout(timeout); if (token) await page.request.delete(`${base}/openapi/v1/auth/sessions/current`, { headers: { Authorization: `Bearer ${token}` } }); await browser.close(); }