diff --git a/tools/e2e/diag_me_mobile.js b/tools/e2e/diag_me_mobile.js new file mode 100644 index 0000000..9ec0eb7 --- /dev/null +++ b/tools/e2e/diag_me_mobile.js @@ -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(); +})(); diff --git a/tools/e2e/run_auth.js b/tools/e2e/run_auth.js index 7a7aa65..9c728ff 100644 --- a/tools/e2e/run_auth.js +++ b/tools/e2e/run_auth.js @@ -16,6 +16,14 @@ const AUTH_ROUTES = [ '/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 () => { diff --git a/tools/e2e/run_mobile.js b/tools/e2e/run_mobile.js new file mode 100644 index 0000000..83bea18 --- /dev/null +++ b/tools/e2e/run_mobile.js @@ -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(); +})();