appium-xcuitest-driver
Version:
Appium driver for iOS using XCUITest for backend
129 lines • 5.37 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getScreenshot = getScreenshot;
exports.getElementScreenshot = getElementScreenshot;
exports.getViewportScreenshot = getViewportScreenshot;
const asyncbox_1 = require("asyncbox");
const lodash_1 = __importDefault(require("lodash"));
const driver_1 = require("appium/driver");
const support_1 = require("appium/support");
/**
* Takes a screenshot of the current screen.
*
* @returns Base64-encoded screenshot data
*/
async function getScreenshot() {
if (this.isWebContext()) {
const webScreenshotMode = (await this.settings.getSettings()).webScreenshotMode;
switch (lodash_1.default.toLower(webScreenshotMode)) {
case 'page':
case 'viewport':
return await this.remote.captureScreenshot({
coordinateSystem: lodash_1.default.capitalize(webScreenshotMode),
});
case 'native':
case undefined:
case null:
break;
default:
this.log.warn(`The webScreenshotMode setting value '${webScreenshotMode}' is not known. ` +
`Supported values are: page, viewport and native. Falling back to the native mode.`);
break;
}
}
const getScreenshotFromWDA = async () => {
this.log.debug(`Taking screenshot with WDA`);
const data = await this.proxyCommand('/screenshot', 'GET');
if (!lodash_1.default.isString(data)) {
throw new Error(`Unable to take screenshot. WDA returned '${JSON.stringify(data)}'`);
}
return data;
};
// if we've specified an mjpeg server, use that
if (this.mjpegStream) {
this.log.info(`mjpeg video stream provided, returning latest frame as screenshot`);
const data = await this.mjpegStream.lastChunkPNGBase64();
if (data) {
return data;
}
this.log.warn('Tried to get screenshot from active MJPEG stream, but there ' +
'was no data yet. Falling back to regular screenshot methods.');
}
try {
return await getScreenshotFromWDA();
}
catch (err) {
this.log.warn(`Error getting screenshot: ${err.message}`);
}
// simulator attempt
if (this.isSimulator()) {
this.log.info(`Falling back to 'simctl io screenshot' API`);
const payload = await this.device.simctl.getScreenshot();
if (!payload) {
throw new driver_1.errors.UnableToCaptureScreen();
}
return payload;
}
// Retry for real devices only. Fail fast on Simulator if simctl does not work as expected
return await (0, asyncbox_1.retryInterval)(2, 1000, getScreenshotFromWDA);
}
/**
* Takes a screenshot of a specific element.
*
* @param el - Element to capture
* @returns Base64-encoded screenshot data
*/
async function getElementScreenshot(el) {
el = support_1.util.unwrapElement(el);
if (this.isWebContext()) {
const atomsElement = this.getAtomsElement(el);
const { width, height } = await this.executeAtom('get_size', [atomsElement]);
if (!width || !height) {
throw new driver_1.errors.UnableToCaptureScreen('Cannot take a screenshot of a zero-size element');
}
const { x, y } = await this.executeAtom('get_top_left_coordinates', [atomsElement]);
return await this.remote.captureScreenshot({ rect: { x, y, width, height } });
}
const data = await this.proxyCommand(`/element/${el}/screenshot`, 'GET');
if (!lodash_1.default.isString(data)) {
throw new driver_1.errors.UnableToCaptureScreen(`Unable to take an element screenshot. WDA returned: ${JSON.stringify(data)}`);
}
return data;
}
/**
* Takes a screenshot of the current viewport.
*
* @returns Base64-encoded screenshot data
*/
async function getViewportScreenshot() {
if (this.isWebContext()) {
return await this.remote.captureScreenshot();
}
const screenshot = await this.getScreenshot();
// if we don't have a status bar, there's nothing to crop, so we can avoid
// extra calls and return straight away
if ((await this.getStatusBarHeight()) === 0) {
return screenshot;
}
const sharp = support_1.imageUtil.requireSharp();
const { width, height } = await sharp(Buffer.from(screenshot, 'base64')).metadata();
if (!width || !height) {
throw new driver_1.errors.UnableToCaptureScreen('The device screenshot is empty');
}
this.log.debug(`Screenshot dimensions: ${width}x${height}`);
const region = await this.getViewportRect();
if (region.width + region.left > width) {
this.log.info('Viewport region exceeds screenshot width, adjusting region to fit');
region.width = width - region.left;
}
if (region.height + region.top > height) {
this.log.info('Viewport region exceeds screenshot height, adjusting region to fit');
region.height = height - region.top;
}
this.log.debug(`Calculated viewport rect: ${JSON.stringify(region)}`);
return await support_1.imageUtil.cropBase64Image(screenshot, region);
}
//# sourceMappingURL=screenshots.js.map