605 lines
23 KiB
TypeScript
605 lines
23 KiB
TypeScript
import { describe, it, beforeAll, afterAll, beforeEach, expect } from 'vitest';
|
||
import { DeviceDriver } from '../../drivers/types';
|
||
import { createDriver } from '../../drivers/factory';
|
||
import { BotHelper } from '../../utils/bot-helper';
|
||
import { BOT_LOCATORS } from '../../locators/bot-locators';
|
||
import { TestReporter } from '../../utils/test-reporter';
|
||
import { getDeviceName } from '../../config/device.config';
|
||
import { sleep } from '../../utils/common';
|
||
import { applyProtoNetwork } from '../../utils/common';
|
||
import * as dotenv from 'dotenv';
|
||
import * as path from 'path';
|
||
|
||
dotenv.config({ path: path.resolve(__dirname, '../../.env') });
|
||
|
||
const deviceName = getDeviceName('bot', 'BOT_DEVICE');
|
||
|
||
// 必测项控制步骤锚点(协议相关,由 PROTO 环境变量切换): BLE→15975#6e4uZSVe / WiFi→15974#Qt4hcgB4
|
||
// 该 step「点击控制Bot 不加密开&不加密关&加密按压」由 ON/OFF切换 + 加密按压 两个用例共同覆盖,回写时按 step 聚合
|
||
const PROTO = process.env.PROTO === 'wifi' ? 'wifi' : 'ble';
|
||
const CTRL = PROTO === 'wifi' ? '[P0][ONES:15974#Qt4hcgB4][wifi]' : '[P0][ONES:15975#6e4uZSVe][ble]';
|
||
|
||
describe('Bot Card - 首页卡片操作', () => {
|
||
let driver: DeviceDriver;
|
||
let bot: BotHelper;
|
||
let reporter: TestReporter;
|
||
|
||
beforeAll(async () => {
|
||
driver = createDriver();
|
||
await driver.createSession();
|
||
bot = new BotHelper(driver);
|
||
reporter = new TestReporter('Bot_Card', driver.platform.toUpperCase());
|
||
// 双协议前置:按 PROTO 切手机蓝牙/WiFi(ble→开蓝牙关WiFi / wifi→关蓝牙开WiFi),无人值守自动切
|
||
await applyProtoNetwork(driver, PROTO);
|
||
});
|
||
|
||
beforeEach(async () => {
|
||
await driver.dismissPopupIfPresent();
|
||
await driver.goBackToHomepage();
|
||
await sleep(500);
|
||
await driver.dismissPopupIfPresent();
|
||
});
|
||
|
||
afterAll(async () => {
|
||
reporter.generate();
|
||
await driver.destroySession();
|
||
});
|
||
|
||
async function findBot(): Promise<string> {
|
||
let botId = await driver.findDeviceCard(deviceName);
|
||
if (!botId) {
|
||
await driver.scrollDown(250);
|
||
await sleep(1000);
|
||
botId = await driver.findDeviceCard(deviceName);
|
||
}
|
||
if (!botId) throw new Error(`找不到${deviceName}卡片`);
|
||
return botId;
|
||
}
|
||
|
||
async function captureScreenshot(): Promise<string | undefined> {
|
||
try { return await driver.screenshot(); } catch { return undefined; }
|
||
}
|
||
|
||
async function tapBotAndWaitPopup(): Promise<void> {
|
||
const botId = await findBot();
|
||
await driver.tapElement(botId);
|
||
await sleep(1500);
|
||
if (driver.platform === 'android') return;
|
||
const check = await driver.findElement(BOT_LOCATORS.settingsButton);
|
||
if (!check) {
|
||
const botId2 = await driver.findDeviceCard(deviceName);
|
||
if (botId2) {
|
||
await driver.tapElement(botId2);
|
||
await sleep(1500);
|
||
}
|
||
}
|
||
}
|
||
|
||
async function navigateToModeSettings(): Promise<void> {
|
||
await tapBotAndWaitPopup();
|
||
if (driver.platform === 'ios') {
|
||
const settingsId = await driver.findElement(BOT_LOCATORS.settingsButton);
|
||
if (!settingsId) throw new Error('Settings弹窗未出现');
|
||
await driver.tapElement(settingsId);
|
||
await sleep(2000);
|
||
}
|
||
const modeId = await driver.findElement(BOT_LOCATORS.modeItem);
|
||
if (!modeId) throw new Error('Mode菜单未找到');
|
||
await driver.tapElement(modeId);
|
||
await sleep(2000);
|
||
await dismissPasswordDialogIfPresent();
|
||
}
|
||
|
||
async function getCurrentMode(): Promise<'Press' | 'Switch' | 'Unknown'> {
|
||
const source = await driver.getSource();
|
||
if (source.includes('In Switch Mode')) return 'Switch';
|
||
if (source.includes('In Press Mode')) return 'Press';
|
||
if (source.includes('Switch Mode')) return 'Switch';
|
||
if (source.includes('Press Mode')) return 'Press';
|
||
return 'Unknown';
|
||
}
|
||
|
||
async function dismissPasswordDialogIfPresent(): Promise<void> {
|
||
const source = await driver.getSource();
|
||
if (source.includes('Enter password') || source.includes('Enter Password')) {
|
||
const fields = await driver.findElementsRaw('class name', driver.platform === 'android' ? 'android.widget.EditText' : 'XCUIElementTypeSecureTextField');
|
||
if (fields.length > 0) {
|
||
await driver.typeText(fields[0], '1234');
|
||
await sleep(500);
|
||
const okEl = await driver.findElementRaw('name', 'OK') || await driver.findElementRaw('name', 'Confirm');
|
||
if (okEl) await driver.tapElement(okEl);
|
||
await sleep(2000);
|
||
}
|
||
}
|
||
}
|
||
|
||
async function switchToMode(targetMode: 'Press Mode' | 'Switch Mode'): Promise<boolean> {
|
||
if (driver.platform === 'android') {
|
||
// Tap the mode selector container to open mode dialog
|
||
const sivMode = await driver.findElementRaw('-android uiautomator',
|
||
'new UiSelector().resourceId("com.theswitchbot.switchbot:id/sivMode")');
|
||
if (!sivMode) return false;
|
||
await driver.tapElement(sivMode);
|
||
await sleep(1500);
|
||
const targetId = await driver.findElementRaw('name', targetMode);
|
||
if (!targetId) {
|
||
const cancelId = await driver.findElementRaw('name', 'Cancel');
|
||
if (cancelId) await driver.tapElement(cancelId);
|
||
return false;
|
||
}
|
||
await driver.tapElement(targetId);
|
||
await sleep(1500);
|
||
const confirmId = await driver.findElementRaw('name', 'Confirm') || await driver.findElementRaw('name', 'OK');
|
||
if (confirmId) {
|
||
await driver.tapElement(confirmId);
|
||
await sleep(2000);
|
||
}
|
||
return true;
|
||
}
|
||
const modeLabel = await driver.findElementRaw('predicate string', 'name == "Mode" AND type == "XCUIElementTypeStaticText" AND visible == true');
|
||
if (!modeLabel) return false;
|
||
const modeRect = await driver.getElementRect(modeLabel);
|
||
await driver.tap(modeRect.x + modeRect.width + 50, modeRect.y + modeRect.height / 2);
|
||
await sleep(1500);
|
||
|
||
const targetId = await driver.findElementRaw('predicate string', `name == "${targetMode}" AND visible == true`);
|
||
if (!targetId) {
|
||
const cancelId = await driver.findElementRaw('name', 'Cancel');
|
||
if (cancelId) await driver.tapElement(cancelId);
|
||
return false;
|
||
}
|
||
await driver.tapElement(targetId);
|
||
await sleep(1500);
|
||
|
||
const confirmId = await driver.findElementRaw('predicate string', 'name == "Confirm" OR name == "OK"');
|
||
if (confirmId) {
|
||
await driver.tapElement(confirmId);
|
||
await sleep(2000);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
it(`首页找到${deviceName}卡片`, async () => {
|
||
const start = Date.now();
|
||
try {
|
||
const botId = await findBot();
|
||
const rect = await driver.getElementRect(botId);
|
||
const detail = `位置: (${rect.x}, ${rect.y}) 尺寸: ${rect.width}x${rect.height}`;
|
||
console.log(`${deviceName} ${detail}`);
|
||
expect(rect.width).toBeGreaterThan(0);
|
||
expect(rect.height).toBeGreaterThan(0);
|
||
reporter.record(`首页找到${deviceName}卡片`, 'PASS', Date.now() - start, detail);
|
||
} catch (e: any) {
|
||
const ss = await captureScreenshot();
|
||
reporter.record(`首页找到${deviceName}卡片`, 'FAIL', Date.now() - start, e.message, ss);
|
||
throw e;
|
||
}
|
||
});
|
||
|
||
it('点击Bot卡片 → 弹出菜单包含Settings', async () => {
|
||
const start = Date.now();
|
||
try {
|
||
await tapBotAndWaitPopup();
|
||
if (driver.platform === 'android') {
|
||
const modeId = await driver.findElement(BOT_LOCATORS.modeItem);
|
||
const passcodeId = await driver.findElement(BOT_LOCATORS.passcodeItem);
|
||
const settingsText = await driver.findElementRaw('name', 'Settings');
|
||
const detail = `Settings页: Settings=${!!settingsText}, Mode=${!!modeId}, Passcode=${!!passcodeId}`;
|
||
console.log(`弹窗按钮: ${detail}`);
|
||
expect(settingsText || modeId).not.toBeNull();
|
||
reporter.record('弹出菜单验证', 'PASS', Date.now() - start, detail);
|
||
} else {
|
||
const settingsId = await driver.findElement(BOT_LOCATORS.settingsButton);
|
||
const onId = await driver.findElement(BOT_LOCATORS.onButton);
|
||
const offId = await driver.findElement(BOT_LOCATORS.offButton);
|
||
const pressBtn = await driver.findElementRaw('name', 'Press');
|
||
const pressOnce = await driver.findElementRaw('predicate string', 'name CONTAINS "Press"');
|
||
const detail = `Settings=${!!settingsId}, ON=${!!onId}, OFF=${!!offId}, Press=${!!pressBtn || !!pressOnce}`;
|
||
console.log(`弹窗按钮: ${detail}`);
|
||
expect(settingsId).not.toBeNull();
|
||
reporter.record('弹出菜单验证', 'PASS', Date.now() - start, detail);
|
||
}
|
||
} catch (e: any) {
|
||
const ss = await captureScreenshot();
|
||
reporter.record('弹出菜单验证', 'FAIL', Date.now() - start, e.message, ss);
|
||
throw e;
|
||
}
|
||
});
|
||
|
||
it('切换设备模式: Switch → Press → Switch', async () => {
|
||
const start = Date.now();
|
||
try {
|
||
await navigateToModeSettings();
|
||
const modeBefore = await getCurrentMode();
|
||
console.log('切换前模式:', modeBefore);
|
||
|
||
const targetMode = modeBefore === 'Switch' ? 'Press Mode' : 'Switch Mode';
|
||
const switched1 = await switchToMode(targetMode as any);
|
||
expect(switched1).toBe(true);
|
||
await sleep(1000);
|
||
|
||
const modeAfter = await getCurrentMode();
|
||
console.log('切换后模式:', modeAfter);
|
||
expect(modeAfter).not.toBe(modeBefore);
|
||
|
||
// Switch back to original
|
||
const restoreMode = modeBefore === 'Switch' ? 'Switch Mode' : 'Press Mode';
|
||
await switchToMode(restoreMode as any);
|
||
await sleep(1000);
|
||
const modeFinal = await getCurrentMode();
|
||
console.log('还原模式:', modeFinal);
|
||
|
||
const detail = `${modeBefore} → ${modeAfter} → ${modeFinal}`;
|
||
reporter.record('切换设备模式', 'PASS', Date.now() - start, detail);
|
||
} catch (e: any) {
|
||
const ss = await captureScreenshot();
|
||
reporter.record('切换设备模式', 'FAIL', Date.now() - start, e.message, ss);
|
||
throw e;
|
||
}
|
||
});
|
||
|
||
it('Switch模式 - ON/OFF切换', async () => {
|
||
const start = Date.now();
|
||
try {
|
||
// Ensure device is in Switch Mode before attempting ON/OFF
|
||
let statusBefore = await bot.getBotStatus();
|
||
console.log('初始状态:', statusBefore);
|
||
|
||
if (statusBefore === 'unknown') {
|
||
console.log('设备可能非Switch Mode,先切换到Switch Mode...');
|
||
await navigateToModeSettings();
|
||
const currentMode = await getCurrentMode();
|
||
console.log('当前模式:', currentMode);
|
||
|
||
if (currentMode !== 'Switch') {
|
||
const switched = await switchToMode('Switch Mode');
|
||
console.log('切换到Switch Mode:', switched);
|
||
await sleep(2000);
|
||
}
|
||
|
||
// Go back to homepage and re-check status
|
||
await driver.goBackToHomepage();
|
||
await sleep(2000);
|
||
statusBefore = await bot.getBotStatus();
|
||
console.log('切换后状态:', statusBefore);
|
||
|
||
if (statusBefore === 'unknown') {
|
||
reporter.record(`${CTRL} 不加密开/关`, 'SKIP', Date.now() - start, '切换Switch Mode后仍无法识别状态');
|
||
return;
|
||
}
|
||
}
|
||
|
||
await tapBotAndWaitPopup();
|
||
|
||
if (statusBefore === 'off') {
|
||
const onId = await driver.findElement(BOT_LOCATORS.onButton);
|
||
expect(onId).not.toBeNull();
|
||
await driver.tapElement(onId!);
|
||
} else {
|
||
const offId = await driver.findElement(BOT_LOCATORS.offButton);
|
||
expect(offId).not.toBeNull();
|
||
await driver.tapElement(offId!);
|
||
}
|
||
|
||
// Wait for BLE command to complete, then go back to homepage to read updated card status
|
||
await sleep(5000);
|
||
await driver.goBackToHomepage();
|
||
await sleep(2000);
|
||
|
||
const statusAfter = await bot.getBotStatus();
|
||
console.log('操作后:', statusAfter);
|
||
expect(statusAfter).not.toBe('unknown');
|
||
expect(statusAfter).not.toBe(statusBefore);
|
||
|
||
const detail = `${statusBefore} → ${statusAfter}`;
|
||
reporter.record(`${CTRL} 不加密开/关`, 'PASS', Date.now() - start, detail);
|
||
|
||
// Restore state
|
||
await tapBotAndWaitPopup();
|
||
if (statusBefore === 'off') {
|
||
const offId = await driver.findElement(BOT_LOCATORS.offButton);
|
||
if (offId) await driver.tapElement(offId);
|
||
} else {
|
||
const onId = await driver.findElement(BOT_LOCATORS.onButton);
|
||
if (onId) await driver.tapElement(onId);
|
||
}
|
||
await sleep(5000);
|
||
} catch (e: any) {
|
||
const ss = await captureScreenshot();
|
||
reporter.record(`${CTRL} 不加密开/关`, 'FAIL', Date.now() - start, e.message, ss);
|
||
throw e;
|
||
}
|
||
});
|
||
|
||
it('设置页 - 验证所有菜单项', async () => {
|
||
const start = Date.now();
|
||
try {
|
||
await tapBotAndWaitPopup();
|
||
const settingsId = await driver.findElement(BOT_LOCATORS.settingsButton);
|
||
expect(settingsId).not.toBeNull();
|
||
await driver.tapElement(settingsId!);
|
||
await sleep(2000);
|
||
|
||
const items = ['modeItem', 'passcodeItem', 'schedulesItem', 'logsItem', 'nfcItem'] as const;
|
||
const found: string[] = [];
|
||
const missing: string[] = [];
|
||
|
||
for (const key of items) {
|
||
const id = await driver.findElement(BOT_LOCATORS[key]);
|
||
if (id) found.push(BOT_LOCATORS[key].name);
|
||
else missing.push(BOT_LOCATORS[key].name);
|
||
}
|
||
|
||
await driver.scrollDown(400);
|
||
await sleep(1000);
|
||
|
||
const bottomItems = ['firmwareItem', 'deviceInfoItem', 'deleteItem'] as const;
|
||
for (const key of bottomItems) {
|
||
const id = await driver.findElement(BOT_LOCATORS[key]);
|
||
if (id) found.push(BOT_LOCATORS[key].name);
|
||
else missing.push(BOT_LOCATORS[key].name);
|
||
}
|
||
|
||
const detail = `找到 ${found.length}/${found.length + missing.length} 项`;
|
||
console.log(`${detail}: ${found.join(', ')}`);
|
||
expect(found.length).toBeGreaterThanOrEqual(6);
|
||
reporter.record('设置页菜单项验证', 'PASS', Date.now() - start, detail);
|
||
} catch (e: any) {
|
||
const ss = await captureScreenshot();
|
||
reporter.record('设置页菜单项验证', 'FAIL', Date.now() - start, e.message, ss);
|
||
throw e;
|
||
}
|
||
});
|
||
|
||
// ==================== 加密相关 ====================
|
||
|
||
async function enterSettings(): Promise<void> {
|
||
await tapBotAndWaitPopup();
|
||
if (driver.platform === 'ios') {
|
||
const settingsId = await driver.findElement(BOT_LOCATORS.settingsButton);
|
||
if (!settingsId) throw new Error('Settings按钮未找到');
|
||
await driver.tapElement(settingsId);
|
||
await sleep(1500);
|
||
}
|
||
}
|
||
|
||
async function scrollToAndTap(name: string): Promise<boolean> {
|
||
if (driver.platform === 'android') {
|
||
const el = await driver.findElementRaw('-android uiautomator',
|
||
`new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().text("${name}"))`);
|
||
if (!el) return false;
|
||
await driver.tapElement(el);
|
||
return true;
|
||
}
|
||
let el = await driver.findElementRaw('name', name);
|
||
if (el) {
|
||
const rect = await driver.getElementRect(el);
|
||
if (rect.y > 750) {
|
||
await driver.scrollDown(300);
|
||
await sleep(500);
|
||
el = await driver.findElementRaw('name', name);
|
||
}
|
||
} else {
|
||
await driver.scrollDown(300);
|
||
await sleep(500);
|
||
el = await driver.findElementRaw('name', name);
|
||
}
|
||
if (!el) return false;
|
||
const rect = await driver.getElementRect(el);
|
||
await driver.tap(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||
return true;
|
||
}
|
||
|
||
it('设置加密密码', async () => {
|
||
const start = Date.now();
|
||
try {
|
||
await enterSettings();
|
||
|
||
const tapped = await scrollToAndTap('Passcode');
|
||
expect(tapped).toBe(true);
|
||
await sleep(2000);
|
||
|
||
// On Android, may need to dismiss existing password dialog first
|
||
await dismissPasswordDialogIfPresent();
|
||
|
||
// Check if password already set (Delete visible) — if so, delete first
|
||
let deleteEl = await driver.findElementRaw('name', 'Delete');
|
||
if (deleteEl) {
|
||
await driver.tapElement(deleteEl);
|
||
await sleep(1500);
|
||
const okEl = await driver.findElementRaw('name', 'OK') || await driver.findElementRaw('name', 'Confirm') || await driver.findElementRaw('name', 'Done');
|
||
if (okEl) await driver.tapElement(okEl);
|
||
await sleep(2000);
|
||
}
|
||
|
||
if (driver.platform === 'android') {
|
||
// Android: tap passwordItemView to open set password dialog
|
||
const pwdItem = await driver.findElementRaw('-android uiautomator',
|
||
'new UiSelector().resourceId("com.theswitchbot.switchbot:id/passwordItemView")');
|
||
if (pwdItem) {
|
||
await driver.tapElement(pwdItem);
|
||
await sleep(2000);
|
||
}
|
||
} else {
|
||
// iOS: tap "Set Password" or "Set Passcode"
|
||
const setEl = await driver.findElementRaw('name', 'Set Password') || await driver.findElementRaw('name', 'Set Passcode');
|
||
if (setEl) {
|
||
await driver.tapElement(setEl);
|
||
await sleep(2000);
|
||
}
|
||
}
|
||
|
||
// Input password via text fields
|
||
const editFields = await driver.findElementsRaw('class name', driver.platform === 'android' ? 'android.widget.EditText' : 'XCUIElementTypeTextField');
|
||
const secureFields = driver.platform === 'ios' ? await driver.findElementsRaw('class name', 'XCUIElementTypeSecureTextField') : [];
|
||
const fields = editFields.length > 0 ? editFields : secureFields;
|
||
|
||
if (fields.length >= 2) {
|
||
await driver.typeText(fields[0], '1234');
|
||
await sleep(500);
|
||
await driver.typeText(fields[1], '1234');
|
||
await sleep(500);
|
||
} else if (fields.length === 1) {
|
||
await driver.typeText(fields[0], '1234');
|
||
await sleep(500);
|
||
}
|
||
|
||
// Tap OK/Confirm
|
||
const confirmEl = await driver.findElementRaw('name', 'OK') || await driver.findElementRaw('name', 'Confirm');
|
||
if (confirmEl) {
|
||
await driver.tapElement(confirmEl);
|
||
await sleep(3000);
|
||
}
|
||
|
||
// Verify password is set
|
||
let source = await driver.getSource();
|
||
const isSet = source.includes('Delete') || source.includes('Change Password') || source.includes('****') || !source.includes('Not set');
|
||
console.log('密码设置结果:', isSet ? '已设置' : '未设置');
|
||
expect(isSet).toBe(true);
|
||
|
||
reporter.record('设置加密密码', 'PASS', Date.now() - start, `密码1234设置=${isSet}`);
|
||
} catch (e: any) {
|
||
const ss = await captureScreenshot();
|
||
reporter.record('设置加密密码', 'FAIL', Date.now() - start, e.message, ss);
|
||
throw e;
|
||
}
|
||
});
|
||
|
||
it('加密Bot-切换为Press模式', async () => {
|
||
const start = Date.now();
|
||
try {
|
||
await sleep(1000);
|
||
const botId = await findBot();
|
||
|
||
let source = await driver.getSource();
|
||
if (source.includes('Press Mode')) {
|
||
console.log('当前已是Press模式');
|
||
reporter.record('加密-切换Press', 'PASS', Date.now() - start, '当前已是Press Mode');
|
||
return;
|
||
}
|
||
|
||
await driver.tapElement(botId);
|
||
await sleep(1000);
|
||
const settingsId = await driver.findElement(BOT_LOCATORS.settingsButton);
|
||
if (!settingsId) throw new Error('Settings按钮未找到');
|
||
await driver.tapElement(settingsId);
|
||
await sleep(1500);
|
||
|
||
const modeEl = await driver.findElementRaw('name', 'Mode');
|
||
expect(modeEl).not.toBeNull();
|
||
await driver.tapElement(modeEl!);
|
||
await sleep(2000);
|
||
|
||
const switched = await switchToMode('Press Mode');
|
||
expect(switched).toBe(true);
|
||
await sleep(3000);
|
||
|
||
source = await driver.getSource();
|
||
const isPress = source.includes('Press Mode');
|
||
console.log('加密后模式:', isPress ? 'Press Mode' : 'other');
|
||
|
||
reporter.record('加密-切换Press', 'PASS', Date.now() - start, `Press Mode=${isPress}`);
|
||
} catch (e: any) {
|
||
const ss = await captureScreenshot();
|
||
reporter.record('加密-切换Press', 'FAIL', Date.now() - start, e.message, ss);
|
||
throw e;
|
||
}
|
||
});
|
||
|
||
it('加密Bot-按压操作', async () => {
|
||
const start = Date.now();
|
||
try {
|
||
const botId = await findBot();
|
||
const rect = await driver.getElementRect(botId);
|
||
|
||
// Tap button area on card
|
||
await driver.tap(rect.x + rect.width - 30, rect.y + rect.height / 2);
|
||
await sleep(2000);
|
||
|
||
// Check if passcode input appears
|
||
let source = await driver.getSource();
|
||
if (source.includes('Passcode') || source.includes('Password') || source.includes('Enter')) {
|
||
// Try text field input
|
||
const textFields = await driver.findElementsRaw('class name', 'XCUIElementTypeTextField');
|
||
const secureFields = await driver.findElementsRaw('class name', 'XCUIElementTypeSecureTextField');
|
||
const field = textFields[0] || secureFields[0];
|
||
if (field) {
|
||
await driver.typeText(field, '1234');
|
||
await sleep(1000);
|
||
const confirmEl = await driver.findElementRaw('name', 'Confirm') || await driver.findElementRaw('name', 'OK');
|
||
if (confirmEl) await driver.tapElement(confirmEl);
|
||
}
|
||
await sleep(5000);
|
||
console.log('输入密码1234后执行按压');
|
||
} else {
|
||
await sleep(8000);
|
||
console.log('直接执行按压(无密码弹窗)');
|
||
}
|
||
|
||
source = await driver.getSource();
|
||
const stillPress = source.includes('Press Mode');
|
||
console.log('按压后状态:', stillPress ? 'Press Mode' : '已执行');
|
||
|
||
reporter.record(`${CTRL} 加密按压`, 'PASS', Date.now() - start, `加密按压完成, Press=${stillPress}`);
|
||
} catch (e: any) {
|
||
const ss = await captureScreenshot();
|
||
reporter.record(`${CTRL} 加密按压`, 'FAIL', Date.now() - start, e.message, ss);
|
||
throw e;
|
||
}
|
||
});
|
||
|
||
it('删除加密密码', async () => {
|
||
const start = Date.now();
|
||
try {
|
||
await enterSettings();
|
||
|
||
const tapped = await scrollToAndTap('Passcode');
|
||
expect(tapped).toBe(true);
|
||
await sleep(2000);
|
||
|
||
// On Android, entering Passcode page may require password
|
||
await dismissPasswordDialogIfPresent();
|
||
await sleep(1000);
|
||
|
||
// Check if password is set (Delete/Clear button visible)
|
||
let deleteEl = await driver.findElementRaw('name', 'Delete');
|
||
if (!deleteEl && driver.platform === 'android') {
|
||
deleteEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("Clear")');
|
||
if (!deleteEl) {
|
||
await driver.scrollDown(200);
|
||
await sleep(500);
|
||
deleteEl = await driver.findElementRaw('name', 'Delete');
|
||
}
|
||
}
|
||
|
||
if (deleteEl) {
|
||
await driver.tapElement(deleteEl);
|
||
await sleep(2000);
|
||
|
||
// Confirmation dialog
|
||
const confirmButtons = ['OK', 'Confirm', 'Delete', 'Done'];
|
||
for (const btn of confirmButtons) {
|
||
const el = await driver.findElementRaw('name', btn);
|
||
if (el) { await driver.tapElement(el); await sleep(3000); break; }
|
||
}
|
||
} else {
|
||
console.log('Delete按钮未找到,密码可能未设置');
|
||
}
|
||
|
||
await sleep(1000);
|
||
const source = await driver.getSource();
|
||
const isDeleted = source.includes('Not set') || source.includes('Set Password') ||
|
||
source.includes('Set Passcode') || source.includes('Passcode') ||
|
||
!source.includes('Delete');
|
||
console.log('密码删除:', isDeleted ? '成功' : '未确认');
|
||
expect(isDeleted).toBe(true);
|
||
|
||
reporter.record('删除加密密码', 'PASS', Date.now() - start, `密码删除, Not set=${isDeleted}`);
|
||
} catch (e: any) {
|
||
const ss = await captureScreenshot();
|
||
reporter.record('删除加密密码', 'FAIL', Date.now() - start, e.message, ss);
|
||
throw e;
|
||
}
|
||
});
|
||
});
|