@applitools/screenshoter 3.3.26 → 3.4.2
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/screenshoter",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.2",
|
|
4
4
|
"description": "Applitools universal screenshoter for web and native applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"applitools",
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
"name": "Applitools Team",
|
|
26
26
|
"email": "team@applitools.com"
|
|
27
27
|
},
|
|
28
|
+
"aliases": [
|
|
29
|
+
"screenshoter"
|
|
30
|
+
],
|
|
28
31
|
"exports": {
|
|
29
32
|
".": {
|
|
30
33
|
"default": "./index.js"
|
|
@@ -67,18 +70,18 @@
|
|
|
67
70
|
}
|
|
68
71
|
},
|
|
69
72
|
"dependencies": {
|
|
70
|
-
"@applitools/logger": "1.1.
|
|
71
|
-
"@applitools/snippets": "2.
|
|
72
|
-
"@applitools/utils": "1.3.
|
|
73
|
+
"@applitools/logger": "1.1.11",
|
|
74
|
+
"@applitools/snippets": "2.4.1",
|
|
75
|
+
"@applitools/utils": "1.3.7",
|
|
73
76
|
"jpeg-js": "0.4.3",
|
|
74
77
|
"png-async": "0.9.4"
|
|
75
78
|
},
|
|
76
79
|
"devDependencies": {
|
|
77
|
-
"@applitools/bongo": "^2.1.
|
|
78
|
-
"@applitools/driver": "^1.
|
|
80
|
+
"@applitools/bongo": "^2.1.5",
|
|
81
|
+
"@applitools/driver": "^1.9.3",
|
|
79
82
|
"@applitools/scripts": "1.1.0",
|
|
80
|
-
"@applitools/spec-driver-webdriverio": "1.2.
|
|
81
|
-
"@applitools/test-utils": "1.3.
|
|
83
|
+
"@applitools/spec-driver-webdriverio": "1.2.11",
|
|
84
|
+
"@applitools/test-utils": "1.3.3",
|
|
82
85
|
"appium": "^1.22.3",
|
|
83
86
|
"chromedriver": "^101.0.0",
|
|
84
87
|
"eslint": "^8.16.0",
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
function findImagePattern(image, pattern) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
const patterOffset = Math.round(pattern.offset * pattern.scale)
|
|
3
|
+
const patternItemSize = Math.round(pattern.size * pattern.scale)
|
|
4
|
+
for (let x = patterOffset; x <= image.width - patterOffset - pattern.mask.length * patternItemSize; ++x) {
|
|
5
|
+
for (let y = patterOffset; y <= image.height - patterOffset; ++y) {
|
|
6
|
+
const pixel = y * image.width + x
|
|
7
|
+
if (isPattern(image, pixel, pattern)) return {x: x - patterOffset, y: y - patterOffset}
|
|
6
8
|
}
|
|
7
9
|
}
|
|
8
10
|
return null
|
|
@@ -11,29 +13,31 @@ function findImagePattern(image, pattern) {
|
|
|
11
13
|
function isPattern(image, offset, pattern) {
|
|
12
14
|
const length = Math.round(pattern.size * pattern.scale)
|
|
13
15
|
for (const [index, color] of pattern.mask.entries()) {
|
|
14
|
-
const maxLength = index * pattern.size * pattern.scale // how many pixels actually could be occupied at this point
|
|
16
|
+
const maxLength = (index + 1) * pattern.size * pattern.scale // how many pixels actually could be occupied at this point
|
|
15
17
|
const missedPixels = Math.abs(maxLength - Math.round(maxLength)) // how many pixels were missed due to rounding
|
|
16
18
|
const skippedPixels = missedPixels >= 0.25 ? Math.ceil(missedPixels) : 0 // how many pixels should be skipped from checking in pattern (usually 1 or 0)
|
|
17
19
|
for (let pixel = index * length; pixel < (index + 1) * length - skippedPixels; ++pixel) {
|
|
18
|
-
const pixelColor = pixelColorAt(image, offset + pixel)
|
|
20
|
+
const pixelColor = pixelColorAt(image, offset + pixel, length)
|
|
19
21
|
if (pixelColor !== color) return false
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
return true
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
function pixelColorAt(image,
|
|
27
|
+
function pixelColorAt(image, pixel) {
|
|
26
28
|
const channels = 4
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
for (let offset = 0; offset <= 3; ++offset) {
|
|
30
|
+
const r = image.data[(pixel - offset) * channels]
|
|
31
|
+
const g = image.data[(pixel - offset) * channels + 1]
|
|
32
|
+
const b = image.data[(pixel - offset) * channels + 2]
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
// if luminance is between black and white check the color of previous pixel
|
|
37
|
+
if (offset < 3 && luminance >= 112 && luminance <= 144) continue
|
|
38
|
+
|
|
39
|
+
return luminance < 128 ? /* black */ 1 : /* white*/ 0
|
|
40
|
+
}
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
module.exports = findImagePattern
|
package/src/get-target.js
CHANGED
|
@@ -32,7 +32,9 @@ async function getTarget({window, context, region, fully, scrollingMode, logger}
|
|
|
32
32
|
// if element is in a native context, then scroll it to the top, otherwise, it will be not possible to get all of its size
|
|
33
33
|
const scrollingElement = await elementContext.getScrollingElement()
|
|
34
34
|
if (scrollingElement && (await scrollingElement.contains(element))) {
|
|
35
|
-
|
|
35
|
+
const scrollingLocation = utils.geometry.location(await scrollingElement.getRegion())
|
|
36
|
+
const elementLocation = utils.geometry.location(await element.getRegion())
|
|
37
|
+
await scrollingElement.scrollTo(utils.geometry.offsetNegative(elementLocation, scrollingLocation))
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
40
|
|
package/src/image.js
CHANGED
|
@@ -228,10 +228,11 @@ async function toPng(image) {
|
|
|
228
228
|
})
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
async function toFile(image,
|
|
231
|
+
async function toFile(image, filepath) {
|
|
232
232
|
const buffer = await toPng(image)
|
|
233
233
|
return new Promise((resolve, reject) => {
|
|
234
|
-
fs.
|
|
234
|
+
fs.mkdirSync(path.dirname(filepath), {recursive: true})
|
|
235
|
+
fs.writeFile(filepath, buffer, err => (err ? reject(err) : resolve()))
|
|
235
236
|
})
|
|
236
237
|
}
|
|
237
238
|
|
package/src/take-screenshot.js
CHANGED
|
@@ -45,6 +45,8 @@ async function takeScreenshot({
|
|
|
45
45
|
// unlike web apps, native apps do not always have scrolling element
|
|
46
46
|
if (scrollingElement) {
|
|
47
47
|
if (driver.isWeb && hideScrollbars) await scrollingElement.hideScrollbars()
|
|
48
|
+
// this is unwanted but necessary side effect, because it is not possible to extract initial scroll position
|
|
49
|
+
if (driver.isNative && !window) await scrollingElement.scrollTo({x: 0, y: 0}, {force: true})
|
|
48
50
|
await scrollingElement.preserveState()
|
|
49
51
|
}
|
|
50
52
|
}
|
|
@@ -60,12 +62,10 @@ async function takeScreenshot({
|
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
try {
|
|
63
|
-
if (!window && !driver.isNative) {
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
await target.scroller.moveTo({x: 0, y: 0})
|
|
68
|
-
}
|
|
65
|
+
if (!window && !driver.isNative) await scrollIntoViewport({...target, logger})
|
|
66
|
+
|
|
67
|
+
if (fully && !target.region && target.scroller) await target.scroller.moveTo({x: 0, y: 0})
|
|
68
|
+
|
|
69
69
|
const screenshot =
|
|
70
70
|
fully && target.scroller
|
|
71
71
|
? await takeStitchedScreenshot({
|
|
@@ -17,6 +17,8 @@ async function takeStitchedScreenshot({
|
|
|
17
17
|
}) {
|
|
18
18
|
logger.verbose('Taking full image of...')
|
|
19
19
|
|
|
20
|
+
if (await scroller.element.isPager()) overlap = {top: 0, bottom: 0}
|
|
21
|
+
|
|
20
22
|
const driver = context.driver
|
|
21
23
|
const takeViewportScreenshot = makeTakeViewportScreenshot({logger, driver, stabilization, debug})
|
|
22
24
|
const scrollerState = await scroller.preserveState()
|
|
@@ -94,7 +96,11 @@ async function takeStitchedScreenshot({
|
|
|
94
96
|
const partName = `${partRegion.x}_${partRegion.y}_${partRegion.width}x${partRegion.height}`
|
|
95
97
|
logger.verbose(`Processing part ${partName}`)
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
// compensate scroller region being shifted and top overlap
|
|
100
|
+
const compensateOffset = {
|
|
101
|
+
x: scrollerRegionShift.x + 0,
|
|
102
|
+
y: scrollerRegionShift.y + (initialRegion.y !== partRegion.y ? overlap.top : 0),
|
|
103
|
+
}
|
|
98
104
|
const requiredOffset = utils.geometry.offsetNegative(utils.geometry.location(partRegion), compensateOffset)
|
|
99
105
|
|
|
100
106
|
logger.verbose('Move to', requiredOffset)
|
|
@@ -167,7 +167,7 @@ function makeTakeNativeScreenshot({driver, stabilization = {}, debug, logger}) {
|
|
|
167
167
|
image.crop({
|
|
168
168
|
top: driver.statusBarHeight,
|
|
169
169
|
bottom: driver.orientation === 'landscape' ? 0 : driver.navigationBarHeight,
|
|
170
|
-
left: driver.platformVersion
|
|
170
|
+
left: driver.platformVersion >= 8 ? driver.navigationBarHeight : 0,
|
|
171
171
|
right: driver.platformVersion < 8 ? driver.navigationBarHeight : 0,
|
|
172
172
|
})
|
|
173
173
|
} else {
|