/** * Browser smoke for 策研 Strategy Lab frontend. * Usage: PLAYWRIGHT_BROWSERS_PATH=... node scripts/browser-smoke.mjs [baseURL] * Requires the Vite dev server (frontend/ npm run dev, /api proxying to backend). */ import { chromium } from 'playwright'; const base = process.argv[2] ?? 'http://127.0.0.1:8788'; const browser = await chromium.launch(); const page = await browser.newPage(); const pageErrors = []; page.on('pageerror', (e) => pageErrors.push(String(e))); page.on('response', (r) => { if (r.status() >= 500) pageErrors.push(`${r.status} ${r.url()}`); }); await page.goto(`${base}/#/login`, { waitUntil: 'networkidle' }); const t1 = await page.evaluate(() => document.body.innerText); if (!t1.includes('邮箱') || !t1.includes('登录')) throw new Error(`login page missing content: ${t1.slice(0, 100)}`); await page.goto(`${base}/#/register`, { waitUntil: 'networkidle' }); if (!(await page.$('form'))) throw new Error('register form missing'); await page.goto(`${base}/#/reset`, { waitUntil: 'networkidle' }); if ((await page.$$eval('input', (els) => els.length)) < 3) throw new Error('reset inputs missing'); // wrong password flow must NOT navigate to app, must render error banner await page.goto(`${base}/#/login`, { waitUntil: 'networkidle' }); await page.fill('#le', 'smoke@example.invalid'); await page.fill('#lp', 'wrong-password'); await page.click('button[type="submit"]'); await page.waitForTimeout(1200); const t2 = await page.evaluate(() => document.body.innerText); if (!t2.includes('不正确') && !t2.includes('HTTP') && !t2.includes('出错')) { throw new Error(`expected visible login error, got: ${t2.slice(0, 160)}`); } for (const h of ['projects', 'datasets', 'runs', 'usage', 'account', 'admin']) { await page.goto(`${base}/#/${h}`, { waitUntil: 'networkidle' }); const has = await page.evaluate(() => document.body.innerText.length > 50); if (!has) throw new Error(`route ${h} rendered empty`); } if (pageErrors.length > 0) { throw new Error(`page errors: ${pageErrors.slice(0, 5).join('; ')}`); } console.log('BROWSER SMOKE OK', { pageErrors: pageErrors.length }); await browser.close();