@applitools/screenshoter 3.2.9 → 3.3.3
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 +19 -19
- package/.bongo/dry-run.tgz +0 -0
- package/CHANGELOG.md +23 -0
- package/docker-compose.yaml +29 -0
- package/index.js +2 -1
- package/package.json +6 -6
- package/src/find-image-pattern.js +11 -38
- package/src/image.js +116 -73
- package/src/scroll-into-viewport.js +16 -7
- 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 +157 -16
- package/test/e2e/android.spec.js +84 -11
- package/test/e2e/external.spec.js +81 -10
- package/test/e2e/ios.spec.js +129 -13
- package/test/e2e/web-ios.spec.js +44 -11
- 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/ios/webview-fully.png +0 -0
- package/test/fixtures/ios/webview.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-landscape.png +0 -0
- package/test/fixtures/web-ios/page-fully.png +0 -0
- package/test/fixtures/web-ios/page-landscape.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
|
@@ -1,25 +1,166 @@
|
|
|
1
1
|
const utils = require('@applitools/utils')
|
|
2
|
-
const
|
|
2
|
+
const snippets = require('@applitools/snippets')
|
|
3
|
+
const findImagePattern = require('./find-image-pattern')
|
|
4
|
+
const makeImage = require('./image')
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
function makeTakeViewportScreenshot(options) {
|
|
7
|
+
const {driver} = options
|
|
8
|
+
if (driver.isNative) {
|
|
9
|
+
return makeTakeNativeScreenshot(options)
|
|
10
|
+
} else if (driver.isIOS) {
|
|
11
|
+
// safari on ios takes screenshot with browser and os interfaces
|
|
12
|
+
return makeTakeMarkedScreenshot(options)
|
|
13
|
+
} else if (driver.browserName === 'Firefox') {
|
|
14
|
+
try {
|
|
15
|
+
const browserVersion = Number.parseInt(driver.browserVersion, 10)
|
|
16
|
+
if (browserVersion >= 48 && browserVersion <= 72) {
|
|
17
|
+
// firefox between versions 48 and 72 takes current frame screenshot only
|
|
18
|
+
return makeTakeMainContextScreenshot(options)
|
|
19
|
+
}
|
|
20
|
+
} catch (ignored) {}
|
|
21
|
+
} else if (driver.browserName === 'Safari' && driver.browserVersion === '11') {
|
|
22
|
+
// safari 11 on macs takes full page screenshot
|
|
23
|
+
return makeTakeSafari11Screenshot(options)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return makeTakeDefaultScreenshot(options)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function makeTakeDefaultScreenshot({driver, stabilization = {}, debug, logger}) {
|
|
30
|
+
return async function takeScreenshot({name} = {}) {
|
|
31
|
+
logger.verbose('Taking screenshot...')
|
|
32
|
+
const image = makeImage(await driver.takeScreenshot())
|
|
33
|
+
await image.debug({...debug, name, suffix: 'original'})
|
|
34
|
+
|
|
35
|
+
if (stabilization.scale) image.scale(stabilization.scale)
|
|
36
|
+
else image.scale(1 / driver.pixelRatio)
|
|
37
|
+
|
|
38
|
+
if (stabilization.rotate) image.crop(stabilization.rotate)
|
|
39
|
+
|
|
40
|
+
if (stabilization.crop) image.crop(stabilization.crop)
|
|
41
|
+
|
|
42
|
+
return image
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function makeTakeMainContextScreenshot({driver, stabilization = {}, debug, logger}) {
|
|
47
|
+
return async function takeScreenshot({name} = {}) {
|
|
48
|
+
logger.verbose('Taking screenshot...')
|
|
49
|
+
const originalContext = driver.currentContext
|
|
50
|
+
await driver.mainContext.focus()
|
|
51
|
+
const image = makeImage(await driver.takeScreenshot())
|
|
52
|
+
await originalContext.focus()
|
|
53
|
+
await image.debug({...debug, name, suffix: 'original'})
|
|
54
|
+
|
|
55
|
+
if (stabilization.scale) image.scale(stabilization.scale)
|
|
56
|
+
else image.scale(1 / driver.pixelRatio)
|
|
57
|
+
|
|
58
|
+
if (stabilization.rotate) image.rotate(stabilization.rotate)
|
|
59
|
+
|
|
60
|
+
if (stabilization.crop) image.crop(stabilization.crop)
|
|
61
|
+
|
|
62
|
+
return image
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function makeTakeSafari11Screenshot({driver, stabilization = {}, debug, logger}) {
|
|
67
|
+
let viewportSize
|
|
68
|
+
|
|
69
|
+
return async function takeScreenshot({name} = {}) {
|
|
70
|
+
logger.verbose('Taking safari 11 driver screenshot...')
|
|
71
|
+
const image = makeImage(await driver.takeScreenshot())
|
|
72
|
+
await image.debug({...debug, name, suffix: 'original'})
|
|
73
|
+
|
|
74
|
+
if (stabilization.scale) image.scale(stabilization.scale)
|
|
75
|
+
else image.scale(1 / driver.pixelRatio)
|
|
76
|
+
|
|
77
|
+
if (stabilization.rotate) image.rotate(stabilization.rotate)
|
|
78
|
+
|
|
79
|
+
if (stabilization.crop) image.crop(stabilization.crop)
|
|
80
|
+
else {
|
|
81
|
+
if (!viewportSize) viewportSize = await driver.getViewportSize()
|
|
82
|
+
const viewportLocation = await driver.mainContext.execute(snippets.getElementScrollOffset, [])
|
|
83
|
+
image.crop(utils.geometry.region(viewportLocation, viewportSize))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return image
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function makeTakeMarkedScreenshot({driver, stabilization = {}, debug, logger}) {
|
|
91
|
+
let viewportRegion
|
|
92
|
+
|
|
93
|
+
return async function takeScreenshot({name} = {}) {
|
|
94
|
+
logger.verbose('Taking viewport screenshot (using markers)...')
|
|
95
|
+
const image = makeImage(await driver.takeScreenshot())
|
|
96
|
+
await image.debug({...debug, name, suffix: 'original'})
|
|
97
|
+
|
|
98
|
+
if (stabilization.scale) image.scale(stabilization.scale)
|
|
99
|
+
else image.scale(1 / driver.pixelRatio)
|
|
100
|
+
|
|
101
|
+
if (stabilization.rotate) image.rotate(stabilization.rotate)
|
|
102
|
+
else if (driver.orientation === 'landscape' && image.width < image.height) image.rotate(-90)
|
|
103
|
+
|
|
104
|
+
if (stabilization.crop) image.crop(stabilization.crop)
|
|
105
|
+
else {
|
|
106
|
+
if (!viewportRegion) viewportRegion = await getViewportRegion()
|
|
107
|
+
if (viewportRegion) image.crop(viewportRegion)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await image.debug({...debug, name, suffix: 'viewport'})
|
|
111
|
+
|
|
112
|
+
return image
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function getViewportRegion() {
|
|
116
|
+
const marker = await driver.mainContext.execute(snippets.addPageMarker)
|
|
117
|
+
await utils.general.sleep(100)
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const image = makeImage(await driver.takeScreenshot())
|
|
121
|
+
|
|
122
|
+
if (stabilization.rotate) image.rotate(stabilization.rotate)
|
|
123
|
+
else if (driver.orientation === 'landscape' && image.width < image.height) image.rotate(-90)
|
|
124
|
+
|
|
125
|
+
await image.debug({...debug, name: 'marker'})
|
|
126
|
+
|
|
127
|
+
const markerLocation = findImagePattern(await image.toObject(), {...marker, pixelRatio: driver.pixelRatio})
|
|
128
|
+
if (!markerLocation) return null
|
|
129
|
+
|
|
130
|
+
const viewportSize = await driver.getViewportSize()
|
|
131
|
+
|
|
132
|
+
return utils.geometry.region(utils.geometry.scale(markerLocation, 1 / driver.pixelRatio), viewportSize)
|
|
133
|
+
} finally {
|
|
134
|
+
await driver.mainContext.execute(snippets.cleanupPageMarker)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function makeTakeNativeScreenshot({driver, stabilization = {}, debug, logger}) {
|
|
140
|
+
return async function takeScreenshot({name, withStatusBar} = {}) {
|
|
141
|
+
logger.verbose('Taking native driver screenshot...')
|
|
142
|
+
const image = makeImage(await driver.takeScreenshot())
|
|
143
|
+
await image.debug({...debug, name, suffix: 'original'})
|
|
144
|
+
|
|
145
|
+
if (stabilization.scale) image.scale(stabilization.scale)
|
|
146
|
+
else image.scale(1 / driver.pixelRatio)
|
|
6
147
|
|
|
7
|
-
|
|
8
|
-
|
|
148
|
+
if (stabilization.rotate) image.rotate(stabilization.rotate)
|
|
149
|
+
else if (driver.orientation === 'landscape' && image.width < image.height) image.rotate(-90)
|
|
9
150
|
|
|
10
|
-
|
|
151
|
+
if (stabilization.crop) image.crop(stabilization.crop)
|
|
152
|
+
else {
|
|
153
|
+
const viewportSize = await driver.getViewportSize()
|
|
154
|
+
const cropRegion = withStatusBar
|
|
155
|
+
? {x: 0, y: 0, width: viewportSize.width, height: viewportSize.height + driver.statusBarHeight}
|
|
156
|
+
: {top: driver.statusBarHeight, bottom: driver.navigationBarHeight, left: 0, right: 0}
|
|
157
|
+
image.crop(cropRegion)
|
|
158
|
+
}
|
|
11
159
|
|
|
12
|
-
|
|
160
|
+
await image.debug({...debug, name, suffix: `viewport${withStatusBar ? '-with-statusbar' : ''}`})
|
|
13
161
|
|
|
14
|
-
|
|
15
|
-
const cropRegion = await driver.getRegionInViewport(context, region)
|
|
16
|
-
if (utils.geometry.isEmpty(cropRegion)) throw new Error('Screenshot region is out of viewport')
|
|
17
|
-
image.crop(cropRegion)
|
|
18
|
-
await image.debug({path: debug.path, suffix: 'region'})
|
|
19
|
-
return {image, region: cropRegion}
|
|
20
|
-
} else {
|
|
21
|
-
return {image, region: utils.geometry.region({x: 0, y: 0}, image.size)}
|
|
162
|
+
return image
|
|
22
163
|
}
|
|
23
164
|
}
|
|
24
165
|
|
|
25
|
-
module.exports =
|
|
166
|
+
module.exports = makeTakeViewportScreenshot
|
package/test/e2e/android.spec.js
CHANGED
|
@@ -3,7 +3,7 @@ const pixelmatch = require('pixelmatch')
|
|
|
3
3
|
const {Driver} = require('@applitools/driver')
|
|
4
4
|
const spec = require('@applitools/spec-driver-webdriverio')
|
|
5
5
|
const makeImage = require('../../src/image')
|
|
6
|
-
const
|
|
6
|
+
const takeScreenshot = require('../../index')
|
|
7
7
|
|
|
8
8
|
const env = {
|
|
9
9
|
android: {
|
|
@@ -20,6 +20,17 @@ const env = {
|
|
|
20
20
|
username: process.env.SAUCE_USERNAME,
|
|
21
21
|
accessKey: process.env.SAUCE_ACCESS_KEY,
|
|
22
22
|
},
|
|
23
|
+
|
|
24
|
+
// url: 'http://0.0.0.0:4723/wd/hub',
|
|
25
|
+
// capabilities: {
|
|
26
|
+
// deviceName: 'Google Pixel 3a XL',
|
|
27
|
+
// platformName: 'Android',
|
|
28
|
+
// platformVersion: '10.0',
|
|
29
|
+
// automationName: 'uiautomator2',
|
|
30
|
+
// nativeWebScreenshot: true,
|
|
31
|
+
// avd: 'Pixel_3a_XL',
|
|
32
|
+
// app: 'https://applitools.jfrog.io/artifactory/Examples/android/1.3/app-debug.apk',
|
|
33
|
+
// },
|
|
23
34
|
},
|
|
24
35
|
androidx: {
|
|
25
36
|
url: 'https://ondemand.saucelabs.com/wd/hub',
|
|
@@ -31,10 +42,20 @@ const env = {
|
|
|
31
42
|
appiumVersion: '1.20.2',
|
|
32
43
|
deviceName: 'Google Pixel 3a XL GoogleAPI Emulator',
|
|
33
44
|
automationName: 'uiautomator2',
|
|
34
|
-
app: 'https://applitools.jfrog.io/artifactory/Examples/androidx/1.
|
|
45
|
+
app: 'https://applitools.jfrog.io/artifactory/Examples/androidx/1.3.1/app_androidx.apk',
|
|
35
46
|
username: process.env.SAUCE_USERNAME,
|
|
36
47
|
accessKey: process.env.SAUCE_ACCESS_KEY,
|
|
37
48
|
},
|
|
49
|
+
|
|
50
|
+
// url: 'http://0.0.0.0:4723/wd/hub',
|
|
51
|
+
// capabilities: {
|
|
52
|
+
// deviceName: 'Google Pixel 3a XL',
|
|
53
|
+
// platformName: 'Android',
|
|
54
|
+
// platformVersion: '10.0',
|
|
55
|
+
// automationName: 'uiautomator2',
|
|
56
|
+
// avd: 'Pixel_3a_XL',
|
|
57
|
+
// app: 'https://applitools.jfrog.io/artifactory/Examples/androidx/1.3.3/app_androidx.apk',
|
|
58
|
+
// },
|
|
38
59
|
},
|
|
39
60
|
}
|
|
40
61
|
|
|
@@ -90,6 +111,10 @@ describe('screenshoter', () => {
|
|
|
90
111
|
return fullApp({type: 'non-scrollable'})
|
|
91
112
|
})
|
|
92
113
|
|
|
114
|
+
it.skip('take webview screenshot', () => {
|
|
115
|
+
return webview()
|
|
116
|
+
})
|
|
117
|
+
|
|
93
118
|
it('take region screenshot', () => {
|
|
94
119
|
return region()
|
|
95
120
|
})
|
|
@@ -122,6 +147,18 @@ describe('screenshoter', () => {
|
|
|
122
147
|
return fullApp({type: 'recycler', x: true})
|
|
123
148
|
})
|
|
124
149
|
|
|
150
|
+
it('take full app screenshot (collapsing layout)', () => {
|
|
151
|
+
return fullApp({type: 'collapsing', x: true})
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it.skip('take full app screenshot (pager)', () => {
|
|
155
|
+
return fullApp({type: 'pager', x: true})
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it.skip('take full app screenshot (overlapped status bar)', () => {
|
|
159
|
+
return fullApp({type: 'overlapped', x: true})
|
|
160
|
+
})
|
|
161
|
+
|
|
125
162
|
it('take full element screenshot', () => {
|
|
126
163
|
return fullElement()
|
|
127
164
|
})
|
|
@@ -130,7 +167,7 @@ describe('screenshoter', () => {
|
|
|
130
167
|
async function app(options = {}) {
|
|
131
168
|
const expectedPath = `./test/fixtures/android/app${options.withStatusBar ? '-statusbar' : ''}.png`
|
|
132
169
|
|
|
133
|
-
const screenshot = await
|
|
170
|
+
const screenshot = await takeScreenshot({logger, driver, wait: 1500, ...options})
|
|
134
171
|
try {
|
|
135
172
|
if (options.withStatusBar) await sanitizeStatusBar(screenshot.image)
|
|
136
173
|
const actual = await screenshot.image.toObject()
|
|
@@ -142,8 +179,18 @@ describe('screenshoter', () => {
|
|
|
142
179
|
}
|
|
143
180
|
}
|
|
144
181
|
async function fullApp({type, x, ...options} = {}) {
|
|
145
|
-
let buttonSelector, expectedPath
|
|
146
|
-
if (type === '
|
|
182
|
+
let buttonSelector, expectedPath, scrollingElementSelector
|
|
183
|
+
if (type === 'pager') {
|
|
184
|
+
buttonSelector = {type: 'id', selector: 'btn_view_pager_2_activity'}
|
|
185
|
+
expectedPath = `./test/fixtures/android/x-app-fully-pager${options.withStatusBar ? '-statusbar' : ''}.png`
|
|
186
|
+
} else if (type === 'overlapped') {
|
|
187
|
+
buttonSelector = {type: 'id', selector: 'btn_recycler_view_under_status_bar_activity'}
|
|
188
|
+
expectedPath = `./test/fixtures/android/x-app-fully-overlapped${options.withStatusBar ? '-statusbar' : ''}.png`
|
|
189
|
+
} else if (type === 'collapsing') {
|
|
190
|
+
buttonSelector = {type: 'id', selector: 'btn_recycler_view_nested_collapsing'}
|
|
191
|
+
scrollingElementSelector = {type: 'id', selector: 'recyclerView'}
|
|
192
|
+
expectedPath = `./test/fixtures/android/x-app-fully-collapsing${options.withStatusBar ? '-statusbar' : ''}.png`
|
|
193
|
+
} else if (type === 'recycler') {
|
|
147
194
|
if (x) {
|
|
148
195
|
buttonSelector = {type: 'id', selector: 'btn_recycler_view_activity'}
|
|
149
196
|
expectedPath = `./test/fixtures/android/x-app-fully-recycler${options.withStatusBar ? '-statusbar' : ''}.png`
|
|
@@ -152,7 +199,7 @@ describe('screenshoter', () => {
|
|
|
152
199
|
expectedPath = `./test/fixtures/android/app-fully-recycler${options.withStatusBar ? '-statusbar' : ''}.png`
|
|
153
200
|
}
|
|
154
201
|
} else if (type === 'non-scrollable') {
|
|
155
|
-
buttonSelector = {type: 'id', selector: '
|
|
202
|
+
buttonSelector = {type: 'id', selector: 'btn_activity_as_dialog'}
|
|
156
203
|
expectedPath = `./test/fixtures/android/app-fully-non-scrollable${options.withStatusBar ? '-statusbar' : ''}.png`
|
|
157
204
|
} else {
|
|
158
205
|
buttonSelector = {type: 'id', selector: 'btn_scroll_view_footer_header'}
|
|
@@ -162,7 +209,13 @@ describe('screenshoter', () => {
|
|
|
162
209
|
const button = await driver.element(buttonSelector)
|
|
163
210
|
await button.click()
|
|
164
211
|
|
|
165
|
-
|
|
212
|
+
await driver.init()
|
|
213
|
+
|
|
214
|
+
if (scrollingElementSelector) {
|
|
215
|
+
await driver.currentContext.setScrollingElement(scrollingElementSelector)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const screenshot = await takeScreenshot({
|
|
166
219
|
logger,
|
|
167
220
|
driver,
|
|
168
221
|
fully: true,
|
|
@@ -181,8 +234,28 @@ describe('screenshoter', () => {
|
|
|
181
234
|
throw err
|
|
182
235
|
}
|
|
183
236
|
}
|
|
237
|
+
async function webview(options) {
|
|
238
|
+
const expectedPath = `./test/fixtures/android/webview.png`
|
|
239
|
+
const buttonSelector = {type: 'id', selector: 'btn_web_view'}
|
|
240
|
+
|
|
241
|
+
const button = await driver.element(buttonSelector)
|
|
242
|
+
await button.click()
|
|
243
|
+
await driver.target.switchContext('WEBVIEW')
|
|
244
|
+
|
|
245
|
+
await driver.init()
|
|
246
|
+
|
|
247
|
+
const screenshot = await takeScreenshot({logger, driver, wait: 1500, ...options})
|
|
248
|
+
try {
|
|
249
|
+
const actual = await screenshot.image.toObject()
|
|
250
|
+
const expected = await makeImage(expectedPath).toObject()
|
|
251
|
+
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
|
|
252
|
+
} catch (err) {
|
|
253
|
+
await screenshot.image.debug({path: './logs', name: 'webview_failed', suffix: Date.now()})
|
|
254
|
+
throw err
|
|
255
|
+
}
|
|
256
|
+
}
|
|
184
257
|
async function region(options) {
|
|
185
|
-
const screenshot = await
|
|
258
|
+
const screenshot = await takeScreenshot({
|
|
186
259
|
logger,
|
|
187
260
|
driver,
|
|
188
261
|
region: {x: 30, y: 500, height: 100, width: 200},
|
|
@@ -199,7 +272,7 @@ describe('screenshoter', () => {
|
|
|
199
272
|
}
|
|
200
273
|
}
|
|
201
274
|
async function fullRegion(options) {
|
|
202
|
-
const screenshot = await
|
|
275
|
+
const screenshot = await takeScreenshot({
|
|
203
276
|
logger,
|
|
204
277
|
driver,
|
|
205
278
|
region: {x: 30, y: 10, height: 700, width: 200},
|
|
@@ -217,7 +290,7 @@ describe('screenshoter', () => {
|
|
|
217
290
|
}
|
|
218
291
|
}
|
|
219
292
|
async function element(options) {
|
|
220
|
-
const screenshot = await
|
|
293
|
+
const screenshot = await takeScreenshot({
|
|
221
294
|
logger,
|
|
222
295
|
driver,
|
|
223
296
|
region: {type: 'id', selector: 'btn_recycler_view'},
|
|
@@ -240,7 +313,7 @@ describe('screenshoter', () => {
|
|
|
240
313
|
})
|
|
241
314
|
await button.click()
|
|
242
315
|
|
|
243
|
-
const screenshot = await
|
|
316
|
+
const screenshot = await takeScreenshot({
|
|
244
317
|
logger,
|
|
245
318
|
driver,
|
|
246
319
|
region: {type: 'id', selector: 'recyclerView'},
|
|
@@ -4,7 +4,7 @@ const {Driver} = require('@applitools/driver')
|
|
|
4
4
|
const utils = require('@applitools/utils')
|
|
5
5
|
const spec = require('@applitools/spec-driver-webdriverio')
|
|
6
6
|
const makeImage = require('../../src/image')
|
|
7
|
-
const
|
|
7
|
+
const takeScreenshot = require('../../index')
|
|
8
8
|
|
|
9
9
|
describe.skip('external tests', () => {
|
|
10
10
|
const logger = {log: () => {}, warn: () => {}, error: () => {}, verbose: () => {}}
|
|
@@ -14,7 +14,7 @@ describe.skip('external tests', () => {
|
|
|
14
14
|
await destroyBrowser()
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
it('AGL - full app screenshot of the view with animated scroll', async () => {
|
|
17
|
+
it('AGL Android - full app screenshot of the view with animated scroll', async () => {
|
|
18
18
|
const expectedPath = `./test/fixtures/external/agl.png`
|
|
19
19
|
|
|
20
20
|
;[browser, destroyBrowser] = await spec.build({
|
|
@@ -23,7 +23,7 @@ describe.skip('external tests', () => {
|
|
|
23
23
|
platformName: 'android',
|
|
24
24
|
'appium:platformVersion': '11.0',
|
|
25
25
|
'appium:deviceName': 'Google Pixel 5',
|
|
26
|
-
'appium:app': '
|
|
26
|
+
'appium:app': 'agl_app_android',
|
|
27
27
|
'bstack:options': {
|
|
28
28
|
userName: process.env.BROWSERSTACK_USERNAME,
|
|
29
29
|
accessKey: process.env.BROWSERSTACK_ACCESS_KEY,
|
|
@@ -41,18 +41,17 @@ describe.skip('external tests', () => {
|
|
|
41
41
|
await utils.general.sleep(8000)
|
|
42
42
|
const signinBtn = await browser.$('//android.widget.Button[@text="SIGN IN"]')
|
|
43
43
|
await signinBtn.click()
|
|
44
|
-
await utils.general.sleep(
|
|
44
|
+
await utils.general.sleep(10000)
|
|
45
45
|
const emailInput = await browser.$('//android.widget.EditText')
|
|
46
46
|
await emailInput.setValue('daniel.martin@toro.com')
|
|
47
47
|
const nxtBtn = await browser.$('//android.widget.Button[@text="NEXT"]')
|
|
48
48
|
await nxtBtn.click()
|
|
49
|
-
await utils.general.sleep(
|
|
49
|
+
await utils.general.sleep(10000)
|
|
50
50
|
const passwordInput = await browser.$('//android.widget.EditText[@password="true"]')
|
|
51
51
|
await passwordInput.setValue('Welcome@1')
|
|
52
52
|
const loginBtn = await browser.$('//android.widget.Button[@text="LOGIN"]')
|
|
53
53
|
await loginBtn.click()
|
|
54
54
|
await utils.general.sleep(18000)
|
|
55
|
-
|
|
56
55
|
const skipBtn = await browser.$('//android.widget.Button[@text="SKIP"]')
|
|
57
56
|
await skipBtn.click()
|
|
58
57
|
await utils.general.sleep(5000)
|
|
@@ -60,11 +59,9 @@ describe.skip('external tests', () => {
|
|
|
60
59
|
await finishBtn.click()
|
|
61
60
|
await utils.general.sleep(15000)
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
// await billingBtn.click()
|
|
65
|
-
// await utils.general.sleep(25000)
|
|
62
|
+
await driver.init()
|
|
66
63
|
|
|
67
|
-
const screenshot = await
|
|
64
|
+
const screenshot = await takeScreenshot({
|
|
68
65
|
logger,
|
|
69
66
|
driver,
|
|
70
67
|
fully: true,
|
|
@@ -81,4 +78,78 @@ describe.skip('external tests', () => {
|
|
|
81
78
|
throw err
|
|
82
79
|
}
|
|
83
80
|
})
|
|
81
|
+
|
|
82
|
+
it('AGL iOS - full app screenshot of the view with animated scroll', async () => {
|
|
83
|
+
const expectedPath = `./test/fixtures/external/agl.png`
|
|
84
|
+
;[browser, destroyBrowser] = await spec.build({
|
|
85
|
+
url: 'https://hub.browserstack.com/wd/hub',
|
|
86
|
+
capabilities: {
|
|
87
|
+
platformName: 'ios',
|
|
88
|
+
'appium:platformVersion': '14',
|
|
89
|
+
'appium:deviceName': 'iPhone 12',
|
|
90
|
+
'appium:app': 'agl_app',
|
|
91
|
+
'appium:processArguments': `{
|
|
92
|
+
"args": [
|
|
93
|
+
"-dev.environment", "qtrtest",
|
|
94
|
+
"-dev.clear.keychain", "YES",
|
|
95
|
+
"-dev.keychain.shared", "NO",
|
|
96
|
+
"-user.lastQuickTourVersionCompleted", "0"
|
|
97
|
+
],
|
|
98
|
+
"env": {
|
|
99
|
+
"DYLD_INSERT_LIBRARIES": "@executable_path/Frameworks/EyesiOSHelper.xcframework/ios-arm64/EyesiOSHelper.framework/EyesiOSHelper"
|
|
100
|
+
}
|
|
101
|
+
}`,
|
|
102
|
+
'bstack:options': {
|
|
103
|
+
userName: process.env.BROWSERSTACK_USERNAME,
|
|
104
|
+
accessKey: process.env.BROWSERSTACK_ACCESS_KEY,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
await browser.closeApp()
|
|
110
|
+
await browser.launchApp()
|
|
111
|
+
const driver = await new Driver({driver: browser, spec, logger}).init()
|
|
112
|
+
|
|
113
|
+
await browser.acceptAlert()
|
|
114
|
+
|
|
115
|
+
await utils.general.sleep(8000)
|
|
116
|
+
const signinBtn = await browser.$('//XCUIElementTypeButton[@name="SIGN IN"]')
|
|
117
|
+
await signinBtn.click()
|
|
118
|
+
await utils.general.sleep(8000)
|
|
119
|
+
const emailInput = await browser.$('//XCUIElementTypeTextField')
|
|
120
|
+
await emailInput.setValue('daniel.martin@toro.com')
|
|
121
|
+
const nxtBtn = await browser.$('//XCUIElementTypeButton[@name="NEXT"]')
|
|
122
|
+
await nxtBtn.click()
|
|
123
|
+
await utils.general.sleep(8000)
|
|
124
|
+
const passwordInput = await browser.$('//XCUIElementTypeSecureTextField')
|
|
125
|
+
await passwordInput.setValue('Welcome@1')
|
|
126
|
+
const loginBtn = await browser.$('//XCUIElementTypeButton[@name="LOGIN"]')
|
|
127
|
+
await loginBtn.click()
|
|
128
|
+
await utils.general.sleep(18000)
|
|
129
|
+
const skipBtn = await browser.$('//XCUIElementTypeButton[@name="Skip"]')
|
|
130
|
+
await skipBtn.click()
|
|
131
|
+
await utils.general.sleep(5000)
|
|
132
|
+
const finishBtn = await browser.$('//XCUIElementTypeButton[@name="Finish"]')
|
|
133
|
+
await finishBtn.click()
|
|
134
|
+
await utils.general.sleep(20000)
|
|
135
|
+
|
|
136
|
+
await driver.init()
|
|
137
|
+
|
|
138
|
+
const screenshot = await takeScreenshot({
|
|
139
|
+
logger,
|
|
140
|
+
driver,
|
|
141
|
+
fully: true,
|
|
142
|
+
framed: true,
|
|
143
|
+
wait: 1500,
|
|
144
|
+
// debug: {path: './'},
|
|
145
|
+
})
|
|
146
|
+
try {
|
|
147
|
+
const actual = await screenshot.image.toObject()
|
|
148
|
+
const expected = await makeImage(expectedPath).toObject()
|
|
149
|
+
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
|
|
150
|
+
} catch (err) {
|
|
151
|
+
await screenshot.image.debug({path: './logs', name: 'viewport_failed', suffix: Date.now()})
|
|
152
|
+
throw err
|
|
153
|
+
}
|
|
154
|
+
})
|
|
84
155
|
})
|