@applitools/screenshoter 3.2.8 → 3.3.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.
Files changed (80) hide show
  1. package/.bongo/dry-run/package-lock.json +49 -6
  2. package/.bongo/dry-run/package.json +5 -0
  3. package/.bongo/dry-run.tgz +0 -0
  4. package/CHANGELOG.md +19 -0
  5. package/index.js +2 -1
  6. package/package.json +7 -4
  7. package/src/find-image-pattern.js +11 -38
  8. package/src/image.js +107 -64
  9. package/src/take-screenshot.js +136 -160
  10. package/src/take-simple-screenshot.js +25 -0
  11. package/src/take-stitched-screenshot.js +34 -40
  12. package/src/take-viewport-screenshot.js +179 -16
  13. package/test/e2e/android.spec.js +120 -13
  14. package/test/e2e/external.spec.js +155 -0
  15. package/test/e2e/ios.spec.js +142 -12
  16. package/test/e2e/web-ios.spec.js +19 -6
  17. package/test/e2e/web.spec.js +33 -21
  18. package/test/fixtures/android/app-fully-non-scrollable.png +0 -0
  19. package/test/fixtures/android/app-fully-recycler.png +0 -0
  20. package/test/fixtures/android/app-fully-scroll-statusbar.png +0 -0
  21. package/test/fixtures/android/app-fully-scroll.png +0 -0
  22. package/test/fixtures/android/app-statusbar.png +0 -0
  23. package/test/fixtures/android/x-app-fully-collapsing.png +0 -0
  24. package/test/fixtures/android/x-app-fully-recycler.png +0 -0
  25. package/test/fixtures/android/x-element-fully.png +0 -0
  26. package/test/fixtures/external/agl.png +0 -0
  27. package/test/fixtures/image/{house.combined-higher-wider.png → house.framed-higher-wider.png} +0 -0
  28. package/test/fixtures/image/{house.combined-higher.png → house.framed-higher.png} +0 -0
  29. package/test/fixtures/image/house.framed-shorter-thinner.png +0 -0
  30. package/test/fixtures/image/{house.combined-wider.png → house.framed-wider.png} +0 -0
  31. package/test/fixtures/ios/app-fully-collapsing.png +0 -0
  32. package/test/fixtures/ios/app-fully-collection.png +0 -0
  33. package/test/fixtures/ios/app-fully-overlapped-statusbar.png +0 -0
  34. package/test/fixtures/ios/app-fully-overlapped.png +0 -0
  35. package/test/fixtures/ios/app-fully-scroll-statusbar.png +0 -0
  36. package/test/fixtures/ios/app-fully-scroll.png +0 -0
  37. package/test/fixtures/ios/app-fully-superview.png +0 -0
  38. package/test/fixtures/ios/app-fully-table.png +0 -0
  39. package/test/fixtures/ios/app-statusbar.png +0 -0
  40. package/test/fixtures/ios/app.png +0 -0
  41. package/test/fixtures/ios/element-fully.png +0 -0
  42. package/test/fixtures/ios/element.png +0 -0
  43. package/test/fixtures/ios/region.png +0 -0
  44. package/test/fixtures/ios/webview-fully.png +0 -0
  45. package/test/fixtures/ios/webview.png +0 -0
  46. package/test/fixtures/pattern/iPad_5th_landscape.png +0 -0
  47. package/test/fixtures/pattern/iPad_5th_portrait.png +0 -0
  48. package/test/fixtures/pattern/iPad_9th_landscape.png +0 -0
  49. package/test/fixtures/pattern/iPad_9th_portrait.png +0 -0
  50. package/test/fixtures/pattern/iPhone_11_landscape.png +0 -0
  51. package/test/fixtures/pattern/iPhone_11_portrait.png +0 -0
  52. package/test/fixtures/pattern/iPhone_13_landscape.png +0 -0
  53. package/test/fixtures/pattern/iPhone_13_portrait.png +0 -0
  54. package/test/fixtures/pattern/iPhone_SE_landscape.png +0 -0
  55. package/test/fixtures/pattern/iPhone_SE_portrait.png +0 -0
  56. package/test/fixtures/pattern/iPhone_XS_portrait_noviewport.png +0 -0
  57. package/test/fixtures/web/frame-fully.png +0 -0
  58. package/test/fixtures/web/frame.png +0 -0
  59. package/test/fixtures/web/inner-element-fully.png +0 -0
  60. package/test/fixtures/web/inner-element.png +0 -0
  61. package/test/fixtures/web/inner-region-fully.png +0 -0
  62. package/test/fixtures/web/inner-region.png +0 -0
  63. package/test/fixtures/web/page-fully.png +0 -0
  64. package/test/fixtures/web/page.png +0 -0
  65. package/test/fixtures/web/region-fully.png +0 -0
  66. package/test/fixtures/web/region.png +0 -0
  67. package/test/fixtures/web-ios/page-fully.png +0 -0
  68. package/test/it/find-pattern.spec.js +16 -11
  69. package/test/it/image.spec.js +42 -15
  70. package/docker-compose.yaml +0 -29
  71. package/src/calculate-screenshot-regions.js +0 -31
  72. package/src/screenshoter.js +0 -158
  73. package/test/fixtures/pattern/iPad_Air_portrait.png +0 -0
  74. package/test/fixtures/pattern/iPhone_5S_landscape.png +0 -0
  75. package/test/fixtures/pattern/iPhone_XR_perfecto_landscape.png +0 -0
  76. package/test/fixtures/pattern/iPhone_XS_Max_perfecto_landscape.png +0 -0
  77. package/test/fixtures/pattern/iPhone_XS_landscape.png +0 -0
  78. package/test/fixtures/pattern/iPhone_XS_portrait.png +0 -0
  79. package/test/fixtures/pattern/iPhone_X_perfecto_portrait.png +0 -0
  80. package/test/util/spec-driver.js +0 -288
