UNPKG

appium-espresso-driver

Version:
85 lines (78 loc) 3.18 kB
import type {EspressoDriver} from '../driver.js'; import type {ScreenshotsInfo} from './types.js'; // Display 4619827259835644672 (HWC display 0): port=0 pnpId=GGL displayName="EMU_display_0" const DISPLAY_PATTERN = /^Display\s+(\d+)\s+\(.+display\s+(\d+)\).+displayName="([^"]*)/gm; /** * Retrieves screenshots of each display available to Android. * This functionality is only supported since Android 10. * * @param displayId - Optional Android display identifier to take a screenshot for. * If not provided then screenshots of all displays are going to be returned. * If provided but no matches were found then an error is thrown. * @returns Promise that resolves to a dictionary of display screenshots, where keys are display IDs * and values contain display information and base64-encoded PNG screenshot data * @throws {Error} If display information cannot be determined or if a provided displayId is not found */ export async function mobileScreenshots( this: EspressoDriver, displayId?: number | string, ): Promise<ScreenshotsInfo> { const displaysInfo = await this.adb.shell(['dumpsys', 'SurfaceFlinger', '--display-id']); const infos: Record<string, {id: string; isDefault: boolean; name: string}> = {}; let match; while ((match = DISPLAY_PATTERN.exec(displaysInfo))) { infos[match[1]] = { id: match[1], isDefault: match[2] === '0', name: match[3], }; } if (Object.keys(infos).length === 0) { this.log.debug(displaysInfo); throw new Error('Cannot determine the information about connected Android displays'); } this.log.info(`Parsed Android display infos: ${JSON.stringify(infos)}`); const toB64Screenshot = async (dispId: string): Promise<string> => (await this.adb.takeScreenshot(dispId)).toString('base64'); const displayIdStr = isNaN(Number(displayId)) ? null : `${displayId}`; if (displayIdStr) { if (!infos[displayIdStr]) { throw new Error( `The provided display identifier '${displayId}' is not known. ` + `Only the following displays have been detected: ${JSON.stringify(infos)}`, ); } return { [displayIdStr]: { ...infos[displayIdStr], payload: await toB64Screenshot(displayIdStr), }, }; } const allInfos = Object.values(infos); const screenshots = await Promise.all(allInfos.map(({id}) => toB64Screenshot(id))); const result: ScreenshotsInfo = {}; for (let i = 0; i < allInfos.length; i++) { const info = allInfos[i]; const payload = screenshots[i]; if (info && payload) { result[info.id] = { ...info, payload, }; } } return result; } /** * Return the base 64 encoded screenshot data. * This method is called only when `appium:nativeWebScreenshot` is enabled * to avoid proxying requests to the chromedriver. * Without `appium:nativeWebScreenshot` or disabled, espresso driver * proxies screenshot endpoint requests to the espresso server directly. * * @returns {Promise<string>} */ export async function getScreenshot(this: EspressoDriver): Promise<string> { return String(await this.espresso.jwproxy.command('/screenshot', 'GET')); }