import { describe, it, beforeAll, afterAll, expect } from 'vitest'; import { DeviceDriver } from '../../drivers/types'; import { createDriver } from '../../drivers/factory'; import { TestReporter } from '../../utils/test-reporter'; import { sleep, ensureHomeTab, setupResilientHooks } from '../../utils/common'; import * as dotenv from 'dotenv'; import * as path from 'path'; dotenv.config({ path: path.resolve(__dirname, '../../.env') }); // Action Panel Settings(首页右上 More → Action Panel Settings):把所有设备的开关**全部打开**。 // 开关=ON → 点设备卡片弹「快捷动作浮层」(灯/加湿器等卡片控制用例依赖);=OFF → 点卡片进功能页。 // 添加新设备后该开关可能默认 OFF → 控制用例会误进功能页失败。故添加后跑此用例统一打开。 describe('Platform - Action Panel Settings(打开所有快捷面板开关)', () => { let driver: DeviceDriver; let reporter: TestReporter; setupResilientHooks(() => driver); beforeAll(async () => { driver = createDriver(); await driver.createSession(); reporter = new TestReporter('Platform_ActionPanel', driver.platform.toUpperCase()); }); afterAll(async () => { reporter.generate(); await driver.destroySession(); }); it('[P0] Action Panel Settings 打开所有开关', { timeout: 120000 }, async () => { const start = Date.now(); const isIOS = driver.platform === 'ios'; // 平台差异(iOS 参考 Android 流程,仅换元素类型):More 按钮 / Switch 类型与状态属性 const findSwitches = () => isIOS ? driver.findElementsRaw('class name', 'XCUIElementTypeSwitch').catch(() => [] as string[]) : driver.findElementsRaw('-android uiautomator', 'new UiSelector().className("android.widget.Switch")').catch(() => [] as string[]); const isSwitchOff = async (sw: string) => isIOS ? (await driver.getElementAttribute(sw, 'value').catch(() => '1')) === '0' // iOS Switch value: 0=off / 1=on : (await driver.getElementAttribute(sw, 'checked').catch(() => 'true')) === 'false'; try { // 紧跟 ADD 阶段(大量添加+重试),App 常停在添加残留页/弹框 → 必须**彻底回首页**再点 More, // 否则 More 落到错页(菜单不开 → 找不到 Action Panel Settings)。带重试:菜单没开就重回首页再点。 let aps: string | null = null; for (let attempt = 0; attempt < 3 && !aps; attempt++) { await driver.goBackToHomepage().catch(() => {}); await driver.dismissPopupIfPresent().catch(() => {}); await ensureHomeTab(driver); await sleep(1000); // 点右上 More(Android: moreBto id;iOS: name "More") const more = isIOS ? await driver.findElementRaw('name', 'More').catch(() => null) : await driver.findElementRaw('id', 'com.theswitchbot.switchbot:id/moreBto').catch(() => null); if (more) await driver.tapElement(more); else if (!isIOS) await driver.tap(1008, 164); await sleep(1800); aps = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("Action Panel Settings")').catch(() => null) || await driver.findElementRaw('name', 'Action Panel Settings').catch(() => null); if (!aps) console.log(`[ActionPanel] 第 ${attempt + 1} 次点 More 未见菜单(可能没在首页),重试`); } if (!aps) throw new Error('More 菜单未找到 Action Panel Settings(多次重试仍未进首页 More 菜单)'); await driver.tapElement(aps); await sleep(2000); // 2) 滚动遍历所有 Switch:OFF 的点开。到底(页面签名不变)即停。 let turnedOn = 0; let lastSig = ''; for (let r = 0; r < 14; r++) { const switches = await findSwitches(); for (const sw of switches) { if (await isSwitchOff(sw)) { await driver.tapElement(sw); turnedOn++; await sleep(600); } } const sig = (await driver.getSource()).slice(-2500); if (sig === lastSig) break; // 到底,无新内容 lastSig = sig; await driver.scrollDown(500); await sleep(800); } console.log(`Action Panel Settings: 本次打开 ${turnedOn} 个开关`); // 3) 回顶补扫,确保无残留 OFF for (let i = 0; i < 6; i++) { await driver.scrollUp(500); await sleep(200); } let stillOff = 0; for (const sw of await findSwitches()) { if (await isSwitchOff(sw)) { await driver.tapElement(sw); stillOff++; await sleep(600); } } expect(true).toBe(true); // 动作型用例:成功进入面板并打开开关即通过 reporter.record('[P0] Action Panel Settings 打开所有开关', 'PASS', Date.now() - start, `已打开 ${turnedOn + stillOff} 个开关(快捷动作面板已全开)`); } catch (e: any) { const ss = await driver.screenshot().catch(() => ''); reporter.record('[P0] Action Panel Settings 打开所有开关', 'FAIL', Date.now() - start, e.message, ss); throw e; } }); });