mirror of
https://github.com/appium/appium.git
synced 2026-10-28 04:14:00 +08:00
130 lines
3.9 KiB
JavaScript
130 lines
3.9 KiB
JavaScript
import _ from 'lodash';
|
|
import {errors} from 'appium/driver';
|
|
import {util} from '@appium/support';
|
|
import {BasePlugin} from 'appium/plugin';
|
|
import {compareImages} from './compare';
|
|
import ImageElementFinder from './finder';
|
|
import {ImageElement} from './image-element';
|
|
import {IMAGE_STRATEGY, IMAGE_ELEMENT_PREFIX} from './constants';
|
|
|
|
function getImgElFromArgs(args) {
|
|
return args.find((arg) => _.isString(arg) && arg.startsWith(IMAGE_ELEMENT_PREFIX));
|
|
}
|
|
|
|
export default class ImageElementPlugin extends BasePlugin {
|
|
constructor(pluginName) {
|
|
super(pluginName);
|
|
this.finder = new ImageElementFinder();
|
|
}
|
|
|
|
// this plugin supports a non-standard 'compare images' command
|
|
static newMethodMap = /** @type {const} */ ({
|
|
'/session/:sessionId/appium/compare_images': {
|
|
POST: {
|
|
command: 'compareImages',
|
|
payloadParams: {
|
|
required: ['mode', 'firstImage', 'secondImage'],
|
|
optional: ['options'],
|
|
},
|
|
neverProxy: true,
|
|
},
|
|
},
|
|
});
|
|
|
|
async compareImages(next, driver, ...args) {
|
|
// @ts-ignore Arguments should be ok there
|
|
return await compareImages(...args);
|
|
}
|
|
|
|
async findElement(next, driver, ...args) {
|
|
return await this._find(false, next, driver, ...args);
|
|
}
|
|
|
|
async findElements(next, driver, ...args) {
|
|
return await this._find(true, next, driver, ...args);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {boolean} multiple
|
|
* @param {*} next
|
|
* @param {*} driver
|
|
* @param {...any} args
|
|
* @returns {Promise<any>}
|
|
*/
|
|
async _find(multiple, next, driver, ...args) {
|
|
const [strategy, selector] = args;
|
|
|
|
// if we're not actually finding by image, just do the normal thing
|
|
if (strategy !== IMAGE_STRATEGY) {
|
|
return await next();
|
|
}
|
|
|
|
return await this.finder.findByImage(Buffer.from(selector, 'base64'), driver, {multiple});
|
|
}
|
|
|
|
async handle(next, driver, cmdName, ...args) {
|
|
// if we have a command that involves an image element id, attempt to find the image element
|
|
// and execute the command on it
|
|
const imgElId = getImgElFromArgs(args);
|
|
if (imgElId) {
|
|
const imgEl = this.finder.getImageElement(imgElId);
|
|
if (!imgEl) {
|
|
throw new errors.NoSuchElementError();
|
|
}
|
|
return await ImageElement.execute(driver, imgEl, cmdName, ...args);
|
|
}
|
|
|
|
if (cmdName === 'deleteSession') {
|
|
this.finder.clearImageElements();
|
|
}
|
|
|
|
// otherwise just do the normal thing
|
|
return await next();
|
|
}
|
|
|
|
async performActions(next, driver, ...args) {
|
|
// Replace with coordinates when ActionSequence includes image elements.
|
|
const [actionSequences] = /** @type {[import('@appium/types').ActionSequence[]]} */ (args);
|
|
for (const actionSequence of actionSequences) {
|
|
for (const action of actionSequence.actions) {
|
|
// The actions that can have an Element as the origin are "pointerMove" and "scroll".
|
|
if (
|
|
!_.isPlainObject(
|
|
/** @type {{origin?: "viewport" | "pointer" | import('@appium/types').Element}} */ (
|
|
action
|
|
).origin,
|
|
)
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
const actionWithEl =
|
|
/** @type {import('@appium/types').PointerMoveAction | import('@appium/types').ScrollAction} */ (
|
|
action
|
|
);
|
|
|
|
const elId = util.unwrapElement(/** @type {import('@appium/types').Element} */ (actionWithEl.origin));
|
|
if (!_.startsWith(elId, IMAGE_ELEMENT_PREFIX)) {
|
|
continue;
|
|
}
|
|
|
|
const imgEl = this.finder.getImageElement(elId);
|
|
if (!imgEl) {
|
|
throw new errors.NoSuchElementError();
|
|
}
|
|
|
|
// Add the element's center coordinates to the offset value.
|
|
actionWithEl.x += imgEl.center.x;
|
|
actionWithEl.y += imgEl.center.y;
|
|
// Set the origin to the viewport so that the external driver can process it using coordinates.
|
|
delete actionWithEl.origin;
|
|
}
|
|
}
|
|
|
|
return await next();
|
|
}
|
|
}
|
|
|
|
export {ImageElementPlugin, getImgElFromArgs, IMAGE_STRATEGY};
|