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, navigateToTimerPage, addTimer, deleteAllTimers, scrollToAndTap, waitForSource, enterDeviceSettings, } from '../../utils/common'; import { getDeviceName } from '../../config/device.config'; import * as dotenv from 'dotenv'; import * as path from 'path'; dotenv.config({ path: path.resolve(__dirname, '../../.env') }); const deviceName = getDeviceName('plug', 'PLUG_DEVICE'); // 必测项控制锚点: 点击控制Plug 开/关 仅 WiFi 必测(15974#Ay79Pj23);BLE 无 base Plug 必测步 → ble 模式不打锚点 import { onesCtrl } from "../../utils/common"; const CTRL_PLUG = onesCtrl("plug", deviceName); describe('Plug Control - 功能页操作', () => { let driver: DeviceDriver; let reporter: TestReporter; beforeAll(async () => { driver = createDriver(); await driver.createSession(); reporter = new TestReporter('Plug_Control', driver.platform.toUpperCase()); }); beforeEach(async () => { await driver.dismissPopupIfPresent(); await driver.goBackToHomepage(); await driver.dismissPopupIfPresent(); }); afterAll(async () => { reporter.generate(); await driver.destroySession(); }); async function enterControlPage(): Promise { let el = await driver.findElementRaw('name', deviceName); if (!el) { await driver.scrollDown(250); await sleep(1000); el = await driver.findElementRaw('name', deviceName); } if (!el) throw new Error(`找不到${deviceName}卡片`); await driver.tapElement(el); await sleep(3000); } it('功能页打开/关闭开关', async () => { const start = Date.now(); try { await enterControlPage(); // Find power toggle on control page let source = await driver.getSource(); const wasTurnedOn = source.includes('ON') || source.includes('Turn off'); // Tap the main power button on control page const powerBtn = await driver.findElementRaw('name', 'Power') || await driver.findElementRaw('name', 'power') || await driver.findElementRaw('name', 'ON') || await driver.findElementRaw('name', 'OFF'); if (powerBtn) { await driver.tapElement(powerBtn); } else { // Tap center of screen as fallback for large power button await driver.tap(200, 400); } await sleep(5000); source = await driver.getSource(); const isNowOn = source.includes('ON') || source.includes('Turn off'); const statusChanged = wasTurnedOn !== isNowOn; console.log(`功能页开关: ${wasTurnedOn ? 'ON' : 'OFF'} → ${isNowOn ? 'ON' : 'OFF'}`); // Restore original state if (powerBtn) { await driver.tapElement(powerBtn); } else { await driver.tap(200, 400); } await sleep(5000); expect(statusChanged).toBe(true); reporter.record(`${CTRL_PLUG}功能页打开/关闭开关`, 'PASS', Date.now() - start, `控制页开关切换成功`); } catch (e: any) { const ss = await driver.screenshot().catch(() => ''); reporter.record(`${CTRL_PLUG}功能页打开/关闭开关`, 'FAIL', Date.now() - start, e.message, ss); throw e; } }); it('定时器-添加', async () => { const start = Date.now(); try { const entered = await enterDeviceSettings(driver, deviceName); expect(entered).toBe(true); const navOk = await navigateToTimerPage(driver); expect(navOk).toBe(true); await sleep(2000); const added = await addTimer(driver); expect(added).toBe(true); const source = await driver.getSource(); expect(source).toContain('Only once'); console.log('定时器列表有Only once: true'); reporter.record('定时器-添加', 'PASS', Date.now() - start, '添加Only once定时成功'); } catch (e: any) { const ss = await driver.screenshot().catch(() => ''); reporter.record('定时器-添加', 'FAIL', Date.now() - start, e.message, ss); throw e; } }); it('定时器-删除', async () => { const start = Date.now(); try { const entered = await enterDeviceSettings(driver, deviceName); expect(entered).toBe(true); const navOk = await navigateToTimerPage(driver); expect(navOk).toBe(true); await sleep(2000); // Ensure at least one timer exists let source = await driver.getSource(); if (!source.includes('Only once') && !source.includes('Turn on') && !source.includes('Turn off')) { await addTimer(driver); } const deleted = await deleteAllTimers(driver); expect(deleted).toBe(true); console.log('定时器已清空: true'); reporter.record('定时器-删除', 'PASS', Date.now() - start, '选择删除 → 确认 → 定时器列表已清空'); } catch (e: any) { const ss = await driver.screenshot().catch(() => ''); reporter.record('定时器-删除', 'FAIL', Date.now() - start, e.message, ss); throw e; } }); it('延迟开关', async () => { const start = Date.now(); try { await enterControlPage(); const tapped = await scrollToAndTap(driver, 'Delay'); if (!tapped) { // Try alternative names const altTapped = await scrollToAndTap(driver, 'Countdown') || await scrollToAndTap(driver, 'Timer'); expect(altTapped).toBe(true); } await sleep(2000); // Set a delay time and confirm const source = await driver.getSource(); const hasDelayPage = source.includes('Delay') || source.includes('Countdown') || source.includes('Timer'); expect(hasDelayPage).toBe(true); // Find confirm/save button const confirmBtn = await driver.findElementRaw('name', 'Save') || await driver.findElementRaw('name', 'Confirm') || await driver.findElementRaw('name', 'OK') || await driver.findElementRaw('name', 'Start'); if (confirmBtn) { await driver.tapElement(confirmBtn); await sleep(2000); } // Cancel the delay to restore state const cancelBtn = await driver.findElementRaw('name', 'Cancel') || await driver.findElementRaw('name', 'Stop'); if (cancelBtn) { await driver.tapElement(cancelBtn); await sleep(1000); } console.log('延迟开关页面验证成功'); reporter.record('延迟开关', 'PASS', Date.now() - start, '延迟开关设置页打开成功'); } catch (e: any) { const ss = await driver.screenshot().catch(() => ''); reporter.record('延迟开关', 'FAIL', Date.now() - start, e.message, ss); throw e; } }); it('导出数据', async () => { const start = Date.now(); try { await enterControlPage(); const tapped = await scrollToAndTap(driver, 'Export Data'); expect(tapped).toBe(true); await sleep(3000); const source = await driver.getSource(); const hasExportPage = source.includes('Export') || source.includes('Data') || source.includes('Share') || source.includes('Email'); expect(hasExportPage).toBe(true); console.log('导出数据页面验证成功'); reporter.record('导出数据', 'PASS', Date.now() - start, 'Export Data页面打开成功'); } catch (e: any) { const ss = await driver.screenshot().catch(() => ''); reporter.record('导出数据', 'FAIL', Date.now() - start, e.message, ss); throw e; } }); });