Files
appium/lib/basedriver/device-settings.js
T
Jonathan Lipps ec72948de2 add -image locator strategy and related logic (#235)
* add -image locator strategy and related logic

* use appium-support jimp helper

* handle find multiple elements by image

* update staleness check variable name

* ensure that a settings object always exists so we can rely on global settings always existing too

* only fix template size if user requests it in settings

* add note about implicit wait error handling

* only automatically update image element position if user turns on an appropriate setting

* add setting to control whether we check for image element staleness

* add setting to determine the image element tap strategy (w3c or mjsonwp)

* prefer single quotes

* add setting to turn off screenshot resizing if not desired

* add docstrings (except for cache class which we may not keep)

* address additional review comments

* add better jsdoc arg info

* use lru-cache npm package instead of rolling our own

* use new versino of appium-support

* make sure the lru cache is checking element size correctly

* give better names and tighten up logic around image el tap strategies

* add some unit tests for image elements

* ensure DeviceSettings has a default no-op update method

* check that driver implements action strategies and fall back / throw as appropriate

* finish out image element unit tests

* have basedriver set noop onSettingsUpdate rather than doing it in DeviceSettings

* move route avoidance detection from protocol to driver

* handle proxying actions to downstream drivers during image tap

* tighten up logic for deciding whether to proxy based on presence of image element

* add find by image specs and fix issues that arose in the process

* clean up regexes

* don't try to be smart and proxy actions for drivers; let them set it up themselves to support image elements

* change default match threshold based on experimentation

* export which settings are handled by basedriver so downstream drivers can utilize this information

* make sure to include a duration for the initial pointerMove action

* add docstring to proxyRouteIsAvoided
2018-07-30 13:17:54 -07:00

80 lines
2.8 KiB
JavaScript

import _ from 'lodash';
import log from './logger';
import { DEFAULT_MATCH_THRESHOLD } from './commands/images';
import { IMAGE_EL_TAP_STRATEGY_W3C } from './image-element';
const GLOBAL_DEFAULT_SETTINGS = {
// value between 0 and 1 representing match strength, below which an image
// element will not be found
imageMatchThreshold: DEFAULT_MATCH_THRESHOLD,
// if the image returned by getScreenshot differs in size or aspect ratio
// from the screen, attempt to fix it automatically
fixImageFindScreenshotDims: true,
// whether Appium should ensure that an image template sent in during image
// element find should have its size adjusted so the match algorithm will not
// complain
fixImageTemplateSize: false,
// whether Appium should re-check that an image element can be matched
// against the current screenshot before clicking it
checkForImageElementStaleness: true,
// whether before clicking on an image element Appium should re-determine the
// position of the element on screen
autoUpdateImageElementPosition: false,
// which method to use for tapping by coordinate for image elements. the
// options are 'w3c' or 'mjsonwp'
imageElementTapStrategy: IMAGE_EL_TAP_STRATEGY_W3C,
};
// declare settings that are really handled only by basedriver, so downstream
// drivers can choose to ignore them for their own settings validation, etc...
const BASEDRIVER_HANDLED_SETTINGS = [
'imageMatchThreshold',
'fixImageFindScreenshotDims',
'fixImageTemplateSize',
'checkForImageElementStaleness',
'autoUpdateImageElementPosition',
'imageElementTapStrategy',
];
class DeviceSettings {
constructor (defaultSettings = {}, onSettingsUpdate = null) {
this._settings = Object.assign({}, GLOBAL_DEFAULT_SETTINGS, defaultSettings);
this.onSettingsUpdate = onSettingsUpdate;
}
// calls updateSettings from implementing driver every time a setting is changed.
async update (newSettings) {
if (!_.isObject(newSettings)) {
throw new Error('Settings update should be called with valid JSON');
}
for (let prop of _.keys(newSettings)) {
if (_.isUndefined(this._settings[prop])) {
log.warn(`Didn't know about setting '${prop}'. Are you sure you ` +
`spelled it correctly? Proceeding anyway. Valid settings: ${_.keys(this._settings)}`);
}
if (this._settings[prop] !== newSettings[prop]) {
// update setting only when there is updateSettings defined.
if (this.onSettingsUpdate) {
await this.onSettingsUpdate(prop, newSettings[prop], this._settings[prop]);
this._settings[prop] = newSettings[prop];
} else {
log.errorAndThrow('Unable to update settings; onSettingsUpdate method not found');
}
}
}
}
getSettings () {
return this._settings;
}
}
export default DeviceSettings;
export { BASEDRIVER_HANDLED_SETTINGS };