@appium/images-plugin 2.0.10 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/compare.d.ts +0 -4
- package/build/lib/compare.d.ts.map +1 -1
- package/build/lib/compare.js +12 -19
- package/build/lib/compare.js.map +1 -1
- package/build/lib/constants.d.ts +13 -0
- package/build/lib/constants.d.ts.map +1 -0
- package/build/lib/constants.js +59 -0
- package/build/lib/constants.js.map +1 -0
- package/build/lib/finder.d.ts +37 -48
- package/build/lib/finder.d.ts.map +1 -1
- package/build/lib/finder.js +167 -160
- package/build/lib/finder.js.map +1 -1
- package/build/lib/image-element.d.ts +60 -20
- package/build/lib/image-element.d.ts.map +1 -1
- package/build/lib/image-element.js +56 -34
- package/build/lib/image-element.js.map +1 -1
- package/build/lib/plugin.d.ts +3 -2
- package/build/lib/plugin.d.ts.map +1 -1
- package/build/lib/plugin.js +10 -12
- package/build/lib/plugin.js.map +1 -1
- package/lib/compare.js +6 -17
- package/lib/constants.js +70 -0
- package/lib/finder.js +186 -195
- package/lib/image-element.js +64 -31
- package/lib/plugin.js +10 -12
- package/package.json +4 -3
package/lib/image-element.js
CHANGED
|
@@ -2,14 +2,12 @@ import _ from 'lodash';
|
|
|
2
2
|
import {errors} from 'appium/driver';
|
|
3
3
|
import {util} from 'appium/support';
|
|
4
4
|
import log from './logger';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
IMAGE_STRATEGY, DEFAULT_SETTINGS, IMAGE_TAP_STRATEGIES,
|
|
7
|
+
IMAGE_ELEMENT_PREFIX, IMAGE_EL_TAP_STRATEGY_W3C,
|
|
8
|
+
} from './constants';
|
|
6
9
|
|
|
7
|
-
const IMAGE_ELEMENT_PREFIX = 'appium-image-element-';
|
|
8
10
|
const TAP_DURATION_MS = 125;
|
|
9
|
-
const IMAGE_EL_TAP_STRATEGY_W3C = 'w3cActions';
|
|
10
|
-
const IMAGE_EL_TAP_STRATEGY_MJSONWP = 'touchActions';
|
|
11
|
-
const IMAGE_TAP_STRATEGIES = [IMAGE_EL_TAP_STRATEGY_MJSONWP, IMAGE_EL_TAP_STRATEGY_W3C];
|
|
12
|
-
const DEFAULT_TEMPLATE_IMAGE_SCALE = 1.0;
|
|
13
11
|
|
|
14
12
|
/**
|
|
15
13
|
* @typedef Dimension
|
|
@@ -23,28 +21,41 @@ const DEFAULT_TEMPLATE_IMAGE_SCALE = 1.0;
|
|
|
23
21
|
* @property {number} y - y coordinate
|
|
24
22
|
*/
|
|
25
23
|
|
|
24
|
+
/**
|
|
25
|
+
* @typedef ImageElementOpts
|
|
26
|
+
* @property {Buffer} template - the image which was used to find this ImageElement
|
|
27
|
+
* @property {Rect} rect - bounds of matched image element
|
|
28
|
+
* @property {number} score The similarity score as a float number in range [0.0, 1.0].
|
|
29
|
+
* 1.0 is the highest score (means both images are totally equal).
|
|
30
|
+
* @property {Buffer?} match - the image which has matched marks. Defaults to null.
|
|
31
|
+
* @property {import('./finder').default?} finder - the finder we can use to re-check stale elements
|
|
32
|
+
* @property {import('@appium/types').Rect?} containerRect - The bounding
|
|
33
|
+
* rectangle to limit the search in
|
|
34
|
+
*/
|
|
35
|
+
|
|
26
36
|
/**
|
|
27
37
|
* Representation of an "image element", which is simply a set of coordinates
|
|
28
38
|
* and methods that can be used on that set of coordinates via the driver
|
|
29
39
|
*/
|
|
30
40
|
export default class ImageElement {
|
|
31
41
|
/**
|
|
32
|
-
* @param {
|
|
33
|
-
* find this ImageElement
|
|
34
|
-
* @param {Rect} rect - bounds of matched image element
|
|
35
|
-
* @param {number} score The similarity score as a float number in range [0.0, 1.0].
|
|
36
|
-
* 1.0 is the highest score (means both images are totally equal).
|
|
37
|
-
* @param {string?} b64Result - the base64-encoded image which has matched marks.
|
|
38
|
-
* Defaults to null.
|
|
39
|
-
* @param {import('./finder').default?} finder - the finder we can use to re-check stale elements
|
|
42
|
+
* @param {ImageElementOpts}
|
|
40
43
|
*/
|
|
41
|
-
constructor(
|
|
42
|
-
|
|
44
|
+
constructor({
|
|
45
|
+
template,
|
|
46
|
+
rect,
|
|
47
|
+
score,
|
|
48
|
+
match = null,
|
|
49
|
+
finder = null,
|
|
50
|
+
containerRect = null,
|
|
51
|
+
}) {
|
|
52
|
+
this.template = template;
|
|
43
53
|
this.rect = rect;
|
|
44
54
|
this.id = `${IMAGE_ELEMENT_PREFIX}${util.uuidV4()}`;
|
|
45
|
-
this.
|
|
55
|
+
this.match = match;
|
|
46
56
|
this.score = score;
|
|
47
57
|
this.finder = finder;
|
|
58
|
+
this.containerRect = containerRect;
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
/**
|
|
@@ -72,20 +83,25 @@ export default class ImageElement {
|
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
/**
|
|
75
|
-
* @returns {
|
|
86
|
+
* @returns {string} - the base64-encoded original image used for matching
|
|
87
|
+
*/
|
|
88
|
+
get originalImage() {
|
|
89
|
+
return this.template.toString('base64');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @returns {string|null} - the base64-encoded image which has matched marks
|
|
76
94
|
*/
|
|
77
95
|
get matchedImage() {
|
|
78
|
-
return this.
|
|
96
|
+
return this.match?.toString('base64') ?? null;
|
|
79
97
|
}
|
|
80
98
|
|
|
81
99
|
/**
|
|
82
|
-
* @param {string} protocolKey - the protocol-specific JSON key for
|
|
83
|
-
* a WebElement
|
|
84
100
|
*
|
|
85
101
|
* @returns {Element} - this image element as a WebElement
|
|
86
102
|
*/
|
|
87
|
-
asElement(
|
|
88
|
-
return
|
|
103
|
+
asElement() {
|
|
104
|
+
return util.wrapElement(this.id);
|
|
89
105
|
}
|
|
90
106
|
|
|
91
107
|
/**
|
|
@@ -132,11 +148,12 @@ export default class ImageElement {
|
|
|
132
148
|
if (checkForImageElementStaleness || updatePos) {
|
|
133
149
|
log.info('Checking image element for staleness before clicking');
|
|
134
150
|
try {
|
|
135
|
-
newImgEl = await this.finder.findByImage(this.template, {
|
|
151
|
+
newImgEl = await this.finder.findByImage(this.template, driver, {
|
|
136
152
|
shouldCheckStaleness: true,
|
|
137
153
|
// Set ignoreDefaultImageTemplateScale because this.template is device screenshot based image
|
|
138
154
|
// managed inside Appium after finidng image by template which managed by a user
|
|
139
155
|
ignoreDefaultImageTemplateScale: true,
|
|
156
|
+
containerRect: this.containerRect,
|
|
140
157
|
});
|
|
141
158
|
} catch (err) {
|
|
142
159
|
throw new errors.StaleElementReferenceError();
|
|
@@ -209,6 +226,22 @@ export default class ImageElement {
|
|
|
209
226
|
);
|
|
210
227
|
}
|
|
211
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Perform lookup of image element(s) inside of the current element
|
|
231
|
+
*
|
|
232
|
+
* @param {boolean} multiple - Whether to lookup multiple elements
|
|
233
|
+
* @param {import('appium/driver').BaseDriver} driver - The driver to use for commands
|
|
234
|
+
* @param {string[]} args = Rest of arguments for executeScripts
|
|
235
|
+
* @returns {Promise<Element|Element[]|ImageElement>} - WebDriver element with a special id prefix
|
|
236
|
+
*/
|
|
237
|
+
async find(multiple, driver, ...args) {
|
|
238
|
+
const [strategy, selector] = args;
|
|
239
|
+
if (strategy !== IMAGE_STRATEGY) {
|
|
240
|
+
throw new errors.InvalidSelectorError(`Lookup strategies other than '${IMAGE_STRATEGY}' are not supported`);
|
|
241
|
+
}
|
|
242
|
+
return await this.finder.findByImage(selector, driver, {multiple, containerRect: this.rect});
|
|
243
|
+
}
|
|
244
|
+
|
|
212
245
|
/**
|
|
213
246
|
* Handle various Appium commands that involve an image element
|
|
214
247
|
*
|
|
@@ -223,6 +256,10 @@ export default class ImageElement {
|
|
|
223
256
|
switch (cmd) {
|
|
224
257
|
case 'click':
|
|
225
258
|
return await imgEl.click(driver);
|
|
259
|
+
case 'findElementFromElement':
|
|
260
|
+
return await imgEl.find(false, driver, ...args);
|
|
261
|
+
case 'findElementsFromElement':
|
|
262
|
+
return await imgEl.find(true, driver, ...args);
|
|
226
263
|
case 'elementDisplayed':
|
|
227
264
|
return true;
|
|
228
265
|
case 'getSize':
|
|
@@ -232,6 +269,8 @@ export default class ImageElement {
|
|
|
232
269
|
return imgEl.location;
|
|
233
270
|
case 'getElementRect':
|
|
234
271
|
return imgEl.rect;
|
|
272
|
+
case 'getElementScreenshot':
|
|
273
|
+
return imgEl.originalImage;
|
|
235
274
|
case 'getAttribute':
|
|
236
275
|
// /session/:sessionId/element/:elementId/attribute/:name
|
|
237
276
|
// /session/:sessionId/element/:elementId/attribute/visual should retun the visual data
|
|
@@ -250,13 +289,7 @@ export default class ImageElement {
|
|
|
250
289
|
}
|
|
251
290
|
}
|
|
252
291
|
|
|
253
|
-
export {
|
|
254
|
-
ImageElement,
|
|
255
|
-
IMAGE_EL_TAP_STRATEGY_MJSONWP,
|
|
256
|
-
IMAGE_EL_TAP_STRATEGY_W3C,
|
|
257
|
-
DEFAULT_TEMPLATE_IMAGE_SCALE,
|
|
258
|
-
IMAGE_ELEMENT_PREFIX,
|
|
259
|
-
};
|
|
292
|
+
export {ImageElement};
|
|
260
293
|
|
|
261
294
|
/**
|
|
262
295
|
* @typedef {import('@appium/types').Rect} Rect
|
package/lib/plugin.js
CHANGED
|
@@ -5,16 +5,11 @@ import {errors} from 'appium/driver';
|
|
|
5
5
|
import BasePlugin from 'appium/plugin';
|
|
6
6
|
import {compareImages} from './compare';
|
|
7
7
|
import ImageElementFinder from './finder';
|
|
8
|
-
import {ImageElement
|
|
9
|
-
|
|
10
|
-
const IMAGE_STRATEGY = '-image';
|
|
8
|
+
import {ImageElement} from './image-element';
|
|
9
|
+
import {IMAGE_STRATEGY, IMAGE_ELEMENT_PREFIX} from './constants';
|
|
11
10
|
|
|
12
11
|
function getImgElFromArgs(args) {
|
|
13
|
-
|
|
14
|
-
if (_.isString(arg) && arg.startsWith(IMAGE_ELEMENT_PREFIX)) {
|
|
15
|
-
return arg;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
12
|
+
return args.find((arg) => _.isString(arg) && arg.startsWith(IMAGE_ELEMENT_PREFIX));
|
|
18
13
|
}
|
|
19
14
|
|
|
20
15
|
export default class ImageElementPlugin extends BasePlugin {
|
|
@@ -57,8 +52,7 @@ export default class ImageElementPlugin extends BasePlugin {
|
|
|
57
52
|
return await next();
|
|
58
53
|
}
|
|
59
54
|
|
|
60
|
-
this.finder.
|
|
61
|
-
return await this.finder.findByImage(selector, {multiple});
|
|
55
|
+
return await this.finder.findByImage(selector, driver, {multiple});
|
|
62
56
|
}
|
|
63
57
|
|
|
64
58
|
async handle(next, driver, cmdName, ...args) {
|
|
@@ -66,13 +60,17 @@ export default class ImageElementPlugin extends BasePlugin {
|
|
|
66
60
|
// and execute the command on it
|
|
67
61
|
const imgElId = getImgElFromArgs(args);
|
|
68
62
|
if (imgElId) {
|
|
69
|
-
|
|
63
|
+
const imgEl = this.finder.getImageElement(imgElId);
|
|
64
|
+
if (!imgEl) {
|
|
70
65
|
throw new errors.NoSuchElementError();
|
|
71
66
|
}
|
|
72
|
-
const imgEl = this.finder.imgElCache.get(imgElId);
|
|
73
67
|
return await ImageElement.execute(driver, imgEl, cmdName, ...args);
|
|
74
68
|
}
|
|
75
69
|
|
|
70
|
+
if (cmdName === 'deleteSession') {
|
|
71
|
+
this.finder.clearImageElements();
|
|
72
|
+
}
|
|
73
|
+
|
|
76
74
|
// otherwise just do the normal thing
|
|
77
75
|
return await next();
|
|
78
76
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appium/images-plugin",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Plugin for working with images and image elements in Appium",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -39,9 +39,10 @@
|
|
|
39
39
|
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@appium/opencv": "^2.0
|
|
42
|
+
"@appium/opencv": "^2.1.0",
|
|
43
43
|
"lodash": "4.17.21",
|
|
44
44
|
"lru-cache": "7.18.3",
|
|
45
|
+
"sharp": "0.32.1",
|
|
45
46
|
"source-map-support": "0.5.21"
|
|
46
47
|
},
|
|
47
48
|
"peerDependencies": {
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
"publishConfig": {
|
|
59
60
|
"access": "public"
|
|
60
61
|
},
|
|
61
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "6b245534c213f3b8d6405515aee1e89133295098",
|
|
62
63
|
"typedoc": {
|
|
63
64
|
"entryPoint": "./lib/plugin.js"
|
|
64
65
|
}
|