import { DeviceDriver } from '../../drivers/types'; import { sleep, waitForElement, waitForSource } from './element.helper'; export async function ensureHomeTab(driver: DeviceDriver): Promise { 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 { 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 { 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 { 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; }