117 lines
5.1 KiB
TypeScript
117 lines
5.1 KiB
TypeScript
import { describe, it, beforeAll, afterAll, expect } from 'vitest';
|
|
import { execSync } from 'child_process';
|
|
import { DeviceDriver } from '../../drivers/types';
|
|
import { createDriver } from '../../drivers/factory';
|
|
import { TestReporter } from '../../utils/test-reporter';
|
|
import { setupResilientHooks } from "../../utils/common";
|
|
import {
|
|
sleep, ensureHomeTab, onesPlatform,
|
|
createAutomation, verifyAutomationExecuted, deleteAutomation,
|
|
createScene, executeSceneFromHomepage, verifySceneInLogs, deleteScene,
|
|
signInWithEmail, isLoggedIn,
|
|
} from '../../utils/common';
|
|
import * as dotenv from 'dotenv';
|
|
import * as path from 'path';
|
|
|
|
dotenv.config({ path: path.resolve(__dirname, '../../.env') });
|
|
|
|
const ANCHOR = `${onesPlatform(15976)} 场景操作`; // P0:场景操作验证(① 自动化 ② 场景)
|
|
|
|
/** 读设备当前时间 [h, m]。Android 用 adb;iOS 用 idevicedate(系统已切 24h)。 */
|
|
function deviceNow(platform: string): [number, number] {
|
|
if (platform === 'ios') {
|
|
try {
|
|
const out = execSync('idevicedate').toString().trim(); // 形如 "Tue Jun 23 20:42:30 CST 2026"
|
|
const m = out.match(/(\d{1,2}):(\d{2}):\d{2}/);
|
|
if (m) return [parseInt(m[1], 10), parseInt(m[2], 10)];
|
|
} catch { /* 兜底用本机时间 */ }
|
|
const d = new Date();
|
|
return [d.getHours(), d.getMinutes()];
|
|
}
|
|
const out = execSync('adb shell date +%H:%M').toString().trim().split(':');
|
|
return [parseInt(out[0], 10), parseInt(out[1], 10)];
|
|
}
|
|
/** 在 [h,m] 上加 addMin 分钟,返回 [h,m](跨小时进位)。 */
|
|
function plusMin(h: number, m: number, addMin: number): [number, number] {
|
|
const t = (h * 60 + m + addMin) % (24 * 60);
|
|
return [Math.floor(t / 60), t % 60];
|
|
}
|
|
|
|
describe('Platform - 场景操作(自动化 + 场景)', () => {
|
|
let driver: DeviceDriver;
|
|
let reporter: TestReporter;
|
|
setupResilientHooks(() => driver);
|
|
const autoName = `AutoOp${Date.now() % 100000}`;
|
|
const sceneName = `SceneOp${Date.now() % 100000}`;
|
|
|
|
beforeAll(async () => {
|
|
driver = createDriver();
|
|
await driver.createSession();
|
|
reporter = new TestReporter('Platform_SceneOp', driver.platform.toUpperCase());
|
|
// 复位到干净首页:上一轮可能残留场景创建模态/Smart Devices 页,直接 isLoggedIn 会在残留态导航挂死(120s hook 超时)。
|
|
await driver.restartApp?.().catch(() => {});
|
|
await driver.goBackToHomepage().catch(() => {});
|
|
if (!(await isLoggedIn(driver))) await signInWithEmail(driver);
|
|
}, 90000);
|
|
|
|
afterAll(async () => {
|
|
// 兜底清理
|
|
try { await deleteAutomation(driver, autoName); } catch { /**/ }
|
|
try { await ensureHomeTab(driver); await deleteScene(driver, sceneName); } catch { /**/ }
|
|
reporter.generate();
|
|
await driver.destroySession();
|
|
});
|
|
|
|
it(`${ANCHOR} ① 自动化创建与执行`, { timeout: 360000 }, async () => {
|
|
const start = Date.now();
|
|
try {
|
|
// 定时设为设备时间 + 2 分钟(创建较快,留出创建耗时后约 1 分钟内触发)
|
|
const [nh, nm] = deviceNow(driver.platform);
|
|
const [th, tm] = plusMin(nh, nm, 2);
|
|
console.log(`设备时间 ${nh}:${nm} → 定时 ${th}:${tm}`);
|
|
const created = await createAutomation(driver, { name: autoName, deviceKeyword: 'Bot 14', targetHour: th, targetMinute: tm, action: 'Turns off' });
|
|
expect(created).toBe(true);
|
|
|
|
// 等到点(目标时间 + 40s 让引擎触发+落日志)
|
|
const deadlineMin = th * 60 + tm;
|
|
for (let i = 0; i < 60; i++) {
|
|
const [ch, cm] = deviceNow(driver.platform);
|
|
if (ch * 60 + cm > deadlineMin) break;
|
|
await sleep(10000);
|
|
}
|
|
await sleep(40000);
|
|
|
|
const executed = await verifyAutomationExecuted(driver, autoName);
|
|
expect(executed).toBe(true);
|
|
await deleteAutomation(driver, autoName);
|
|
reporter.record(`${ANCHOR} ①自动化`, 'PASS', Date.now() - start, `自动化 ${autoName} 定时${th}:${tm} 触发并有日志,已删除`);
|
|
} catch (e: any) {
|
|
const ss = await driver.screenshot().catch(() => '');
|
|
reporter.record(`${ANCHOR} ①自动化`, 'FAIL', Date.now() - start, e.message, ss);
|
|
throw e;
|
|
}
|
|
});
|
|
|
|
it(`${ANCHOR} ② 场景创建与执行`, { timeout: 180000 }, async () => {
|
|
const start = Date.now();
|
|
try {
|
|
// 场景动作与自动化(Bot Turns off)区分:Bot Turns on(同设备不同动作)
|
|
const created = await createScene(driver, { name: sceneName, deviceKeyword: 'Bot 14', action: 'Turns on' });
|
|
expect(created).toBe(true);
|
|
await ensureHomeTab(driver);
|
|
const executed = await executeSceneFromHomepage(driver, sceneName);
|
|
expect(executed).toBe(true);
|
|
await sleep(6000);
|
|
await driver.goBackToHomepage();
|
|
const hasLog = await verifySceneInLogs(driver, sceneName);
|
|
expect(hasLog).toBe(true);
|
|
await deleteScene(driver, sceneName);
|
|
reporter.record(`${ANCHOR} ②场景`, 'PASS', Date.now() - start, `场景 ${sceneName} 执行并有日志,已删除`);
|
|
} catch (e: any) {
|
|
const ss = await driver.screenshot().catch(() => '');
|
|
reporter.record(`${ANCHOR} ②场景`, 'FAIL', Date.now() - start, e.message, ss);
|
|
throw e;
|
|
}
|
|
});
|
|
});
|