AI_UIAutomation/tests/switch/relay_switch_card.test.ts

120 lines
5.7 KiB
TypeScript

import { describe, it, beforeAll, afterAll, beforeEach, expect } from 'vitest';
import { DeviceDriver } from '../../drivers/types';
import { createDriver } from '../../drivers/factory';
import { TestReporter } from '../../utils/test-reporter';
import { sleep, onesCtrl, setupResilientHooks, findHomeCard } from '../../utils/common';
import * as dotenv from 'dotenv';
import * as path from 'path';
dotenv.config({ path: path.resolve(__dirname, '../../.env') });
// Relay Switch 首页卡片控制(参照 plug_card):Relay Switch 卡**无首页内联开关**(点卡任意处直接进功能页) →
// "首页控制" = 首页找到卡片 + 从首页点卡进设备页发起开/关。功能页:大圆形电源键(中心 ~540,525)+ 状态 "On"/"Off"。
const deviceName = process.env.RELAY_SWITCH_DEVICE || 'Relay Switch 1';
const CTRL = onesCtrl('plug', deviceName) || '[P0]'; // 基础 Relay Switch 1 → step41 Relay1(A1TLxsFw)
describe('Relay Switch Card - 首页卡片控制(进设备页 开/关)', () => {
let driver: DeviceDriver;
let reporter: TestReporter;
setupResilientHooks(() => driver);
const isIOS = () => driver.platform === 'ios';
beforeAll(async () => {
driver = createDriver();
await driver.createSession();
reporter = new TestReporter('RelaySwitch_Card', driver.platform.toUpperCase());
});
beforeEach(async () => {
await driver.dismissPopupIfPresent();
await driver.goBackToHomepage();
await sleep(500);
await driver.dismissPopupIfPresent();
});
afterAll(async () => {
reporter.generate();
await driver.destroySession();
});
function readState(src: string): 'On' | 'Off' | 'unknown' {
if (isIOS()) { const m = src.match(/(?:name|label|value)="(On|Off)"/); return m ? (m[1] as any) : 'unknown'; }
for (const m of src.matchAll(/text="(On|Off)"[^>]*bounds="\[\d+,(\d+)\]\[\d+,\d+\]"/g)) {
const y = +m[2]; if (y > 250 && y < 820) return m[1] as any;
}
return 'unknown';
}
async function tapPower(): Promise<boolean> {
if (!isIOS()) {
const cont = await driver.findElementRaw('-android uiautomator',
'new UiSelector().clickable(true).childSelector(new UiSelector().textMatches("On|Off"))').catch(() => null);
if (cont) { await driver.tapElement(cont); return true; }
const wh = await driver.getWindowSize().catch(() => ({ width: 1080, height: 2400 }));
await driver.tap(Math.round(wh.width * 0.5), Math.round(wh.height * 0.219)); return true;
}
const p = await driver.findElementRaw('predicate string', 'name == "Power" OR name == "On" OR name == "Off"').catch(() => null);
if (p) { await driver.tapElement(p); return true; }
const wh = await driver.getWindowSize().catch(() => ({ width: 390, height: 844 }));
await driver.tap(Math.round(wh.width * 0.5), Math.round(wh.height * 0.28)); return true;
}
async function waitState(want: 'On' | 'Off'): Promise<'On' | 'Off' | 'unknown'> {
let st = readState(await driver.getSource());
for (let i = 0; i < 12 && st !== want; i++) { await sleep(1500); st = readState(await driver.getSource()); }
return st;
}
// 从首页点卡进设备页(无弹窗,点卡直进)
async function enterFromCard(): Promise<boolean> {
const card = await findHomeCard(driver, deviceName);
if (!card) return false;
await driver.tapElement(card); await sleep(2200);
for (let i = 0; i < 8; i++) { if (readState(await driver.getSource()) !== 'unknown') return true; await sleep(1000); }
return readState(await driver.getSource()) !== 'unknown';
}
it(`首页找到 ${deviceName} 卡片`, { timeout: 60000 }, async () => {
const start = Date.now();
try {
const card = await findHomeCard(driver, deviceName);
expect(card).not.toBeNull();
const rect = await driver.getElementRect(card!);
expect(rect.width).toBeGreaterThan(0);
reporter.record('首页找到Relay Switch卡片', 'PASS', Date.now() - start, `位置(${rect.x},${rect.y}) ${rect.width}x${rect.height}`);
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record('首页找到Relay Switch卡片', 'FAIL', Date.now() - start, e.message, ss); throw e;
}
});
it(`${CTRL} 首页控制${deviceName}(开+关)`, { timeout: 120000 }, async () => {
const start = Date.now();
try {
if (!(await enterFromCard())) {
// 首页有该开关却进不去设备页 = 未正确执行 → FAIL(交给 catch);首页确无该开关(未添加/本平台无实体)→ 合法 SKIP。
await driver.goBackToHomepage().catch(() => {}); await sleep(1200);
if (await findHomeCard(driver, deviceName).catch(() => null)) throw new Error('首页进设备页失败(首页有该开关但进不去,未正确执行)');
reporter.record(`${CTRL} 首页控制${deviceName}`, 'SKIP', Date.now() - start, '首页无该开关(未添加/本平台无实体),跳过');
return;
}
const s0 = readState(await driver.getSource());
console.log(`[RSCard] 初始: ${s0}`);
const target1 = s0 === 'On' ? 'Off' : 'On';
expect(await tapPower()).toBe(true);
const s1 = await waitState(target1);
console.log(`[RSCard] 操作1后: ${s1}(目标${target1})`);
expect(s1).toBe(target1);
const target2 = target1 === 'On' ? 'Off' : 'On';
await tapPower();
const s2 = await waitState(target2);
console.log(`[RSCard] 操作2后: ${s2}(目标${target2})`);
expect(s2).toBe(target2);
reporter.record(`${CTRL} 首页控制${deviceName}`, 'PASS', Date.now() - start, `首页发起开/关均生效(${s0}${s1}${s2})`);
} catch (e: any) {
const ss = await driver.screenshot().catch(() => '');
reporter.record(`${CTRL} 首页控制${deviceName}`, 'FAIL', Date.now() - start, e.message, ss); throw e;
}
});
});