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 { getDeviceName } from '../../config/device.config'; import { sleep, enterDeviceSettings, renameDevice, changeDeviceRoom, navigateToTimerPage, addTimer, deleteAllTimers, navigateToFirmwarePage, checkFirmwareVersion, navigateToDeviceInfo, getDeviceInfo, scrollToAndTap, waitForSource, enterEditInfo, addDeviceViaBLE, isDeviceOnHomepage, } from '../../utils/common'; import * as dotenv from 'dotenv'; import * as path from 'path'; dotenv.config({ path: path.resolve(__dirname, '../../.env') }); const deviceName = getDeviceName('ceilingLight', 'CEILING_LIGHT_DEVICE'); // 必测项控制锚点: 点击控制吸顶灯pro开/关灯 BLE 15975#2528azD6 / WiFi 15974#TcnL3gFM const PROTO = process.env.PROTO === 'wifi' ? 'wifi' : 'ble'; const CTRL_CEIL = PROTO === 'wifi' ? '[P0][ONES:15974#TcnL3gFM][wifi]' : '[P0][ONES:15975#2528azD6][ble]'; describe('CeilingLight Control - 吸顶灯功能页', () => { let driver: DeviceDriver; let reporter: TestReporter; beforeAll(async () => { driver = createDriver(); await driver.createSession(); reporter = new TestReporter('CeilingLight_Control', driver.platform.toUpperCase()); }); beforeEach(async () => { await driver.dismissPopupIfPresent(); await driver.goBackToHomepage(); await driver.dismissPopupIfPresent(); }); afterAll(async () => { reporter.generate(); await driver.destroySession(); }); async function enterCeilingLightControl(): Promise { const 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 enterCeilingLightControl(); const powerEl = await driver.findElementRaw('name', 'Power') || await driver.findElementRaw('name', 'power') || await driver.findElementRaw('name', 'ON'); expect(powerEl).not.toBeNull(); await driver.tapElement(powerEl!); await sleep(3000); const source = await driver.getSource(); const isOn = source.includes('ON') || source.includes('Night Light') || source.includes('Full'); expect(isOn).toBe(true); reporter.record(`${CTRL_CEIL} 打开开关`, 'PASS', Date.now() - start, `吸顶灯已开启`); } catch (e: any) { const ss = await driver.screenshot().catch(() => ''); reporter.record(`${CTRL_CEIL} 打开开关`, 'FAIL', Date.now() - start, e.message, ss); throw e; } }); it('打开小夜灯', async () => { const start = Date.now(); try { await enterCeilingLightControl(); const nightLightEl = await driver.findElementRaw('name', 'Night Light') || await driver.findElementRaw('name', 'night light') || await driver.findElementRaw('name', 'Night'); expect(nightLightEl).not.toBeNull(); await driver.tapElement(nightLightEl!); await sleep(3000); const source = await driver.getSource(); const isNightLight = source.includes('Night Light') || source.includes('Night'); expect(isNightLight).toBe(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 enterCeilingLightControl(); const fullLightEl = await driver.findElementRaw('name', 'Full Light') || await driver.findElementRaw('name', 'Full') || await driver.findElementRaw('name', 'full light'); expect(fullLightEl).not.toBeNull(); await driver.tapElement(fullLightEl!); await sleep(3000); const source = await driver.getSource(); const isFull = source.includes('Full Light') || source.includes('Full'); expect(isFull).toBe(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 enterCeilingLightControl(); const automationEl = await driver.findElementRaw('name', 'Automation') || await driver.findElementRaw('name', 'automation') || await driver.findElementRaw('name', 'Auto'); expect(automationEl).not.toBeNull(); await driver.tapElement(automationEl!); await sleep(3000); let source = await driver.getSource(); const hasAutomation = source.includes('Automation') || source.includes('Scene') || source.includes('Auto'); expect(hasAutomation).toBe(true); // Toggle back const backEl = await driver.findElementRaw('name', 'Back') || await driver.findElementRaw('name', 'back') || await driver.findElementRaw('name', 'Close'); if (backEl) { await driver.tapElement(backEl); await sleep(2000); } 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 enterCeilingLightControl(); const tapped = await scrollToAndTap(driver, 'Delay'); expect(tapped).toBe(true); await sleep(2000); const source = await driver.getSource(); const hasDelay = source.includes('Delay') || source.includes('Timer') || source.includes('Hour') || source.includes('Min'); expect(hasDelay).toBe(true); // Confirm the delay setting const confirmEl = await driver.findElementRaw('name', 'Confirm') || await driver.findElementRaw('name', 'OK') || await driver.findElementRaw('name', 'Save'); if (confirmEl) { await driver.tapElement(confirmEl); await sleep(2000); } 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 enterCeilingLightControl(); 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(); const hasTimer = source.includes('Only once') || source.includes('Timer'); console.log('定时器添加成功:', hasTimer); 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 enterCeilingLightControl(); const navOk = await navigateToTimerPage(driver); expect(navOk).toBe(true); await sleep(2000); 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 enterCeilingLightControl(); const powerEl = await driver.findElementRaw('name', 'Power') || await driver.findElementRaw('name', 'power') || await driver.findElementRaw('name', 'OFF'); expect(powerEl).not.toBeNull(); await driver.tapElement(powerEl!); await sleep(3000); const source = await driver.getSource(); const isOff = source.includes('OFF') || source.includes('off') || !source.includes('Night Light'); console.log('吸顶灯已关闭:', isOff); reporter.record(`${CTRL_CEIL} 关闭开关`, 'PASS', Date.now() - start, `吸顶灯已关闭`); } catch (e: any) { const ss = await driver.screenshot().catch(() => ''); reporter.record(`${CTRL_CEIL} 关闭开关`, 'FAIL', Date.now() - start, e.message, ss); throw e; } }); });