UNPKG

misoai-android

Version:

Appium-based Android automation library for misoAI

787 lines (777 loc) 21.3 kB
import { PageType, ElementTreeNode, Size, Point } from 'misoai-core'; import { ElementInfo } from 'misoai-shared/extractor'; import { AndroidDevicePage } from 'misoai-web'; import { PageAgent, PageAgentOpt } from 'misoai-web/agent'; export { overrideAIConfig } from 'misoai-shared/env'; /** * Appium server configuration options */ interface AppiumServerConfig { /** * Hostname of the Appium server */ hostname: string; /** * Port number of the Appium server */ port: number; /** * Path to the WebDriver endpoint (default: '/wd/hub') */ path?: string; /** * Protocol to use (default: 'http') */ protocol?: 'http' | 'https'; } /** * Base capabilities for Appium Android sessions */ interface AppiumBaseCapabilities { /** * Platform name (must be 'Android') */ platformName: 'Android'; /** * Automation name (e.g., 'UiAutomator2', 'Espresso') */ 'appium:automationName'?: string; /** * Android platform version */ 'appium:platformVersion'?: string; /** * Device name */ 'appium:deviceName'?: string; /** * Device UDID (unique device identifier) */ 'appium:udid'?: string; /** * Path or URL to APK file */ 'appium:app'?: string; /** * Package name of the Android app */ 'appium:appPackage'?: string; /** * Activity name to launch */ 'appium:appActivity'?: string; /** * Timeout for new commands in seconds */ 'appium:newCommandTimeout'?: number; /** * Automatically grant permissions to the app */ 'appium:autoGrantPermissions'?: boolean; /** * Other vendor-specific capabilities */ [key: string]: any; } /** * Sauce Labs specific options */ interface SauceLabsSpecificOptions { /** * Build identifier */ build?: string; /** * Test name */ name?: string; /** * Tags for the test */ tags?: string[]; /** * Tunnel identifier for Sauce Connect */ tunnelIdentifier?: string; /** * Appium version to use */ appiumVersion?: string; /** * Sauce Labs username */ username?: string; /** * Sauce Labs access key */ accessKey?: string; } /** * Sauce Labs capabilities */ interface SauceLabsCapabilities extends AppiumBaseCapabilities { /** * Sauce Labs specific options */ 'sauce:options'?: SauceLabsSpecificOptions; } /** * Sauce Labs configuration */ interface SauceLabsConfig { /** * Sauce Labs username */ user: string; /** * Sauce Labs access key */ key: string; /** * Sauce Labs region */ region: 'us-west-1' | 'eu-central-1' | 'us-east-1'; /** * Whether to use headless testing */ headless?: boolean; } /** * Implementation of AndroidDevicePage using Appium and WebdriverIO */ declare class AppiumDevice implements AndroidDevicePage { /** * Page type identifier */ pageType: PageType; /** * Current URI/URL of the device */ uri: string | undefined; /** * WebdriverIO browser instance */ private driver; /** * Appium server configuration */ private serverConfig; /** * Appium capabilities */ private capabilities; /** * Screen size cache */ private screenSize; /** * Creates a new AppiumDevice instance * * @param serverConfig - Appium server configuration * @param capabilities - Appium capabilities */ constructor(serverConfig: AppiumServerConfig, capabilities: AppiumBaseCapabilities); /** * Connects to the Appium server and starts a session */ connect(): Promise<WebdriverIO.Browser>; /** * Disconnects from the Appium server and ends the session */ disconnect(): Promise<void>; /** * Launches an app or opens a URL * * @param uri - App package, activity, or URL to launch */ launch(uri: string): Promise<AppiumDevice>; /** * Gets the WebdriverIO driver instance, connecting if necessary */ private getDriver; /** * Takes a screenshot and returns it as a base64-encoded string */ screenshotBase64(): Promise<string>; /** * Gets the element tree for the current screen * @returns Promise resolving to the element tree */ getElementsNodeTree(): Promise<ElementTreeNode<ElementInfo>>; /** * Gets the current URL */ url(): Promise<string>; /** * Gets the screen size */ size(): Promise<Size>; /** * Starts an activity * * @param appPackage - Package name * @param appActivity - Activity name * @param opts - Additional options */ startActivity(appPackage: string, appActivity: string, opts?: string): Promise<void>; /** * Opens a URL * * @param url - URL to open */ openUrl(url: string): Promise<void>; /** * Closes the current app */ closeApp(): Promise<void>; /** * Terminates an app * * @param appId - App package name */ terminateApp(appId: string): Promise<boolean>; /** * Installs an app * * @param appPath - Path to the app */ installApp(appPath: string): Promise<void>; /** * Checks if an app is installed * * @param appId - App package name */ isAppInstalled(appId: string): Promise<boolean>; /** * Removes an app * * @param appId - App package name */ removeApp(appId: string): Promise<void>; /** * Gets the current activity */ getCurrentActivity(): Promise<string>; /** * Gets the current package */ getCurrentPackage(): Promise<string>; /** * Gets the screen orientation */ getScreenOrientation(): Promise<'PORTRAIT' | 'LANDSCAPE'>; /** * Sets the screen orientation * * @param orientation - Orientation to set */ setScreenOrientation(orientation: 'PORTRAIT' | 'LANDSCAPE'): Promise<void>; /** * Gets the device time */ getDeviceTime(): Promise<string>; /** * Hides the keyboard */ hideKeyboard(): Promise<void>; /** * Checks if the keyboard is shown */ isKeyboardShown(): Promise<boolean>; /** * Presses a key code * * @param keycode - Key code to press * @param metastate - Meta state * @param flags - Flags */ pressKeyCode(keycode: number, metastate?: number, flags?: number): Promise<void>; /** * Long presses a key code * * @param keycode - Key code to press * @param metastate - Meta state * @param flags - Flags */ longPressKeyCode(keycode: number, metastate?: number, flags?: number): Promise<void>; /** * Gets available contexts */ getContexts(): Promise<string[]>; /** * Gets the current context */ getCurrentContext(): Promise<string>; /** * Switches to a context * * @param contextName - Context to switch to */ switchContext(contextName: string): Promise<void>; /** * Executes a script * * @param script - Script to execute * @param args - Arguments for the script */ executeScript(script: string, args?: any[]): Promise<any>; /** * Scrolls to the top of the screen * * @param startingPoint - Optional starting point for the scroll */ scrollUntilTop(startingPoint?: Point): Promise<void>; /** * Scrolls to the bottom of the screen * * @param startingPoint - Optional starting point for the scroll */ scrollUntilBottom(startingPoint?: Point): Promise<void>; /** * Scrolls to the left of the screen * * @param startingPoint - Optional starting point for the scroll */ scrollUntilLeft(startingPoint?: Point): Promise<void>; /** * Scrolls to the right of the screen * * @param startingPoint - Optional starting point for the scroll */ scrollUntilRight(startingPoint?: Point): Promise<void>; /** * Scrolls up by a specified distance * * @param distance - Distance to scroll (default: 200) * @param startingPoint - Optional starting point for the scroll */ scrollUp(distance?: number, startingPoint?: Point): Promise<void>; /** * Scrolls down by a specified distance * * @param distance - Distance to scroll (default: 200) * @param startingPoint - Optional starting point for the scroll */ scrollDown(distance?: number, startingPoint?: Point): Promise<void>; /** * Scrolls left by a specified distance * * @param distance - Distance to scroll (default: 200) * @param startingPoint - Optional starting point for the scroll */ scrollLeft(distance?: number, startingPoint?: Point): Promise<void>; /** * Scrolls right by a specified distance * * @param distance - Distance to scroll (default: 200) * @param startingPoint - Optional starting point for the scroll */ scrollRight(distance?: number, startingPoint?: Point): Promise<void>; /** * Performs a swipe gesture using W3C Actions API * * @param startX - Starting X coordinate * @param startY - Starting Y coordinate * @param endX - Ending X coordinate * @param endY - Ending Y coordinate * @param duration - Duration of the swipe in milliseconds (default: 800) */ swipe(startX: number, startY: number, endX: number, endY: number, duration?: number): Promise<void>; /** * Presses the back button */ back(): Promise<void>; /** * Presses the home button */ home(): Promise<void>; /** * Opens the recent apps screen */ recentApps(): Promise<void>; /** * Gets the elements info (deprecated, use getElementsNodeTree instead) */ getElementsInfo(): Promise<ElementInfo[]>; /** * Mouse actions */ get mouse(): { click: (x: number, y: number) => Promise<void>; wheel: (deltaX: number, deltaY: number) => Promise<void>; move: (x: number, y: number) => Promise<void>; drag: (from: { x: number; y: number; }, to: { x: number; y: number; }) => Promise<void>; }; /** * Keyboard actions using W3C Actions API */ get keyboard(): { type: (text: string) => Promise<void>; press: (action: { key: string; command?: string; } | { key: string; command?: string; }[]) => Promise<void>; }; /** * Clears input in an element * * @param element - Element to clear */ clearInput(element: ElementInfo): Promise<void>; /** * Performs a tap at the specified coordinates using W3C Actions API * * @param x - X coordinate * @param y - Y coordinate */ tap(x: number, y: number): Promise<void>; /** * Gets XPaths for elements with the specified ID * * @param id - Element ID to search for */ getXpathsById(id: string): Promise<string[]>; /** * Gets element info by XPath * * @param xpath - XPath to search for */ getElementInfoByXpath(xpath: string): Promise<ElementInfo>; /** * Helper method to determine node type from class name */ private getNodeTypeFromClassName; /** * Gets device information including screen size and orientation */ getDeviceInfo(): Promise<{ screenSize: Size; orientation: 'PORTRAIT' | 'LANDSCAPE'; deviceTime: string; currentPackage: string; currentActivity: string; }>; /** * Waits for an element to appear on screen * * @param selector - Element selector * @param timeout - Timeout in milliseconds (default: 10000) */ waitForElement(selector: string, timeout?: number): Promise<WebdriverIO.Element>; /** * Waits for an element to disappear from screen * * @param selector - Element selector * @param timeout - Timeout in milliseconds (default: 10000) */ waitForElementToDisappear(selector: string, timeout?: number): Promise<void>; /** * Performs a long press at the specified coordinates * * @param x - X coordinate * @param y - Y coordinate * @param duration - Duration of the long press in milliseconds (default: 1000) */ longPress(x: number, y: number, duration?: number): Promise<void>; /** * Performs a double tap at the specified coordinates * * @param x - X coordinate * @param y - Y coordinate */ doubleTap(x: number, y: number): Promise<void>; /** * Destroys the device connection */ destroy(): Promise<void>; } declare class AndroidAgent extends PageAgent<AppiumDevice> { constructor(page: AppiumDevice, opts?: PageAgentOpt); launch(uri: string): Promise<void>; } /** * Creates an AndroidAgent from an Appium server * * @param config - Appium server configuration * @param capabilities - Appium capabilities * @param agentOpts - Optional agent options * @returns Promise resolving to an AndroidAgent */ declare function agentFromAppiumServer(config: AppiumServerConfig, capabilities: AppiumBaseCapabilities, agentOpts?: PageAgentOpt): Promise<AndroidAgent>; /** * Creates an AndroidAgent from a local Appium server * * @param capabilities - Appium capabilities * @param agentOpts - Optional agent options * @returns Promise resolving to an AndroidAgent */ declare function agentFromLocalAppium(capabilities: AppiumBaseCapabilities, agentOpts?: PageAgentOpt): Promise<AndroidAgent>; /** * Creates an AndroidAgent from Sauce Labs * * @param slConfig - Sauce Labs configuration * @param capabilities - Appium capabilities with Sauce Labs options * @param agentOpts - Optional agent options * @returns Promise resolving to an AndroidAgent */ declare function agentFromSauceLabs(slConfig: SauceLabsConfig, capabilities: AppiumBaseCapabilities & SauceLabsCapabilities, agentOpts?: PageAgentOpt): Promise<AndroidAgent>; /** * Performance monitoring utilities for Android devices */ /** * Interface for CPU information */ interface CpuInfo { user: number; system: number; idle: number; total: number; } /** * Interface for memory information */ interface MemoryInfo { totalMem: number; freeMem: number; usedMem: number; usedMemPercent: number; } /** * Interface for battery information */ interface BatteryInfo { level: number; status: string; temperature: number; } /** * Interface for network information */ interface NetworkInfo { rxBytes: number; txBytes: number; rxPackets: number; txPackets: number; } /** * Interface for device information */ interface DeviceInfo { model: string; manufacturer: string; androidVersion: string; cpuArchitecture: string; cpuCores: number; totalRam: string; screenDensity: string; } /** * Interface for performance metrics */ interface PerformanceMetrics { timestamp: number; packageName: string; cpuInfo?: CpuInfo; memoryInfo?: MemoryInfo; batteryInfo?: BatteryInfo; networkInfo?: NetworkInfo; } /** * Performance monitor class for Android devices */ declare class PerformanceMonitor { private device; private defaultPackageName?; private metrics; private monitoringInterval; private availableMetrics; private lastActivePackage; /** * Creates a new PerformanceMonitor instance * * @param device - AppiumDevice instance * @param defaultPackageName - Optional default package name to use if active package detection fails */ constructor(device: AppiumDevice, defaultPackageName?: string); /** * Gets the currently active package name */ private getActivePackage; /** * Initializes the performance monitor */ initialize(): Promise<string[]>; /** * Gets device information */ getDeviceInfo(): Promise<DeviceInfo>; /** * Gets current performance metrics */ getCurrentMetrics(): Promise<PerformanceMetrics>; /** * Starts monitoring performance metrics at the specified interval * * @param intervalMs - Interval in milliseconds (default: 5000) */ startMonitoring(intervalMs?: number): void; /** * Stops monitoring performance metrics */ stopMonitoring(): void; /** * Gets all collected metrics */ getMetrics(): PerformanceMetrics[]; /** * Clears all collected metrics */ clearMetrics(): void; /** * Exports metrics to JSON string */ exportMetricsToJson(): string; /** * Exports metrics to a JSON file * * @param filePath - Path to save the JSON file */ exportMetricsToFile(filePath: string): Promise<void>; /** * Gets metrics for a specific package * * @param packageName - Package name to filter by */ getMetricsForPackage(packageName: string): PerformanceMetrics[]; /** * Gets metrics within a time range * * @param startTime - Start timestamp in milliseconds * @param endTime - End timestamp in milliseconds */ getMetricsInTimeRange(startTime: number, endTime: number): PerformanceMetrics[]; } /** * Media utility functions for Android automation * * This module provides helper functions for taking screenshots, recording video, * and other media-related operations on Android devices. */ /** * Options for taking a screenshot */ interface ScreenshotOptions { /** * File path where the screenshot should be saved * If not provided, the screenshot will only be returned as base64 */ filePath?: string; /** * Whether to create the directory if it doesn't exist * @default true */ createDir?: boolean; /** * Quality of the screenshot (1-100) * Only applicable when saving to a JPEG file * @default 90 */ quality?: number; /** * Whether to return the screenshot as base64 data * @default true */ returnBase64?: boolean; } /** * Options for recording video */ interface VideoRecordingOptions { /** * File path where the video should be saved */ filePath: string; /** * Whether to create the directory if it doesn't exist * @default true */ createDir?: boolean; /** * Maximum duration of the recording in seconds * @default 180 (3 minutes) */ timeLimit?: number; /** * Bit rate for the video in bits per second * @default 4000000 (4 Mbps) */ bitRate?: number; /** * Video size (width x height) in pixels * @default "1280x720" */ size?: string; } /** * Takes a screenshot of the current screen * * @param device - AppiumDevice instance * @param options - Screenshot options * @returns Promise resolving to the screenshot as base64 data (if returnBase64 is true) * * @example * ```typescript * // Take a screenshot and save it to a file * await takeScreenshot(device, { filePath: 'screenshots/home-screen.png' }); * * // Take a screenshot and get it as base64 data * const base64Screenshot = await takeScreenshot(device); * ``` */ declare function takeScreenshot(device: AppiumDevice, options?: ScreenshotOptions): Promise<string | void>; /** * Starts recording the screen * * @param device - AppiumDevice instance * @param options - Video recording options * @returns Promise resolving when recording has started * * @example * ```typescript * // Start recording video * await startVideoRecording(device, { * timeLimit: 60, // 1 minute * bitRate: 6000000 // 6 Mbps * }); * * // Perform some actions... * * // Stop recording and save the video * await stopVideoRecording(device, { filePath: 'videos/test-recording.mp4' }); * ``` */ declare function startVideoRecording(device: AppiumDevice, options?: Partial<VideoRecordingOptions>): Promise<void>; /** * Stops recording the screen and saves the video * * @param device - AppiumDevice instance * @param options - Video recording options * @returns Promise resolving to the video as base64 data * * @example * ```typescript * // Stop recording and save the video * await stopVideoRecording(device, { filePath: 'videos/test-recording.mp4' }); * ``` */ declare function stopVideoRecording(device: AppiumDevice, options: VideoRecordingOptions): Promise<string>; export { AndroidAgent, type AppiumBaseCapabilities, AppiumDevice, type AppiumServerConfig, type BatteryInfo, type CpuInfo, type DeviceInfo, type MemoryInfo, type NetworkInfo, type PerformanceMetrics, PerformanceMonitor, type SauceLabsCapabilities, type SauceLabsConfig, type SauceLabsSpecificOptions, type ScreenshotOptions, type VideoRecordingOptions, agentFromAppiumServer, agentFromLocalAppium, agentFromSauceLabs, startVideoRecording, stopVideoRecording, takeScreenshot };