import { DeviceDriver } from '../../drivers/types'; export function sleep(ms: number): Promise { return new Promise(r => setTimeout(r, ms)); } /** * 诊断:打印当前页面上的设备卡名(找不到目标设备时调,方便定位 = 真没这设备,还是名字/状态变了/还没渲染)。 * Android 取 nameText/nameTextMeter 节点文本;iOS 取 XCUIElementTypeCell 的 name。失败只告警,不抛。 */ export async function logVisibleDeviceCards(driver: DeviceDriver, context: string): Promise { try { const src = await driver.getSource(); let names: string[] = []; if (driver.platform === 'android') { for (const n of src.split('<')) { if (!/resource-id="[^"]*\/(nameText|nameTextMeter)"/.test(n)) continue; const t = (n.match(/text="([^"]*)"/) || [])[1]; if (t && t.trim()) names.push(t.trim()); } } else { names = (src.match(/XCUIElementTypeCell[^>]*?name="([^"]+)"/g) || []) .map((m) => (m.match(/name="([^"]+)"/) || [])[1]).filter(Boolean) as string[]; } names = [...new Set(names)]; console.log(`[诊断]${context} 当前页设备卡(${names.length}): ${names.slice(0, 50).join(' | ') || '(无)'}`); } catch (e: any) { console.log(`[诊断]${context} 取设备卡列表失败: ${e.message}`); } } export async function waitForElement( driver: DeviceDriver, using: string, value: string, timeout = 10000 ): Promise { const start = Date.now(); while (Date.now() - start < timeout) { const el = await driver.findElementRaw(using, value); if (el) return el; await sleep(1000); } return null; } export async function waitForSource( driver: DeviceDriver, keyword: string, timeout = 10000 ): Promise { const start = Date.now(); while (Date.now() - start < timeout) { const src = await driver.getSource(); if (src.includes(keyword)) return true; await sleep(1000); } return false; } export async function scrollUntilFound( driver: DeviceDriver, using: string, value: string, maxScrolls = 5, scrollDistance = 300 ): Promise { for (let i = 0; i < maxScrolls; i++) { const el = await driver.findElementRaw(using, value); if (el) return el; await driver.scrollDown(scrollDistance); await sleep(800); } return null; } export async function tapWithRetry( driver: DeviceDriver, using: string, value: string, retries = 3 ): Promise { for (let i = 0; i < retries; i++) { try { const el = await driver.findElementRaw(using, value); if (el) { await driver.tapElement(el); return true; } } catch { /* stale element, retry */ } await sleep(500); } return false; } export async function sourceContains(driver: DeviceDriver, keyword: string): Promise { const src = await driver.getSource(); return src.includes(keyword); } export async function findElementOnScreen( driver: DeviceDriver, keyword: string ): Promise { let src = await driver.getSource(); if (src.includes(keyword)) return true; await driver.scrollDown(300); await sleep(800); src = await driver.getSource(); return src.includes(keyword); }