test(e2e): mobile 视口测试 (375x812) + 扩展登录态路由
完整测试覆盖 (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!) 无判空
This commit is contained in:
21
tools/e2e/diag_me_mobile.js
Normal file
21
tools/e2e/diag_me_mobile.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
const { chromium } = require('playwright');
|
||||||
|
(async () => {
|
||||||
|
const browser = await chromium.launch({ headless: true });
|
||||||
|
const ctx = await browser.newContext({ viewport: { width: 375, height: 812 } });
|
||||||
|
await ctx.addInitScript(([u,p]) => { localStorage['_test_token'] = u+'|'+p; }, ['6477108200','8818']);
|
||||||
|
const page = await ctx.newPage();
|
||||||
|
const logs = [];
|
||||||
|
page.on('console', m => logs.push(m.text()));
|
||||||
|
await page.goto('http://127.0.0.1:8099/', { waitUntil: 'load' });
|
||||||
|
await page.waitForSelector('canvas', { timeout: 90000 });
|
||||||
|
await page.reload({ waitUntil: 'load' });
|
||||||
|
await page.waitForTimeout(8000);
|
||||||
|
await page.goto('http://127.0.0.1:8099/me', { waitUntil: 'load' });
|
||||||
|
await page.waitForTimeout(6000);
|
||||||
|
const stacks = logs.filter(l => l.startsWith('CK_STACK:'));
|
||||||
|
for (const s of stacks) {
|
||||||
|
const proj = s.match(/flutter_wisetronic\/[^\s]+:\d+/g);
|
||||||
|
if (proj) console.log('RenderFlex 项目位置:', [...new Set(proj)].slice(0,3));
|
||||||
|
}
|
||||||
|
await browser.close();
|
||||||
|
})();
|
||||||
@@ -16,6 +16,14 @@ const AUTH_ROUTES = [
|
|||||||
'/new-ticket/310',
|
'/new-ticket/310',
|
||||||
'/change-password',
|
'/change-password',
|
||||||
'/checkout/310',
|
'/checkout/310',
|
||||||
|
// 带动态 id(无效 id 也应优雅处理不崩)
|
||||||
|
'/orderdetail/1',
|
||||||
|
'/paynow/1',
|
||||||
|
'/view-ticket/1',
|
||||||
|
'/new-comment/1',
|
||||||
|
'/ocr-scan',
|
||||||
|
'/renew-license',
|
||||||
|
'/renew-minioffice/1',
|
||||||
];
|
];
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|||||||
71
tools/e2e/run_mobile.js
Normal file
71
tools/e2e/run_mobile.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// Mobile 视口测试(width 375,触发 ScreenTypeLayout mobile 分支)
|
||||||
|
const { chromium } = require('playwright');
|
||||||
|
const BASE = 'http://127.0.0.1:8099';
|
||||||
|
|
||||||
|
const ROUTES = [
|
||||||
|
'/',
|
||||||
|
'/shop',
|
||||||
|
'/shop/310',
|
||||||
|
'/me',
|
||||||
|
'/orders',
|
||||||
|
'/checkout/310',
|
||||||
|
'/blog/310',
|
||||||
|
'/view-blog/52',
|
||||||
|
'/download',
|
||||||
|
'/about-us',
|
||||||
|
'/contact-us',
|
||||||
|
'/user-profile',
|
||||||
|
'/my-addresses/310',
|
||||||
|
'/new-user',
|
||||||
|
];
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const browser = await chromium.launch({ headless: true });
|
||||||
|
const ctx = await browser.newContext({ viewport: { width: 375, height: 812 } }); // iPhone 尺寸
|
||||||
|
await ctx.addInitScript(([u, p]) => { localStorage['_test_token'] = u + '|' + p; }, ['6477108200', '8818']);
|
||||||
|
|
||||||
|
const page = await ctx.newPage();
|
||||||
|
// 先 autologin
|
||||||
|
page.on('console', () => {});
|
||||||
|
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('Mobile 视口 (375x812) 测试:\n');
|
||||||
|
|
||||||
|
const results = [];
|
||||||
|
for (const route of 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, 100));
|
||||||
|
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, 100)));
|
||||||
|
try {
|
||||||
|
await page.goto(BASE + route, { waitUntil: 'load', timeout: 30000 });
|
||||||
|
await page.waitForTimeout(5000);
|
||||||
|
} catch (e) { errors.push('GOTO: ' + e.message.slice(0, 70)); }
|
||||||
|
|
||||||
|
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, 100)}`);
|
||||||
|
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} 路由 (mobile),${failed.length} 个有错误`);
|
||||||
|
await browser.close();
|
||||||
|
})();
|
||||||
Reference in New Issue
Block a user