@@ -1,25 +1,188 @@
1
1
  const utils = require('@applitools/utils')
2
- const makeTakeScreenshot = require('./take-screenshot')
2
+ const snippets = require('@applitools/snippets')
3
+ const findImagePattern = require('./find-image-pattern')
4
+ const makeImage = require('./image')
3
5
 
4
- async function takeViewportScreenshot({context, region, withStatusBar, wait, stabilization, debug = {}, logger}) {
5
- logger.verbose('Taking image of...')
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
+ const calculateScaleRatio = makeCalculateScaleRatio({driver})
31
+ return async function takeScreenshot({name} = {}) {
32
+ logger.verbose('Taking screenshot...')
33
+ const image = makeImage(await driver.takeScreenshot())
34
+ await image.debug({...debug, name, suffix: 'original'})
35
+
36
+ if (stabilization.scale) image.scale(stabilization.scale)
37
+ else image.scale(await calculateScaleRatio(image.width))
38
+
39
+ if (stabilization.rotate) image.crop(stabilization.rotate)
40
+
41
+ if (stabilization.crop) image.crop(stabilization.crop)
42
+
43
+ return image
44
+ }
45
+ }
46
+
47
+ function makeTakeMainContextScreenshot({driver, stabilization = {}, debug, logger}) {
48
+ const calculateScaleRatio = makeCalculateScaleRatio({driver})
49
+ return async function takeScreenshot({name} = {}) {
50
+ logger.verbose('Taking screenshot...')
51
+ const originalContext = driver.currentContext
52
+ await driver.mainContext.focus()
53
+ const image = makeImage(await driver.takeScreenshot())
54
+ await originalContext.focus()
55
+ await image.debug({...debug, name, suffix: 'original'})
56
+
57
+ if (stabilization.scale) image.scale(stabilization.scale)
58
+ else image.scale(await calculateScaleRatio(image.width))
59
+
60
+ if (stabilization.rotate) image.rotate(stabilization.rotate)
61
+
62
+ if (stabilization.crop) image.crop(stabilization.crop)
63
+
64
+ return image
65
+ }
66
+ }
67
+
68
+ function makeTakeSafari11Screenshot({driver, stabilization = {}, debug, logger}) {
69
+ const calculateScaleRatio = makeCalculateScaleRatio({driver})
70
+ let viewportSize
71
+
72
+ return async function takeScreenshot({name} = {}) {
73
+ logger.verbose('Taking safari 11 driver screenshot...')
74
+ const image = makeImage(await driver.takeScreenshot())
75
+ await image.debug({...debug, name, suffix: 'original'})
76
+
77
+ if (stabilization.scale) image.scale(stabilization.scale)
78
+ else image.scale(await calculateScaleRatio(image.width))
79
+
80
+ if (stabilization.rotate) image.rotate(stabilization.rotate)
81
+
82
+ if (stabilization.crop) image.crop(stabilization.crop)
83
+ else {
84
+ if (!viewportSize) viewportSize = await driver.getViewportSize()
85
+ const viewportLocation = await driver.mainContext.execute(snippets.getElementScrollOffset, [])
86
+ image.crop(utils.geometry.region(viewportLocation, viewportSize))
87
+ }
88
+
89
+ return image
90
+ }
91
+ }
92
+
93
+ function makeTakeMarkedScreenshot({driver, stabilization = {}, debug, logger}) {
94
+ const calculateScaleRatio = makeCalculateScaleRatio({driver})
95
+ let viewportRegion
96
+
97
+ return async function takeScreenshot({name} = {}) {
98
+ logger.verbose('Taking viewport screenshot (using markers)...')
99
+ const image = makeImage(await driver.takeScreenshot())
100
+ await image.debug({...debug, name, suffix: 'original'})
101
+
102
+ if (stabilization.scale) image.scale(stabilization.scale)
103
+ else image.scale(await calculateScaleRatio(image.width))
104
+
105
+ if (stabilization.rotate) image.rotate(stabilization.rotate)
106
+
107
+ if (stabilization.crop) image.crop(stabilization.crop)
108
+ else {
109
+ if (!viewportRegion) viewportRegion = await getViewportRegion()
110
+ if (viewportRegion) image.crop(viewportRegion)
111
+ }
112
+
113
+ await image.debug({...debug, name, suffix: 'viewport'})
114
+
115
+ return image
116
+ }
117
+
118
+ async function getViewportRegion() {
119
+ const marker = await driver.mainContext.execute(snippets.addPageMarker)
120
+ await utils.general.sleep(100)
121
+
122
+ try {
123
+ const image = makeImage(await driver.takeScreenshot())
124
+
125
+ if (stabilization.rotate) await image.rotate(stabilization.rotate)
6
126
 
7
- const driver = context.driver
8
- const takeScreenshot = makeTakeScreenshot({logger, driver, stabilization, debug})
127
+ await image.debug({...debug, name: 'marker'})
9
128
 
10
- await utils.general.sleep(wait)
129
+ const markerLocation = findImagePattern(await image.toObject(), {...marker, pixelRatio: driver.pixelRatio})
130
+ if (!markerLocation) return null
131
+
132
+ const viewportSize = await driver.getViewportSize()
133
+
134
+ return utils.geometry.region(utils.geometry.scale(markerLocation, 1 / driver.pixelRatio), viewportSize)
135
+ } finally {
136
+ await driver.mainContext.execute(snippets.cleanupPageMarker)
137
+ }
138
+ }
139
+ }
140
+
141
+ function makeTakeNativeScreenshot({driver, stabilization = {}, debug, logger}) {
142
+ return async function takeScreenshot({name, withStatusBar} = {}) {
143
+ logger.verbose('Taking native driver screenshot...')
144
+ const image = makeImage(await driver.takeScreenshot())
145
+ await image.debug({...debug, name, suffix: 'original'})
146
+
147
+ if (stabilization.scale) image.scale(stabilization.scale)
148
+ else image.scale(1 / driver.pixelRatio)
149
+
150
+ if (stabilization.rotate) image.rotate(stabilization.rotate)
151
+
152
+ if (stabilization.crop) image.crop(stabilization.crop)
153
+ else {
154
+ const viewportSize = await driver.getViewportSize()
155
+ const cropRegion = withStatusBar
156
+ ? {x: 0, y: 0, width: viewportSize.width, height: viewportSize.height + driver.statusBarHeight}
157
+ : {top: driver.statusBarHeight, bottom: driver.navigationBarHeight, left: 0, right: 0}
158
+ image.crop(cropRegion)
159
+ }
160
+
161
+ await image.debug({...debug, name, suffix: `viewport${withStatusBar ? '-with-statusbar' : ''}`})
162
+
163
+ return image
164
+ }
165
+ }
11
166
 
