完整测试覆盖 (49 路由, 0 崩溃): - 公开 desktop: 18/18 ✓ - 登录态 desktop: 17/17 ✓ (含 orderdetail/paynow/view-ticket/ocr-scan/renew-*) - mobile 视口: 14/14 ✓ (仅 /me 4px RenderFlex 溢出, 无害布局警告) 修复汇总 (本轮自动化发现+修复): 1. download Scrollbar 缺 ScrollPosition -> primary:true 2. contact-stores initState dispose 后 setState -> mounted 保护 3. buy-service onGenerateRoute pathElements 越界 RangeError -> 长度检查 4. add_remove_button/shopping_cart_* cartInfo 误加 ! (nullfix 脚本) 5. checkout table_token(tableNumber!) 无判空
95 lines
3.2 KiB
JavaScript
95 lines
3.2 KiB
JavaScript
// 登录态路由测试:注入 _test_token,autologin 后遍历需登录路由
|
||
const { chromium } = require('playwright');
|
||
const BASE = 'http://127.0.0.1:8099';
|
||
const USER = '6477108200';
|
||
const PASS = '8818';
|
||
|
||
// 需登录路由(动态参数用合理默认)
|
||
const AUTH_ROUTES = [
|
||
'/me',
|
||
'/orders',
|
||
'/user-profile',
|
||
'/my-cards',
|
||
'/my-addresses/310',
|
||
'/coupons/310',
|
||
'/my-support/310',
|
||
'/new-ticket/310',
|
||
'/change-password',
|
||
'/checkout/310',
|
||
// 带动态 id(无效 id 也应优雅处理不崩)
|
||
'/orderdetail/1',
|
||
'/paynow/1',
|
||
'/view-ticket/1',
|
||
'/new-comment/1',
|
||
'/ocr-scan',
|
||
'/renew-license',
|
||
'/renew-minioffice/1',
|
||
];
|
||
|
||
(async () => {
|
||
const browser = await chromium.launch({ headless: true });
|
||
const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
|
||
await ctx.addInitScript(([u, p]) => { localStorage['_test_token'] = u + '|' + p; }, [USER, PASS]);
|
||
|
||
// 先访问首页触发 autologin
|
||
const page = await ctx.newPage();
|
||
let autologinOk = false;
|
||
page.on('console', m => { if (m.text().includes('CK_AUTOLOGIN_OK')) autologinOk = true; });
|
||
console.log('触发 autologin...');
|
||
await page.goto(BASE + '/', { waitUntil: 'load', timeout: 60000 });
|
||
await page.waitForSelector('canvas', { timeout: 90000 });
|
||
await page.reload({ waitUntil: 'load' });
|
||
await page.waitForTimeout(8000);
|
||
console.log('autologin:', autologinOk ? '✓ 成功' : '✗ 未确认\n');
|
||
|
||
const results = [];
|
||
for (const route of AUTH_ROUTES) {
|
||
const errors = [];
|
||
const stacks = [];
|
||
const pageErrs = [];
|
||
page.removeAllListeners('console');
|
||
page.removeAllListeners('pageerror');
|
||
page.on('console', m => {
|
||
const t = m.text();
|
||
if (t.startsWith('CK_ERROR:')) errors.push(t.slice(0, 120));
|
||
if (t.startsWith('CK_STACK:')) {
|
||
const proj = t.match(/flutter_wisetronic\/[^\s]+:\d+/g);
|
||
if (proj) stacks.push([...new Set(proj)].slice(0, 2));
|
||
}
|
||
});
|
||
page.on('pageerror', e => pageErrs.push(e.message.slice(0, 120)));
|
||
|
||
try {
|
||
await page.goto(BASE + route, { waitUntil: 'load', timeout: 30000 });
|
||
await page.waitForTimeout(6000);
|
||
} catch (e) {
|
||
errors.push('GOTO: ' + e.message.slice(0, 80));
|
||
}
|
||
|
||
const allErr = [...errors, ...pageErrs];
|
||
const status = allErr.length === 0 ? '✓ OK' : `✗ ${allErr.length}`;
|
||
console.log(`${status.padEnd(10)} ${route}`);
|
||
if (allErr.length) {
|
||
console.log(` ${allErr[0].slice(0, 120)}`);
|
||
if (stacks.length) console.log(` 位置: ${JSON.stringify(stacks[0])}`);
|
||
}
|
||
results.push({ route, errors: allErr, stacks });
|
||
}
|
||
|
||
const failed = results.filter(r => r.errors.length > 0);
|
||
console.log(`\n========== 汇总 ==========`);
|
||
console.log(`${results.length} 个登录态路由,${failed.length} 个有错误`);
|
||
if (failed.length) {
|
||
const locMap = {};
|
||
for (const f of failed) {
|
||
const loc = f.stacks[0] ? f.stacks[0][0] : f.errors[0].slice(0, 40);
|
||
locMap[loc] = locMap[loc] || [];
|
||
locMap[loc].push(f.route);
|
||
}
|
||
for (const [loc, routes] of Object.entries(locMap)) {
|
||
console.log(` ${loc}\n → ${routes.join(', ')}`);
|
||
}
|
||
}
|
||
await browser.close();
|
||
})();
|