AI_UIAutomation/utils/common/navigation.helper.ts

147 lines
5.4 KiB
TypeScript

import { DeviceDriver } from '../../drivers/types';
import { sleep, waitForElement, waitForSource } from './element.helper';
export async function ensureHomeTab(driver: DeviceDriver): Promise<void> {
await driver.goBackToHomepage();
await sleep(1000);
if (driver.platform === 'android') {
try {
const homeTab = await driver.findElementRaw('accessibility id', 'Home');
if (homeTab) { await driver.tapElement(homeTab); await sleep(1000); }
} catch { /* element may be stale after navigation */ }
} else {
const homeTab = await driver.findElementRaw('predicate string', 'name BEGINSWITH "HomeScene"');
if (homeTab) { await driver.tapElement(homeTab); await sleep(1000); }
}
}
export async function navigateToAddPage(
driver: DeviceDriver,
type: 'Device' | 'Scene'
): Promise<boolean> {
await driver.dismissPopupIfPresent();
await ensureHomeTab(driver);
await driver.dismissPopupIfPresent();
if (driver.platform === 'android') {
const addBtn = await driver.findElementRaw('id', 'com.theswitchbot.switchbot:id/addBto');
if (!addBtn) { console.log('FAIL: addBto not found'); return false; }
await driver.tapElement(addBtn);
await sleep(1500);
const menuText = type === 'Device' ? 'Add Device' : 'Add Scene';
const menuEl = await driver.findElementRaw('-android uiautomator', `new UiSelector().text("${menuText}")`);
if (!menuEl) { console.log(`FAIL: no ${menuText} in menu`); return false; }
await driver.tapElement(menuEl);
await sleep(3000);
const src = await driver.getSource();
if (type === 'Device') return src.includes('Bot') || src.includes('Add Device');
return src.includes('Create Scene');
}
// iOS
const addBtn = await driver.findElementRaw('name', 'Add');
if (!addBtn) { console.log('FAIL: Add button not found'); return false; }
if (type === 'Scene') {
await driver.tapElement(addBtn);
await sleep(1500);
await driver.dismissPopupIfPresent();
const addSceneEl = await driver.findElementRaw('name', 'Add Scene');
if (!addSceneEl) { console.log('FAIL: no Add Scene'); return false; }
const rect = await driver.getElementRect(addSceneEl);
await driver.tap(rect.x + rect.width / 2, rect.y + rect.height / 2);
const found = await waitForElement(driver, 'predicate string', 'name CONTAINS "Create Scene"', 8000);
if (!found) { console.log('FAIL: Create Scene not loaded'); return false; }
await driver.dismissPopupIfPresent();
return true;
}
// iOS - Add Device
const addRect = await driver.getElementRect(addBtn);
for (let attempt = 0; attempt < 2; attempt++) {
await driver.tap(addRect.x + addRect.width / 2, addRect.y + addRect.height / 2);
await sleep(1500);
const addDevice = await driver.findElementRaw('name', 'Add Device');
if (addDevice) {
const rect = await driver.getElementRect(addDevice);
await driver.tap(rect.x + rect.width / 2, rect.y + rect.height / 2);
return await waitForSource(driver, 'Add Device', 5000);
}
}
console.log('FAIL: no Add Device in menu');
return false;
}
export async function navigateToManageScenes(driver: DeviceDriver): Promise<boolean> {
if (driver.platform === 'android') {
await ensureHomeTab(driver);
const moreBtn = await driver.findElementRaw('id', 'com.theswitchbot.switchbot:id/moreBto');
if (!moreBtn) { console.log('FAIL: moreBto not found'); return false; }
await driver.tapElement(moreBtn);
await sleep(1500);
const manageEl = await driver.findElementRaw('-android uiautomator', 'new UiSelector().text("Manage Scenes")');
if (!manageEl) { console.log('FAIL: no Manage Scenes'); return false; }
await driver.tapElement(manageEl);
await sleep(2000);
return true;
}
// iOS
await driver.tap(347, 48);
await sleep(1500);
const manageEl = await driver.findElementRaw('name', 'Manage Scenes');
if (!manageEl) { console.log('FAIL: no Manage Scenes'); return false; }
await driver.tapElement(manageEl);
await sleep(2000);
return true;
}
export async function navigateThroughWizard(
driver: DeviceDriver,
buttonNames = ['Use now', 'Start Using', 'Done', 'Got it', 'OK', 'Skip', 'Next'],
maxSteps = 10
): Promise<boolean> {
if (driver.platform === 'android') {
for (let i = 0; i < maxSteps; i++) {
await sleep(1000);
const src = await driver.getSource();
if (!src.includes('Add Bot') && !src.includes('Added successfully') && !src.includes('Install')) {
if (await driver.isOnHomepage()) return true;
}
let tapped = false;
for (const btn of buttonNames) {
try {
const el = await driver.findElementRaw('-android uiautomator', `new UiSelector().text("${btn}")`);
if (el) {
await driver.tapElement(el);
await sleep(2000);
tapped = true;
break;
}
} catch { /* stale element, continue */ }
}
if (!tapped) {
await driver.goBack();
await sleep(1000);
}
}
return await driver.isOnHomepage();
}
// iOS
for (let i = 0; i < maxSteps; i++) {
const source = await driver.getSource();
if (source.includes('XCUIElementTypeTabBar') && !source.includes('Add Bot')) return true;
let tapped = false;
for (const btn of buttonNames) {
const el = await driver.findElementRaw('name', btn);
if (el) { await driver.tapElement(el); await sleep(2000); tapped = true; break; }
}
if (!tapped) break;
}
return true;
}