12
- const image = await takeScreenshot({withStatusBar})
167
+ function makeCalculateScaleRatio({driver}) {
168
+ let viewportWidth, contentWidth
169
+ const VIEWPORT_THRESHOLD = 1
170
+ const CONTENT_THRESHOLD = 10
171
+ return async function calculateScaleRatio(imageWidth) {
172
+ if (!viewportWidth) viewportWidth = await driver.getViewportSize().then(size => size.width)
173
+ if (!contentWidth) contentWidth = await driver.mainContext.getContentSize().then(size => size.width)
174
+ // If the image's width is the same as the viewport's width or the
175
+ // top level context's width, no scaling is necessary.
176
+ if (
177
+ (imageWidth >= viewportWidth - VIEWPORT_THRESHOLD && imageWidth <= viewportWidth + VIEWPORT_THRESHOLD) ||
178
+ (imageWidth >= contentWidth - CONTENT_THRESHOLD && imageWidth <= contentWidth + CONTENT_THRESHOLD)
179
+ ) {
180
+ return 1
181
+ }
13
182
 
14
- if (region) {
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)}
183
+ const scaledImageWidth = Math.round(imageWidth / driver.pixelRatio)
184
+ return viewportWidth / scaledImageWidth / driver.pixelRatio
22
185
  }
