AI_UIAutomation/tests/platform/action_panel_settings.test.ts

94 lines
4.9 KiB
TypeScript

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;
}
});
});