import { createDriver } from '../drivers/factory'; // iOS Meter 报警/校准 UI 探索(自包含,不 import utils/common 桶,避免 ts-node require vitest 报错)。 const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); async function main() { process.env.PLATFORM = 'ios'; const driver: any = createDriver(); await driver.createSession(); const dump = async (tag: string) => { const src: string = await driver.getSource().catch(() => ''); const labels = [...new Set((src.match(/(?:name|label)="[^"]{1,44}"/g) || []))].slice(0, 70); console.log(`\n===== [${tag}] ${labels.length} labels =====`); console.log(labels.join('\n')); }; const find = (pred: string) => driver.findElementRaw('predicate string', pred).catch(() => null); try { // 1) 首页滚动查找 Meter 0B cell(首屏没有,需向下 flick 找)→ 点进设备页 let cell = null; for (let i = 0; i < 16 && !cell; i++) { cell = await find('name CONTAINS "Meter 0B" AND type == "XCUIElementTypeCell"') || await find('name CONTAINS "Meter 0B"'); if (cell) break; await driver.scrollDown(400).catch(() => {}); await sleep(700); } if (!cell) { console.log('滚动 16 次仍找不到 Meter 0B'); } else { console.log('找到 Meter 0B,点进'); await driver.tapElement(cell); await sleep(2500); } // 2) 详情页:列出所有 Button + 坐标,找右上角齿轮 const btns: string[] = await driver.findElementsRaw('predicate string', 'type == "XCUIElementTypeButton"').catch(() => []); console.log(`\n===== [详情页 Button 列表] ${btns.length} 个 =====`); const rects: { el: string; name: string; x: number; y: number; w: number }[] = []; for (const b of btns) { const r = await driver.getElementRect(b).catch(() => null); const nm = await driver.getElementAttribute(b, 'name').catch(() => '') || ''; if (r) { rects.push({ el: b, name: nm, x: r.x, y: r.y, w: r.width }); console.log(` "${nm}" @(${Math.round(r.x)},${Math.round(r.y)}) w=${Math.round(r.width)}`); } } // 右上角齿轮:y 最小(顶栏)、x 最大(最右)的无名/gear 按钮 const topBar = rects.filter(r => r.y < 130).sort((a, b) => b.x - a.x); const gear = topBar.find(r => /set|gear|齿轮|more/i.test(r.name)) || topBar[0]; if (gear) { console.log(`点右上角按钮 "${gear.name}" @(${Math.round(gear.x)},${Math.round(gear.y)})`); await driver.tapElement(gear.el); await sleep(2500); } await dump('齿轮后页面'); // 3) Alert Conditions const alert = await find('name CONTAINS "Alert" OR label CONTAINS "Alert"'); if (alert) { await driver.tapElement(alert); await sleep(4000); await dump('AlertConditions页'); // 原始结构:Temperature Alert 附近的元素类型/value(找启用控件) const src: string = await driver.getSource().catch(() => ''); const idx = src.indexOf('Temperature Alert'); console.log('\n===== [Temperature Alert 附近原始 XML] ====='); console.log(src.slice(Math.max(0, idx - 400), idx + 900).replace(/>\n<')); await driver.tap(33, 69); await sleep(2000); } else console.log('!! 未找到 Alert Conditions 入口'); // 4) Calibration const cal = await find('name CONTAINS "Calibrat" OR label CONTAINS "Calibrat"'); if (cal) { await driver.tapElement(cal); await sleep(3500); await dump('Calibration列表页'); const t = await find('name CONTAINS "Temperature" OR label CONTAINS "Temperature"'); if (t) { await driver.tapElement(t); await sleep(2500); const nx = await find('name == "Next" OR label == "Next"'); if (nx) { await driver.tapElement(nx); await sleep(2500); } await dump('温度校准offset页'); } } else console.log('!! 未找到 Calibration 入口'); } catch (e: any) { console.log('探索异常:', e.message); } finally { await driver.destroySession().catch(() => {}); } } main();