@applitools/screenshoter 3.2.9 → 3.3.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/.bongo/dry-run/package-lock.json +11 -11
- package/.bongo/dry-run.tgz +0 -0
- package/CHANGELOG.md +6 -0
- package/index.js +2 -1
- package/logs/screenshot_2021_12_16_19_06_06_332Z_full_app_failed_1639681566332.png +0 -0
- package/logs/screenshot_2021_12_16_19_15_59_935Z_full_app_failed_1639682159935.png +0 -0
- package/logs/screenshot_2021_12_16_19_33_20_679Z_full_app_failed_1639683200679.png +0 -0
- package/logs/screenshot_2021_12_16_19_37_22_120Z_ios_viewport_failed.png +0 -0
- package/logs/screenshot_2021_12_16_19_38_09_461Z_ios_full_page_failed.png +0 -0
- package/logs/screenshot_2021_12_16_19_59_45_182Z_ios_viewport_failed.png +0 -0
- package/package.json +5 -5
- package/src/find-image-pattern.js +10 -38
- package/src/image.js +104 -64
- package/src/take-screenshot.js +136 -160
- package/src/take-simple-screenshot.js +25 -0
- package/src/take-stitched-screenshot.js +32 -52
- package/src/take-viewport-screenshot.js +179 -16
- package/test/e2e/android.spec.js +42 -11
- package/test/e2e/external.spec.js +81 -10
- package/test/e2e/ios.spec.js +48 -10
- package/test/e2e/web-ios.spec.js +3 -5
- package/test/e2e/web.spec.js +20 -15
- package/test/fixtures/android/app-fully-non-scrollable.png +0 -0
- package/test/fixtures/android/app-fully-recycler.png +0 -0
- package/test/fixtures/android/app-fully-scroll-statusbar.png +0 -0
- package/test/fixtures/android/app-fully-scroll.png +0 -0
- package/test/fixtures/android/app-statusbar.png +0 -0
- package/test/fixtures/android/x-app-fully-collapsing.png +0 -0
- package/test/fixtures/android/x-app-fully-recycler.png +0 -0
- package/test/fixtures/android/x-element-fully.png +0 -0
- package/test/fixtures/image/{house.combined-higher-wider.png → house.framed-higher-wider.png} +0 -0
- package/test/fixtures/image/{house.combined-higher.png → house.framed-higher.png} +0 -0
- package/test/fixtures/image/house.framed-shorter-thinner.png +0 -0
- package/test/fixtures/image/{house.combined-wider.png → house.framed-wider.png} +0 -0
- package/test/fixtures/ios/app-fully-collapsing.png +0 -0
- package/test/fixtures/ios/app-fully-collection.png +0 -0
- package/test/fixtures/ios/app-fully-overlapped-statusbar.png +0 -0
- package/test/fixtures/ios/app-fully-overlapped.png +0 -0
- package/test/fixtures/ios/app-fully-scroll-statusbar.png +0 -0
- package/test/fixtures/ios/app-fully-scroll.png +0 -0
- package/test/fixtures/ios/app-fully-superview.png +0 -0
- package/test/fixtures/ios/app-fully-table.png +0 -0
- package/test/fixtures/ios/app-statusbar.png +0 -0
- package/test/fixtures/ios/app.png +0 -0
- package/test/fixtures/ios/element-fully.png +0 -0
- package/test/fixtures/ios/element.png +0 -0
- package/test/fixtures/ios/region.png +0 -0
- package/test/fixtures/pattern/iPad_5th_landscape.png +0 -0
- package/test/fixtures/pattern/iPad_5th_portrait.png +0 -0
- package/test/fixtures/pattern/iPad_9th_landscape.png +0 -0
- package/test/fixtures/pattern/iPad_9th_portrait.png +0 -0
- package/test/fixtures/pattern/iPhone_11_landscape.png +0 -0
- package/test/fixtures/pattern/iPhone_11_portrait.png +0 -0
- package/test/fixtures/pattern/iPhone_13_landscape.png +0 -0
- package/test/fixtures/pattern/iPhone_13_portrait.png +0 -0
- package/test/fixtures/pattern/iPhone_SE_landscape.png +0 -0
- package/test/fixtures/pattern/iPhone_SE_portrait.png +0 -0
- package/test/fixtures/pattern/iPhone_XS_portrait_noviewport.png +0 -0
- package/test/fixtures/web-ios/page-fully.png +0 -0
- package/test/fixtures/web-ios/page.png +0 -0
- package/test/it/find-pattern.spec.js +16 -11
- package/test/it/image.spec.js +42 -15
- package/logs/screenshot_2021_11_14_12_35_00_342Z_full_frame_failed.png +0 -0
- package/logs/screenshot_2021_11_14_12_38_00_715Z_frame_failed.png +0 -0
- package/logs/screenshot_2021_11_14_12_38_03_866Z_frame_failed.png +0 -0
- package/logs/screenshot_2021_11_14_13_02_56_464Z_full_app_failed_1636894976464.png +0 -0
- package/logs/screenshot_2021_11_14_13_04_27_904Z_full_app_failed_1636895067904.png +0 -0
- package/logs/screenshot_2021_11_14_13_06_13_662Z_full_app_failed_1636895173662.png +0 -0
- package/logs/screenshot_2021_11_14_13_06_23_745Z_full_app_failed_1636895183745.png +0 -0
- package/logs/screenshot_2021_11_14_13_18_31_571Z_full_app_failed_1636895911571.png +0 -0
- package/logs/screenshot_2021_11_14_13_25_54_557Z_viewport_failed_1636896354557.png +0 -0
- package/logs/screenshot_2021_11_14_13_29_32_326Z_viewport_failed_1636896572326.png +0 -0
- package/logs/screenshot_2021_11_14_13_34_22_483Z_viewport_failed_1636896862483.png +0 -0
- package/logs/screenshot_2021_11_14_13_37_25_734Z_viewport_failed_1636897045734.png +0 -0
- package/logs/screenshot_2021_11_14_13_42_25_024Z_viewport_failed_1636897345024.png +0 -0
- package/logs/screenshot_2021_11_14_13_57_24_366Z_full_app_failed_1636898244366.png +0 -0
- package/logs/screenshot_2021_11_14_14_20_42_951Z_full_app_failed_1636899642951.png +0 -0
- package/logs/screenshot_2021_11_14_14_31_07_853Z_full_app_failed_1636900267853.png +0 -0
- package/logs/screenshot_2021_11_14_14_32_07_195Z_full_app_failed_1636900327195.png +0 -0
- package/logs/screenshot_2021_11_14_14_42_16_716Z_full_app_failed_1636900936716.png +0 -0
- package/logs/screenshot_2021_11_14_14_47_37_646Z_full_app_failed_1636901257646.png +0 -0
- package/logs/screenshot_2021_11_14_14_54_18_522Z_full_app_failed_1636901658522.png +0 -0
- package/logs/screenshot_2021_11_14_14_55_36_756Z_full_app_failed_1636901736756.png +0 -0
- package/logs/screenshot_2021_11_14_15_00_26_000Z_full_app_failed_1636902026000.png +0 -0
- package/logs/screenshot_2021_11_14_15_04_13_598Z_full_app_failed_1636902253598.png +0 -0
- package/logs/screenshot_2021_11_14_15_07_37_914Z_full_app_failed_1636902457914.png +0 -0
- package/logs/screenshot_2021_11_14_15_12_20_039Z_full_app_failed_1636902740039.png +0 -0
- package/logs/screenshot_2021_11_14_15_15_44_401Z_full_app_failed_1636902944401.png +0 -0
- package/logs/screenshot_2021_11_14_15_26_23_318Z_viewport_failed_1636903583318.png +0 -0
- package/src/calculate-screenshot-regions.js +0 -31
- package/src/screenshoter.js +0 -159
- package/test/fixtures/pattern/iPad_Air_portrait.png +0 -0
- package/test/fixtures/pattern/iPhone_5S_landscape.png +0 -0
- package/test/fixtures/pattern/iPhone_XR_perfecto_landscape.png +0 -0
- package/test/fixtures/pattern/iPhone_XS_Max_perfecto_landscape.png +0 -0
- package/test/fixtures/pattern/iPhone_XS_landscape.png +0 -0
- package/test/fixtures/pattern/iPhone_XS_portrait.png +0 -0
- package/test/fixtures/pattern/iPhone_X_perfecto_portrait.png +0 -0
package/test/e2e/web.spec.js
CHANGED
|
@@ -2,7 +2,7 @@ const assert = require('assert')
|
|
|
2
2
|
const pixelmatch = require('pixelmatch')
|
|
3
3
|
const {Driver} = require('@applitools/driver')
|
|
4
4
|
const spec = require('@applitools/spec-driver-webdriverio')
|
|
5
|
-
const
|
|
5
|
+
const takeScreenshot = require('../../index')
|
|
6
6
|
const makeImage = require('../../src/image')
|
|
7
7
|
|
|
8
8
|
const env = {
|
|
@@ -128,7 +128,7 @@ describe('screenshoter web', () => {
|
|
|
128
128
|
})
|
|
129
129
|
|
|
130
130
|
async function viewport(options) {
|
|
131
|
-
const screenshot = await
|
|
131
|
+
const screenshot = await takeScreenshot({logger, driver, ...options})
|
|
132
132
|
try {
|
|
133
133
|
const actual = await screenshot.image.toObject()
|
|
134
134
|
const expected = await makeImage('./test/fixtures/web/page.png').toObject()
|
|
@@ -139,7 +139,7 @@ describe('screenshoter web', () => {
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
async function fullPage(options) {
|
|
142
|
-
const screenshot = await
|
|
142
|
+
const screenshot = await takeScreenshot({logger, driver, fully: true, ...options})
|
|
143
143
|
try {
|
|
144
144
|
const actual = await screenshot.image.toObject()
|
|
145
145
|
const expected = await makeImage('./test/fixtures/web/page-fully.png').toObject()
|
|
@@ -150,7 +150,12 @@ describe('screenshoter web', () => {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
async function frame(options) {
|
|
153
|
-
const screenshot = await
|
|
153
|
+
const screenshot = await takeScreenshot({
|
|
154
|
+
logger,
|
|
155
|
+
driver,
|
|
156
|
+
frames: [{reference: 'iframe[name="frame1"]'}],
|
|
157
|
+
...options,
|
|
158
|
+
})
|
|
154
159
|
try {
|
|
155
160
|
const actual = await screenshot.image.toObject()
|
|
156
161
|
const expected = await makeImage('./test/fixtures/web/frame.png').toObject()
|
|
@@ -161,7 +166,7 @@ describe('screenshoter web', () => {
|
|
|
161
166
|
}
|
|
162
167
|
}
|
|
163
168
|
async function fullFrame(options) {
|
|
164
|
-
const screenshot = await
|
|
169
|
+
const screenshot = await takeScreenshot({
|
|
165
170
|
logger,
|
|
166
171
|
driver,
|
|
167
172
|
frames: [{reference: 'iframe[name="frame1"]'}],
|
|
@@ -179,7 +184,7 @@ describe('screenshoter web', () => {
|
|
|
179
184
|
}
|
|
180
185
|
async function region(options) {
|
|
181
186
|
const region = {x: 30, y: 500, height: 100, width: 200}
|
|
182
|
-
const screenshot = await
|
|
187
|
+
const screenshot = await takeScreenshot({logger, driver, region, ...options})
|
|
183
188
|
try {
|
|
184
189
|
const actual = await screenshot.image.toObject()
|
|
185
190
|
const expected = await makeImage('./test/fixtures/web/region.png').toObject()
|
|
@@ -191,7 +196,7 @@ describe('screenshoter web', () => {
|
|
|
191
196
|
}
|
|
192
197
|
async function fullRegion(options) {
|
|
193
198
|
const region = {x: 30, y: 500, height: 700, width: 200}
|
|
194
|
-
const screenshot = await
|
|
199
|
+
const screenshot = await takeScreenshot({logger, driver, region, fully: true, ...options})
|
|
195
200
|
try {
|
|
196
201
|
const actual = await screenshot.image.toObject()
|
|
197
202
|
const expected = await makeImage('./test/fixtures/web/region-fully.png').toObject()
|
|
@@ -202,7 +207,7 @@ describe('screenshoter web', () => {
|
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
async function element(options) {
|
|
205
|
-
const screenshot = await
|
|
210
|
+
const screenshot = await takeScreenshot({logger, driver, region: '#overflowing-div-image', ...options})
|
|
206
211
|
try {
|
|
207
212
|
const actual = await screenshot.image.toObject()
|
|
208
213
|
const expected = await makeImage('./test/fixtures/web/element.png').toObject()
|
|
@@ -213,7 +218,7 @@ describe('screenshoter web', () => {
|
|
|
213
218
|
}
|
|
214
219
|
}
|
|
215
220
|
async function fullElement(options) {
|
|
216
|
-
const screenshot = await
|
|
221
|
+
const screenshot = await takeScreenshot({logger, driver, region: '#overflowing-div-image', fully: true, ...options})
|
|
217
222
|
try {
|
|
218
223
|
const actual = await screenshot.image.toObject()
|
|
219
224
|
const expected = await makeImage('./test/fixtures/web/element-fully.png').toObject()
|
|
@@ -224,7 +229,7 @@ describe('screenshoter web', () => {
|
|
|
224
229
|
}
|
|
225
230
|
}
|
|
226
231
|
async function regionInFrame(options) {
|
|
227
|
-
const screenshot = await
|
|
232
|
+
const screenshot = await takeScreenshot({
|
|
228
233
|
logger,
|
|
229
234
|
driver,
|
|
230
235
|
frames: [{reference: 'iframe[name="frame1"]'}],
|
|
@@ -241,7 +246,7 @@ describe('screenshoter web', () => {
|
|
|
241
246
|
}
|
|
242
247
|
}
|
|
243
248
|
async function fullRegionInFrame(options) {
|
|
244
|
-
const screenshot = await
|
|
249
|
+
const screenshot = await takeScreenshot({
|
|
245
250
|
logger,
|
|
246
251
|
driver,
|
|
247
252
|
frames: [{reference: 'iframe[name="frame1"]'}],
|
|
@@ -259,7 +264,7 @@ describe('screenshoter web', () => {
|
|
|
259
264
|
}
|
|
260
265
|
}
|
|
261
266
|
async function elementInFrame(options) {
|
|
262
|
-
const screenshot = await
|
|
267
|
+
const screenshot = await takeScreenshot({
|
|
263
268
|
logger,
|
|
264
269
|
driver,
|
|
265
270
|
frames: [{reference: 'iframe[name="frame1"]'}],
|
|
@@ -276,7 +281,7 @@ describe('screenshoter web', () => {
|
|
|
276
281
|
}
|
|
277
282
|
}
|
|
278
283
|
async function fullElementInFrame(options) {
|
|
279
|
-
const screenshot = await
|
|
284
|
+
const screenshot = await takeScreenshot({
|
|
280
285
|
logger,
|
|
281
286
|
driver,
|
|
282
287
|
frames: [{reference: 'iframe[name="frame1"]'}],
|
|
@@ -294,7 +299,7 @@ describe('screenshoter web', () => {
|
|
|
294
299
|
}
|
|
295
300
|
}
|
|
296
301
|
async function frameInFrame(options) {
|
|
297
|
-
const screenshot = await
|
|
302
|
+
const screenshot = await takeScreenshot({
|
|
298
303
|
logger,
|
|
299
304
|
driver,
|
|
300
305
|
frames: [{reference: 'iframe[name="frame1"]'}, {reference: 'iframe[name="frame1-1"]'}],
|
|
@@ -310,7 +315,7 @@ describe('screenshoter web', () => {
|
|
|
310
315
|
}
|
|
311
316
|
}
|
|
312
317
|
async function fullFrameInFrame(options) {
|
|
313
|
-
const screenshot = await
|
|
318
|
+
const screenshot = await takeScreenshot({
|
|
314
319
|
logger,
|
|
315
320
|
driver,
|
|
316
321
|
frames: [{reference: 'iframe[name="frame1"]'}, {reference: 'iframe[name="frame1-1"]'}],
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/test/fixtures/image/{house.combined-higher-wider.png → house.framed-higher-wider.png}
RENAMED
|
File without changes
|
|
File without changes
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -4,23 +4,28 @@ const findPattern = require('../../src/find-image-pattern')
|
|
|
4
4
|
|
|
5
5
|
describe('pattern', () => {
|
|
6
6
|
const fixtures = [
|
|
7
|
-
{name: '
|
|
8
|
-
{name: '
|
|
9
|
-
{name: '
|
|
10
|
-
{name: '
|
|
11
|
-
{name: '
|
|
12
|
-
{name: '
|
|
13
|
-
{name: '
|
|
7
|
+
{name: 'iPhone_SE_portrait', position: {x: 0, y: 140}, offset: 0, pixelRatio: 2},
|
|
8
|
+
{name: 'iPhone_SE_landscape', position: {x: 0, y: 100}, offset: 0, pixelRatio: 2},
|
|
9
|
+
{name: 'iPhone_11_portrait', position: {x: 0, y: 282}, offset: 0, pixelRatio: 3},
|
|
10
|
+
{name: 'iPhone_11_landscape', position: {x: 132, y: 150}, offset: 0, pixelRatio: 3},
|
|
11
|
+
{name: 'iPhone_13_portrait', position: {x: 0, y: 141}, offset: 0, pixelRatio: 3},
|
|
12
|
+
{name: 'iPhone_13_landscape', position: {x: 141, y: 144}, offset: 0, pixelRatio: 3},
|
|
13
|
+
{name: 'iPad_5th_portrait', position: {x: 0, y: 140}, offset: 0, pixelRatio: 2},
|
|
14
|
+
{name: 'iPad_5th_landscape', position: {x: 0, y: 140}, offset: 0, pixelRatio: 2},
|
|
15
|
+
{name: 'iPad_9th_portrait', position: {x: 0, y: 136}, offset: 0, pixelRatio: 2},
|
|
16
|
+
{name: 'iPad_9th_landscape', position: {x: 641, y: 137}, offset: 1, pixelRatio: 2},
|
|
17
|
+
{name: 'iPhone_XS_portrait_noviewport', position: {x: 0, y: 282}, offset: 0, pixelRatio: 3},
|
|
14
18
|
{name: 'iPhone_XS_portrait_nomarker', position: null, pixelRatio: 3},
|
|
15
19
|
]
|
|
16
20
|
|
|
17
|
-
fixtures.forEach(({name, position, pixelRatio}) => {
|
|
21
|
+
fixtures.forEach(({name, position, offset, pixelRatio}) => {
|
|
18
22
|
it(name, async () => {
|
|
19
23
|
const image = await makeImage(`./test/fixtures/pattern/${name}.png`)
|
|
20
24
|
const result = findPattern(await image.toObject(), {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
pixelRatio,
|
|
26
|
+
mask: [1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1],
|
|
27
|
+
offset,
|
|
28
|
+
size: 1,
|
|
24
29
|
})
|
|
25
30
|
assert.deepStrictEqual(result, position)
|
|
26
31
|
})
|
package/test/it/image.spec.js
CHANGED
|
@@ -78,42 +78,69 @@ describe('image', () => {
|
|
|
78
78
|
assert.strictEqual(actual.height, 50000)
|
|
79
79
|
})
|
|
80
80
|
|
|
81
|
-
it('should
|
|
81
|
+
it('should frame image in a higher and wider region', async () => {
|
|
82
82
|
const image = makeImage('./test/fixtures/image/house.png')
|
|
83
83
|
const srcImage = makeImage({
|
|
84
84
|
width: 200,
|
|
85
85
|
height: 200,
|
|
86
86
|
data: Buffer.alloc(200 * 200 * 4, Buffer.from([0xff, 0, 0, 0xff])),
|
|
87
87
|
})
|
|
88
|
-
const combinedImage = await srcImage.
|
|
88
|
+
const combinedImage = await srcImage.frame(image, image, {x: 200, y: 200, width: 100, height: 100})
|
|
89
89
|
const actual = await combinedImage.toObject()
|
|
90
|
-
const expected = await makeImage('./test/fixtures/image/house.
|
|
90
|
+
const expected = await makeImage('./test/fixtures/image/house.framed-higher-wider.png').toObject()
|
|
91
91
|
assert.ok(pixelmatch(actual.data, expected.data, null, expected.width, expected.height) === 0)
|
|
92
92
|
})
|
|
93
93
|
|
|
94
|
-
it('should
|
|
94
|
+
it('should frame image in a higher region', async () => {
|
|
95
95
|
const image = await makeImage('./test/fixtures/image/house.png')
|
|
96
96
|
const srcImage = makeImage({
|
|
97
97
|
width: 200,
|
|
98
98
|
height: 200,
|
|
99
99
|
data: Buffer.alloc(200 * 200 * 4, Buffer.from([0, 0xff, 0, 0xff])),
|
|
100
100
|
})
|
|
101
|
-
const combinedImage = await srcImage.
|
|
101
|
+
const combinedImage = await srcImage.frame(image, image, {x: 200, y: 200, width: 200, height: 100})
|
|
102
102
|
const actual = await combinedImage.toObject()
|
|
103
|
-
const expected = await makeImage('./test/fixtures/image/house.
|
|
103
|
+
const expected = await makeImage('./test/fixtures/image/house.framed-higher.png').toObject()
|
|
104
104
|
assert.ok(pixelmatch(actual.data, expected.data, null, expected.width, expected.height) === 0)
|
|
105
105
|
})
|
|
106
106
|
|
|
107
|
-
it('should
|
|
107
|
+
it('should frame image in a wider region', async () => {
|
|
108
108
|
const image = await makeImage('./test/fixtures/image/house.png')
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
height: 200
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
109
|
+
const data = Buffer.alloc(200 * 200 * 4, Buffer.from([0, 0, 0xff, 0xff]))
|
|
110
|
+
const actual = await makeImage({width: 200, height: 200, data})
|
|
111
|
+
.frame(image, image, {x: 200, y: 200, width: 100, height: 200})
|
|
112
|
+
.toObject()
|
|
113
|
+
const expected = await makeImage('./test/fixtures/image/house.framed-wider.png').toObject()
|
|
114
|
+
assert.ok(pixelmatch(actual.data, expected.data, null, expected.width, expected.height) === 0)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('should frame image in a shorter and thinner region', async () => {
|
|
118
|
+
const image = await makeImage('./test/fixtures/image/house.png')
|
|
119
|
+
const data = Buffer.alloc(200 * 200 * 4, Buffer.from([0xff, 0, 0xff, 0xff]))
|
|
120
|
+
const actual = await makeImage({width: 200, height: 200, data})
|
|
121
|
+
.frame(image, image, {x: 100, y: 100, width: 250, height: 250})
|
|
122
|
+
.toObject()
|
|
123
|
+
const expected = await makeImage('./test/fixtures/image/house.framed-shorter-thinner.png').toObject()
|
|
124
|
+
assert.ok(pixelmatch(actual.data, expected.data, null, expected.width, expected.height) === 0)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('should frame image in a shorter region', async () => {
|
|
128
|
+
const image = await makeImage('./test/fixtures/image/house.png')
|
|
129
|
+
const data = Buffer.alloc(200 * 200 * 4, Buffer.from([0xff, 0, 0xff, 0xff]))
|
|
130
|
+
const actual = await makeImage({width: 200, height: 200, data})
|
|
131
|
+
.frame(image, image, {x: 100, y: 100, width: 200, height: 250})
|
|
132
|
+
.toObject()
|
|
133
|
+
const expected = await makeImage('./test/fixtures/image/house.framed-shorter-thinner.png').toObject()
|
|
134
|
+
assert.ok(pixelmatch(actual.data, expected.data, null, expected.width, expected.height) === 0)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('should frame image in a thinner region', async () => {
|
|
138
|
+
const image = await makeImage('./test/fixtures/image/house.png')
|
|
139
|
+
const data = Buffer.alloc(200 * 200 * 4, Buffer.from([0xff, 0, 0xff, 0xff]))
|
|
140
|
+
const actual = await makeImage({width: 200, height: 200, data})
|
|
141
|
+
.frame(image, image, {x: 100, y: 100, width: 250, height: 200})
|
|
142
|
+
.toObject()
|
|
143
|
+
const expected = await makeImage('./test/fixtures/image/house.framed-shorter-thinner.png').toObject()
|
|
117
144
|
assert.ok(pixelmatch(actual.data, expected.data, null, expected.width, expected.height) === 0)
|
|
118
145
|
})
|
|
119
146
|
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const utils = require('@applitools/utils')
|
|
2
|
-
|
|
3
|
-
async function calculateScreenshotRegions({context, screenshotRegion, regions}) {
|
|
4
|
-
const screenshotRegions = []
|
|
5
|
-
for (const region of regions) {
|
|
6
|
-
screenshotRegions.push(await transformRegion(region))
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
return screenshotRegions
|
|
10
|
-
|
|
11
|
-
async function transformRegion(region) {
|
|
12
|
-
if (utils.types.has(region, ['x', 'y', 'width', 'height'])) {
|
|
13
|
-
// if someday different coordinate systems will be supported (context or app based), the conversion will happen here
|
|
14
|
-
return [regions]
|
|
15
|
-
}
|
|
16
|
-
const elements = await context.elements(region)
|
|
17
|
-
return elements.reduce(async (regions, element) => {
|
|
18
|
-
regions = await regions
|
|
19
|
-
const region = await element.getRegion()
|
|
20
|
-
regions.push({
|
|
21
|
-
x: Math.max(0, region.x - screenshotRegion.x),
|
|
22
|
-
y: Math.max(0, region.y - screenshotRegion.y),
|
|
23
|
-
width: region.width,
|
|
24
|
-
height: region.height,
|
|
25
|
-
})
|
|
26
|
-
return regions
|
|
27
|
-
}, [])
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
module.exports = calculateScreenshotRegions
|
package/src/screenshoter.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
const utils = require('@applitools/utils')
|
|
2
|
-
const makeScroller = require('./scroller')
|
|
3
|
-
const scrollIntoViewport = require('./scroll-into-viewport')
|
|
4
|
-
const takeStitchedScreenshot = require('./take-stitched-screenshot')
|
|
5
|
-
const takeViewportScreenshot = require('./take-viewport-screenshot')
|
|
6
|
-
|
|
7
|
-
async function screenshoter({
|
|
8
|
-
driver,
|
|
9
|
-
frames = [],
|
|
10
|
-
region,
|
|
11
|
-
fully,
|
|
12
|
-
scrollingMode,
|
|
13
|
-
hideScrollbars,
|
|
14
|
-
hideCaret,
|
|
15
|
-
withStatusBar,
|
|
16
|
-
overlap,
|
|
17
|
-
framed,
|
|
18
|
-
wait,
|
|
19
|
-
stabilization,
|
|
20
|
-
hooks,
|
|
21
|
-
debug,
|
|
22
|
-
logger,
|
|
23
|
-
}) {
|
|
24
|
-
// screenshot of a window/app was requested (fully or viewport)
|
|
25
|
-
const window = !region && (!frames || frames.length === 0)
|
|
26
|
-
// framed screenshots could be taken only when screenshot of window/app fully was requested
|
|
27
|
-
framed = framed && fully && window
|
|
28
|
-
// screenshots with status bar could be taken only when screenshot of app or framed app fully was requested
|
|
29
|
-
withStatusBar = withStatusBar && driver.isNative && window && (!fully || framed)
|
|
30
|
-
scrollingMode = driver.isNative ? 'scroll' : scrollingMode
|
|
31
|
-
|
|
32
|
-
const activeContext = driver.currentContext
|
|
33
|
-
const context =
|
|
34
|
-
frames.length > 0
|
|
35
|
-
? await activeContext.context(frames.reduce((parent, frame) => ({...frame, parent}), null))
|
|
36
|
-
: activeContext
|
|
37
|
-
|
|
38
|
-
// traverse from main context to target context to hide scrollbars and preserve context state (scroll/translate position)
|
|
39
|
-
for (const nextContext of context.path) {
|
|
40
|
-
const scrollingElement = await nextContext.getScrollingElement()
|
|
41
|
-
// unlike web apps, native apps do not always have scrolling element
|
|
42
|
-
if (scrollingElement) {
|
|
43
|
-
if (driver.isWeb && hideScrollbars) await scrollingElement.hideScrollbars()
|
|
44
|
-
await scrollingElement.preserveState()
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// blur active element in target context
|
|
49
|
-
const activeElement = driver.isWeb && hideCaret ? await context.blurElement() : null
|
|
50
|
-
|
|
51
|
-
const target = await getTarget({window, context, region, fully, scrollingMode, logger})
|
|
52
|
-
|
|
53
|
-
if (driver.isWeb && hideScrollbars) await target.scroller.hideScrollbars()
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
if (!window) await scrollIntoViewport({...target, logger})
|
|
57
|
-
|
|
58
|
-
const screenshot =
|
|
59
|
-
fully && target.scroller
|
|
60
|
-
? await takeStitchedScreenshot({...target, withStatusBar, overlap, framed, wait, stabilization, debug, logger})
|
|
61
|
-
: await takeViewportScreenshot({...target, withStatusBar, wait, stabilization, debug, logger})
|
|
62
|
-
|
|
63
|
-
if (hooks && hooks.afterScreenshot) {
|
|
64
|
-
// imitate image-like state for the hook
|
|
65
|
-
if (window && fully && target.scroller) {
|
|
66
|
-
await target.scroller.moveTo({x: 0, y: 0}, await driver.mainContext.getScrollingElement())
|
|
67
|
-
}
|
|
68
|
-
await hooks.afterScreenshot({driver, scroller: target.scroller, screenshot})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return screenshot
|
|
72
|
-
} finally {
|
|
73
|
-
if (target.scroller) {
|
|
74
|
-
await target.scroller.restoreScrollbars()
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// if there was active element and we have blurred it, then restore focus
|
|
78
|
-
if (activeElement) await context.focusElement(activeElement)
|
|
79
|
-
|
|
80
|
-
// traverse from target context to the main context to restore scrollbars and context states
|
|
81
|
-
for (const prevContext of context.path.reverse()) {
|
|
82
|
-
const scrollingElement = await prevContext.getScrollingElement()
|
|
83
|
-
if (scrollingElement) {
|
|
84
|
-
if (driver.isWeb && hideScrollbars) await scrollingElement.restoreScrollbars()
|
|
85
|
-
await scrollingElement.restoreState()
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// restore focus on original active context
|
|
90
|
-
await activeContext.focus()
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async function getTarget({window, context, region, fully, scrollingMode, logger}) {
|
|
95
|
-
if (window) {
|
|
96
|
-
// window/app
|
|
97
|
-
const scrollingElement = await context.main.getScrollingElement()
|
|
98
|
-
return {
|
|
99
|
-
context: context.main,
|
|
100
|
-
scroller: scrollingElement ? makeScroller({element: scrollingElement, scrollingMode, logger}) : null,
|
|
101
|
-
}
|
|
102
|
-
} else if (region) {
|
|
103
|
-
if (utils.types.has(region, ['x', 'y', 'width', 'height'])) {
|
|
104
|
-
// region by coordinates
|
|
105
|
-
const scrollingElement = await context.getScrollingElement()
|
|
106
|
-
return {
|
|
107
|
-
context,
|
|
108
|
-
region,
|
|
109
|
-
scroller: scrollingElement ? makeScroller({element: scrollingElement, scrollingMode, logger}) : null,
|
|
110
|
-
}
|
|
111
|
-
} else {
|
|
112
|
-
// region by element or selector
|
|
113
|
-
const element = await context.element(region)
|
|
114
|
-
if (!element) throw new Error('Element not found!')
|
|
115
|
-
|
|
116
|
-
const elementContext = element.context
|
|
117
|
-
|
|
118
|
-
if (fully) {
|
|
119
|
-
const isScrollable = await element.isScrollable()
|
|
120
|
-
// if element is scrollable, then take screenshot of the full element content, otherwise take screenshot of full element
|
|
121
|
-
const region = isScrollable ? null : await element.getRegion()
|
|
122
|
-
const scrollingElement = isScrollable ? element : await elementContext.getScrollingElement()
|
|
123
|
-
// css stitching could be applied only to root element of its context
|
|
124
|
-
scrollingMode = scrollingMode === 'css' && !(await scrollingElement.isRoot()) ? 'mixed' : scrollingMode
|
|
125
|
-
return {
|
|
126
|
-
context: elementContext,
|
|
127
|
-
region,
|
|
128
|
-
scroller: scrollingElement ? makeScroller({element: scrollingElement, scrollingMode, logger}) : null,
|
|
129
|
-
}
|
|
130
|
-
} else {
|
|
131
|
-
const scrollingElement = await context.getScrollingElement()
|
|
132
|
-
return {
|
|
133
|
-
context: elementContext,
|
|
134
|
-
region: await element.getRegion(),
|
|
135
|
-
scroller: scrollingElement ? makeScroller({element: scrollingElement, scrollingMode, logger}) : null,
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
} else if (!context.isMain) {
|
|
140
|
-
// context
|
|
141
|
-
if (fully) {
|
|
142
|
-
const scrollingElement = await context.getScrollingElement()
|
|
143
|
-
return {
|
|
144
|
-
context,
|
|
145
|
-
scroller: scrollingElement ? makeScroller({logger, element: scrollingElement, scrollingMode}) : null,
|
|
146
|
-
}
|
|
147
|
-
} else {
|
|
148
|
-
const scrollingElement = await context.parent.getScrollingElement()
|
|
149
|
-
const element = await context.getContextElement()
|
|
150
|
-
return {
|
|
151
|
-
context: context.parent,
|
|
152
|
-
region: await element.getRegion(), // IMHO we should use CLIENT (without borders) region here
|
|
153
|
-
scroller: scrollingElement ? makeScroller({logger, element: scrollingElement, scrollingMode}) : null,
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
module.exports = screenshoter
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|