import automator from 'miniprogram-automator'; import fs from 'fs'; import path from 'path'; const WS = 'ws://127.0.0.1:9420'; const TIMEOUT = 15000; const SCREENSHOTS_DIR = 'g:/hms/apps/miniprogram/screenshots'; function withTimeout(promise, ms, label) { return Promise.race([ promise, new Promise((_, reject) => setTimeout(() => reject(new Error(`${label} timeout`)), ms)) ]); } function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } async function main() { console.log('=== HMS 小程序完整验证 ===\n'); if (!fs.existsSync(SCREENSHOTS_DIR)) fs.mkdirSync(SCREENSHOTS_DIR, { recursive: true }); // Connect console.log('[1] 连接开发者工具...'); const mp = await withTimeout(automator.connect({ wsEndpoint: WS }), TIMEOUT, 'connect'); console.log(' 已连接\n'); // System info console.log('[2] 系统信息...'); try { const info = await withTimeout(mp.systemInfo(), TIMEOUT, 'systemInfo'); console.log(` 设备: ${info.model}`); console.log(` 系统: ${info.system}`); console.log(` SDK: ${info.SDKVersion}`); console.log(` 屏幕: ${info.screenWidth}x${info.screenHeight}\n`); } catch (e) { console.log(` [WARN] ${e.message}\n`); } // Current page console.log('[3] 当前页面...'); try { const page = await withTimeout(mp.currentPage(), TIMEOUT, 'currentPage'); console.log(` 路径: ${page.path}\n`); } catch (e) { console.log(` [WARN] ${e.message}\n`); } // Navigate and screenshot each page console.log('[4] 页面导航验证...'); const pages = [ { path: '/pages/index/index', name: '首页' }, { path: '/pages/health/index', name: '健康中心' }, { path: '/pages/health/input/index', name: '健康数据录入' }, { path: '/pages/health/trend/index', name: '健康趋势' }, { path: '/pages/appointment/index', name: '预约列表' }, { path: '/pages/appointment/create/index', name: '创建预约' }, { path: '/pages/article/index', name: '资讯文章' }, { path: '/pages/profile/index', name: '个人中心' }, { path: '/pages/profile/family/index', name: '就诊人管理' }, { path: '/pages/profile/reports/index', name: '我的报告' }, { path: '/pages/login/index', name: '登录页' }, ]; let passCount = 0; let failCount = 0; let ssCount = 0; for (const p of pages) { try { await withTimeout(mp.reLaunch(p.path), TIMEOUT, `reLaunch ${p.path}`); await sleep(2000); const page = await withTimeout(mp.currentPage(), TIMEOUT, 'currentPage'); // Screenshot let ssOk = false; try { const ss = await withTimeout(mp.screenshot({ path: `${SCREENSHOTS_DIR}/${p.path.replace(/\//g, '_').replace(/^_/, '')}.png` }), 20000, 'screenshot'); ssOk = true; ssCount++; } catch (e) { // Retry without path option try { const ss = await withTimeout(mp.screenshot(), 20000, 'screenshot2'); const safeName = p.path.replace(/\//g, '_').replace(/^_/, ''); const ssPath = `${SCREENSHOTS_DIR}/${safeName}.png`; if (Buffer.isBuffer(ss)) { fs.writeFileSync(ssPath, ss); } else { fs.writeFileSync(ssPath, Buffer.from(ss, 'base64')); } ssOk = true; ssCount++; } catch (e2) { // ignore } } console.log(` [OK] ${p.name} (${p.path})${ssOk ? ' 📸' : ''}`); passCount++; } catch (e) { console.log(` [FAIL] ${p.name}: ${e.message}`); failCount++; } } // Test page data on key pages console.log('\n[5] 页面数据验证...'); const dataTests = [ { path: '/pages/index/index', name: '首页', checkData: ['services'] }, { path: '/pages/profile/index', name: '个人中心', checkData: ['MENU_ITEMS'] }, { path: '/pages/login/index', name: '登录页', checkData: [] }, ]; for (const test of dataTests) { try { await withTimeout(mp.reLaunch(test.path), TIMEOUT, `reLaunch ${test.path}`); await sleep(2000); const page = await withTimeout(mp.currentPage(), TIMEOUT, 'currentPage'); const data = await withTimeout(page.data(), TIMEOUT, 'pageData'); console.log(` [OK] ${test.name} data keys: ${Object.keys(data).join(', ')}`); } catch (e) { console.log(` [WARN] ${test.name}: ${e.message}`); } } // Summary console.log('\n=== 验证结果 ==='); console.log(` 页面加载: ${passCount}/${pages.length} 通过, ${failCount} 失败`); console.log(` 截图: ${ssCount} 张`); console.log(` 截图目录: ${SCREENSHOTS_DIR}`); await mp.close(); console.log('\n验证完成!'); } main().catch(err => { console.error('Fatal:', err.message); process.exit(1); });