23
186
  }
24
187
 
25
- module.exports = takeViewportScreenshot
188
+ module.exports = makeTakeViewportScreenshot
@@ -1,9 +1,63 @@
1
1
  const assert = require('assert')
2
2
  const pixelmatch = require('pixelmatch')
3
3
  const {Driver} = require('@applitools/driver')
4
- const spec = require('../util/spec-driver')
4
+ const spec = require('@applitools/spec-driver-webdriverio')
5
5
  const makeImage = require('../../src/image')
6
- const screenshoter = require('../../index')
6
+ const takeScreenshot = require('../../index')
7
+
8
+ const env = {
9
+ android: {
10
+ url: 'https://ondemand.saucelabs.com/wd/hub',
11
+ capabilities: {
12
+ name: 'Android Screenshoter Test',
13
+ browserName: '',
14
+ platformName: 'Android',
15
+ platformVersion: '7.0',
16
+ appiumVersion: '1.20.2',
17
+ deviceName: 'Samsung Galaxy S8 FHD GoogleAPI Emulator',
18
+ automationName: 'uiautomator2',
19
+ app: 'https://applitools.jfrog.io/artifactory/Examples/android/1.3/app-debug.apk',
20
+ username: process.env.SAUCE_USERNAME,
21
+ accessKey: process.env.SAUCE_ACCESS_KEY,
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
+ // },
34
+ },
35
+ androidx: {
36
+ url: 'https://ondemand.saucelabs.com/wd/hub',
37
+ capabilities: {
38
+ name: 'AndroidX Screenshoter Test',
39
+ browserName: '',
40
+ platformName: 'Android',
41
+ platformVersion: '10.0',
42
+ appiumVersion: '1.20.2',
43
+ deviceName: 'Google Pixel 3a XL GoogleAPI Emulator',
44
+ automationName: 'uiautomator2',
45
+ app: 'https://applitools.jfrog.io/artifactory/Examples/androidx/1.3.1/app_androidx.apk',
46
+ username: process.env.SAUCE_USERNAME,
47
+ accessKey: process.env.SAUCE_ACCESS_KEY,
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
+ // },
59
+ },
60
+ }
7
61
 
8
62
  describe('screenshoter', () => {
9
63
  const logger = {log: () => {}, warn: () => {}, error: () => {}, verbose: () => {}}
@@ -20,7 +74,7 @@ describe('screenshoter', () => {
20
74
 
21
75
  describe('android app', () => {
22
76
  before(async () => {
23
- ;[browser, destroyBrowser] = await spec.build({type: 'android'})
77
+ ;[browser, destroyBrowser] = await spec.build(env.android)
24
78
  })
25
79
 
26
80
  after(async () => {
@@ -57,6 +111,10 @@ describe('screenshoter', () => {
57
111
  return fullApp({type: 'non-scrollable'})
58
112
  })
59
113
 
114
+ it.skip('take webview screenshot', () => {
115
+ return webview()
116
+ })
117
+
60
118
  it('take region screenshot', () => {
61
119
  return region()
62
120
  })
@@ -72,7 +130,7 @@ describe('screenshoter', () => {
72
130
 
73
131
  describe('androidx app', () => {
74
132
  before(async () => {
75
- ;[browser, destroyBrowser] = await spec.build({type: 'androidx'})
133
+ ;[browser, destroyBrowser] = await spec.build(env.androidx)
76
134
  })
77
135
 
78
136
  after(async () => {
@@ -89,6 +147,18 @@ describe('screenshoter', () => {
89
147
  return fullApp({type: 'recycler', x: true})
90
148
  })
91
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
+
92
162
  it('take full element screenshot', () => {
93
163
  return fullElement()
94
164
  })
@@ -97,7 +167,7 @@ describe('screenshoter', () => {
97
167
  async function app(options = {}) {
98
168
  const expectedPath = `./test/fixtures/android/app${options.withStatusBar ? '-statusbar' : ''}.png`
99
169
 
100
- const screenshot = await screenshoter({logger, driver, wait: 1500, ...options})
170
+ const screenshot = await takeScreenshot({logger, driver, wait: 1500, ...options})
101
171
  try {
102
172
  if (options.withStatusBar) await sanitizeStatusBar(screenshot.image)
103
173
  const actual = await screenshot.image.toObject()
@@ -109,8 +179,18 @@ describe('screenshoter', () => {
109
179
  }
110
180
  }
111
181
  async function fullApp({type, x, ...options} = {}) {
112
- let buttonSelector, expectedPath
113
- if (type === 'recycler') {
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') {
114
194
  if (x) {
115
195
  buttonSelector = {type: 'id', selector: 'btn_recycler_view_activity'}
116
196
  expectedPath = `./test/fixtures/android/x-app-fully-recycler${options.withStatusBar ? '-statusbar' : ''}.png`
@@ -119,7 +199,7 @@ describe('screenshoter', () => {
119
199
  expectedPath = `./test/fixtures/android/app-fully-recycler${options.withStatusBar ? '-statusbar' : ''}.png`
120
200
  }
121
201
  } else if (type === 'non-scrollable') {
122
- buttonSelector = {type: 'id', selector: 'btn_edit_text'}
202
+ buttonSelector = {type: 'id', selector: 'btn_activity_as_dialog'}
123
203
  expectedPath = `./test/fixtures/android/app-fully-non-scrollable${options.withStatusBar ? '-statusbar' : ''}.png`
124
204
  } else {
125
205
  buttonSelector = {type: 'id', selector: 'btn_scroll_view_footer_header'}
@@ -129,7 +209,13 @@ describe('screenshoter', () => {
129
209
  const button = await driver.element(buttonSelector)
130
210
  await button.click()
131
211
 
132
- const screenshot = await screenshoter({
212
+ await driver.init()
213
+
214
+ if (scrollingElementSelector) {
215
+ await driver.currentContext.setScrollingElement(scrollingElementSelector)
216
+ }
217
+
218
+ const screenshot = await takeScreenshot({
133
219
  logger,
134
220
  driver,
135
221
  fully: true,
@@ -148,8 +234,29 @@ describe('screenshoter', () => {
148
234
  throw err
149
235
  }
150
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
+ console.log(await driver.target.getContexts())
244
+ await driver.target.switchContext('WEBVIEW')
245
+
246
+ await driver.init()
247
+
248
+ const screenshot = await takeScreenshot({logger, driver, wait: 1500, ...options})
249
+ try {
250
+ const actual = await screenshot.image.toObject()
251
+ const expected = await makeImage(expectedPath).toObject()
252
+ assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
253
+ } catch (err) {
254
+ await screenshot.image.debug({path: './logs', name: 'webview_failed', suffix: Date.now()})
255
+ throw err
256
+ }
257
+ }
151
258
  async function region(options) {
152
- const screenshot = await screenshoter({
259
+ const screenshot = await takeScreenshot({
153
260
  logger,
154
261
  driver,
155
262
  region: {x: 30, y: 500, height: 100, width: 200},
@@ -166,7 +273,7 @@ describe('screenshoter', () => {
166
273
  }
167
274
  }
168
275
  async function fullRegion(options) {
169
- const screenshot = await screenshoter({
276
+ const screenshot = await takeScreenshot({
170
277
  logger,
171
278
  driver,
172
279
  region: {x: 30, y: 10, height: 700, width: 200},
@@ -184,7 +291,7 @@ describe('screenshoter', () => {
184
291
  }
185
292
  }
186
293
  async function element(options) {
187
- const screenshot = await screenshoter({
294
+ const screenshot = await takeScreenshot({
188
295
  logger,
189
296
  driver,
190
297
  region: {type: 'id', selector: 'btn_recycler_view'},
@@ -207,7 +314,7 @@ describe('screenshoter', () => {
207
314
  })
208
315
  await button.click()
209
316
 
210
- const screenshot = await screenshoter({
317
+ const screenshot = await takeScreenshot({
211
318
  logger,
212
319
  driver,
213
320
  region: {type: 'id', selector: 'recyclerView'},
@@ -0,0 +1,155 @@
1
+ const assert = require('assert')
2
+ const pixelmatch = require('pixelmatch')
3
+ const {Driver} = require('@applitools/driver')
4
+ const utils = require('@applitools/utils')
5
+ const spec = require('@applitools/spec-driver-webdriverio')
6
+ const makeImage = require('../../src/image')
7
+ const takeScreenshot = require('../../index')
8
+
9
+ describe.skip('external tests', () => {
10
+ const logger = {log: () => {}, warn: () => {}, error: () => {}, verbose: () => {}}
11
+ let browser, destroyBrowser
12
+
13
+ afterEach(async () => {
14
+ await destroyBrowser()
15
+ })
16
+
17
+ it('AGL Android - full app screenshot of the view with animated scroll', async () => {
18
+ const expectedPath = `./test/fixtures/external/agl.png`
19
+
20
+ ;[browser, destroyBrowser] = await spec.build({
21
+ url: 'https://hub.browserstack.com/wd/hub',
22
+ capabilities: {
23
+ platformName: 'android',
24
+ 'appium:platformVersion': '11.0',
25
+ 'appium:deviceName': 'Google Pixel 5',
26
+ 'appium:app': 'agl_app_android',
27
+ 'bstack:options': {
28
+ userName: process.env.BROWSERSTACK_USERNAME,
29
+ accessKey: process.env.BROWSERSTACK_ACCESS_KEY,
30
+ },
31
+ },
32
+ })
33
+
34
+ await browser.closeApp()
35
+ await browser.launchApp()
36
+ const driver = await new Driver({driver: browser, spec, logger}).init()
37
+
38
+ const saveBtn = await browser.$('//android.widget.Button')
39
+ await saveBtn.click()
40
+
41
+ await utils.general.sleep(8000)
42
+ const signinBtn = await browser.$('//android.widget.Button[@text="SIGN IN"]')
43
+ await signinBtn.click()
44
+ await utils.general.sleep(10000)
45
+ const emailInput = await browser.$('//android.widget.EditText')
46
+ await emailInput.setValue('daniel.martin@toro.com')
47
+ const nxtBtn = await browser.$('//android.widget.Button[@text="NEXT"]')
48
+ await nxtBtn.click()
49
+ await utils.general.sleep(10000)
50
+ const passwordInput = await browser.$('//android.widget.EditText[@password="true"]')
51
+ await passwordInput.setValue('Welcome@1')
52
+ const loginBtn = await browser.$('//android.widget.Button[@text="LOGIN"]')
53
+ await loginBtn.click()
54
+ await utils.general.sleep(18000)
55
+ const skipBtn = await browser.$('//android.widget.Button[@text="SKIP"]')
56
+ await skipBtn.click()
57
+ await utils.general.sleep(5000)
58
+ const finishBtn = await browser.$('//android.widget.Button[@text="FINISH"]')
59
+ await finishBtn.click()
60
+ await utils.general.sleep(15000)
61
+
62
+ await driver.init()
63
+
64
+ const screenshot = await takeScreenshot({
65
+ logger,
66
+ driver,
67
+ fully: true,
68
+ framed: true,
69
+ stabilization: {crop: {top: 53, bottom: 16, left: 0, right: 0}},
70
+ debug: {path: './'},
71
+ })
72
+ try {
73
+ const actual = await screenshot.image.toObject()
74
+ const expected = await makeImage(expectedPath).toObject()
75
+ assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
76
+ } catch (err) {
77
+ await screenshot.image.debug({path: './logs', name: 'viewport_failed', suffix: Date.now()})
78
+ throw err
79
+ }
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
+ })
155
+ })