UNPKG

@percy/appium-app

Version:

Appium client library for visual testing with Percy

249 lines (231 loc) 6.7 kB
const { GenericProvider } = require('./genericProvider'); const { TimeIt } = require('../util/timing'); const { Tile } = require('../util/tile'); const log = require('../util/log'); const utils = require('@percy/sdk-utils'); class AppAutomateProvider extends GenericProvider { constructor(driver) { super(driver); this._markedPercy = false; } static supports(driver) { return driver.remoteHostname.includes( process.env.AA_DOMAIN || 'browserstack' ); } async screenshot( name, { fullscreen, deviceName, orientation, statusBarHeight, navigationBarHeight, fullPage, screenLengths, ignoreRegionXpaths, ignoreRegionAccessibilityIds, ignoreRegionAppiumElements, customIgnoreRegions, considerRegionXpaths, considerRegionAccessibilityIds, considerRegionAppiumElements, customConsiderRegions, scrollableXpath, topScrollviewOffset, bottomScrollviewOffset, scrollableId, sync, testCase, labels, thTestCaseExecutionId, androidScrollAreaPercentage, scrollSpeed } = {} ) { let response = null; let error; sync = sync || null; try { let result = await this.percyScreenshotBegin(name); this.setDebugUrl(result); response = await super.screenshot(name, { fullscreen, deviceName: deviceName || result?.deviceName, osVersion: result?.osVersion?.split('.')[0], orientation, statusBarHeight, navigationBarHeight, fullPage, screenLengths, ignoreRegionXpaths, ignoreRegionAccessibilityIds, ignoreRegionAppiumElements, customIgnoreRegions, considerRegionXpaths, considerRegionAccessibilityIds, considerRegionAppiumElements, customConsiderRegions, scrollableXpath, topScrollviewOffset, bottomScrollviewOffset, scrollableId, sync, testCase, labels, thTestCaseExecutionId, androidScrollAreaPercentage, scrollSpeed }); } catch (e) { error = e; throw e; } finally { await this.percyScreenshotEnd( name, response?.body?.link, sync, `${error}` ); } return response; } async percyScreenshotBegin(name) { return await TimeIt.run('percyScreenshotBegin', async () => { try { let result = await this.browserstackExecutor('percyScreenshot', { name, percyBuildId: utils.percy?.build?.id, percyBuildUrl: utils.percy?.build?.url, state: 'begin' }); this._markedPercy = result.success; return result; } catch (e) { log.debug(`[${name}] Could not mark App Automate session as percy`); log.debug(`[${name}] ${e}`); return null; } }); } async percyScreenshotEnd( name, percyScreenshotUrl, sync, statusMessage = null ) { return await TimeIt.run('percyScreenshotEnd', async () => { try { await this.browserstackExecutor('percyScreenshot', { name, percyScreenshotUrl, status: percyScreenshotUrl ? 'success' : 'failure', statusMessage, sync, state: 'end' }); } catch (e) { log.debug(`[${name}] Could not mark App Automate session as percy`); } }); } // Override this for AA specific optimizations async getTiles( fullscreen, fullPage, screenLengths, scrollableXpath, topScrollviewOffset, bottomScrollviewOffset, scrollableId, androidScrollAreaPercentage, scrollSpeed ) { // Override AA optimizations if (this.isDisableRemoteUpload()) { if (fullPage === true) { log.warn( 'Full page screenshots are only supported when "PERCY_DISABLE_REMOTE_UPLOADS" is not set' ); } return await super.getTiles(fullscreen, fullPage, screenLengths); } let screenshotType = 'fullpage'; let projectId = 'percy-prod'; if (fullPage !== true) { screenshotType = 'singlepage'; } if (this.isPercyDev()) { projectId = 'percy-dev'; } // Take screenshots via browserstack executor const response = await TimeIt.run( 'percyScreenshot:screenshot', async () => { return await this.browserstackExecutor('percyScreenshot', { state: 'screenshot', percyBuildId: utils.percy?.build?.id, screenshotType, projectId, scaleFactor: await this.metadata.scaleFactor(), options: { numOfTiles: screenLengths || 4, deviceHeight: (await this.metadata.screenSize()).height, scollableXpath: scrollableXpath || null, topScrollviewOffset: topScrollviewOffset || 0, bottomScrollviewOffset: bottomScrollviewOffset || 0, scrollableId: scrollableId || null, FORCE_FULL_PAGE: process.env.FORCE_FULL_PAGE === 'true', androidScrollAreaPercentage: androidScrollAreaPercentage || null, scrollSpeed: scrollSpeed || null } }); } ); if (!response.success) { throw new Error( 'Failed to get screenshots from App Automate.' + ' Check dashboard for error.' ); } const tiles = []; const statBarHeight = await this.metadata.statusBarHeight(); const navBarHeight = await this.metadata.navigationBarHeight(); JSON.parse(response.result).forEach((tileData) => { tiles.push( new Tile({ statusBarHeight: statBarHeight, navBarHeight, fullscreen, headerHeight: tileData.header_height, footerHeight: tileData.footer_height, sha: tileData.sha.split('-')[0] // drop build id }) ); }); return tiles; } async browserstackExecutor(action, args) { let options = args ? { action, arguments: args } : { action }; return JSON.parse( await this.driver.execute( `browserstack_executor: ${JSON.stringify(options)}` ) ); } setDebugUrl(result) { if (!result) return null; const buildHash = result.buildHash; const sessionHash = result.sessionHash; this.debugUrl = `https://app-automate.browserstack.com/dashboard/v2/builds/${buildHash}/sessions/${sessionHash}`; } isDisableRemoteUpload() { return process.env.PERCY_DISABLE_REMOTE_UPLOADS === 'true'; } isPercyDev() { return process.env.PERCY_ENABLE_DEV === 'true'; } } module.exports = { AppAutomateProvider };