@applitools/screenshoter 3.3.1 → 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 (32) hide show
  1. package/.bongo/dry-run/package-lock.json +11 -11
  2. package/.bongo/dry-run.tgz +0 -0
  3. package/CHANGELOG.md +5 -0
  4. package/package.json +3 -3
  5. package/src/find-image-pattern.js +2 -1
  6. package/src/take-viewport-screenshot.js +8 -8
  7. package/test/e2e/android.spec.js +44 -1
  8. package/test/e2e/ios.spec.js +82 -5
  9. package/test/fixtures/ios/app-fully-collapsing.png +0 -0
  10. package/test/fixtures/ios/app-fully-collection.png +0 -0
  11. package/test/fixtures/ios/app-fully-overlapped-statusbar.png +0 -0
  12. package/test/fixtures/ios/app-fully-overlapped.png +0 -0
  13. package/test/fixtures/ios/app-fully-scroll-statusbar.png +0 -0
  14. package/test/fixtures/ios/app-fully-scroll.png +0 -0
  15. package/test/fixtures/ios/app-fully-superview.png +0 -0
  16. package/test/fixtures/ios/app-fully-table.png +0 -0
  17. package/test/fixtures/ios/app-statusbar.png +0 -0
  18. package/test/fixtures/ios/app.png +0 -0
  19. package/test/fixtures/ios/element-fully.png +0 -0
  20. package/test/fixtures/ios/element.png +0 -0
  21. package/test/fixtures/ios/region.png +0 -0
  22. package/test/fixtures/ios/webview-fully.png +0 -0
  23. package/test/fixtures/ios/webview.png +0 -0
  24. package/test/fixtures/web-ios/page-fully.png +0 -0
  25. package/test/fixtures/web-ios/page.png +0 -0
  26. package/test/it/find-pattern.spec.js +1 -1
  27. package/logs/screenshot_2021_12_16_19_06_06_332Z_full_app_failed_1639681566332.png +0 -0
  28. package/logs/screenshot_2021_12_16_19_15_59_935Z_full_app_failed_1639682159935.png +0 -0
  29. package/logs/screenshot_2021_12_16_19_33_20_679Z_full_app_failed_1639683200679.png +0 -0
  30. package/logs/screenshot_2021_12_16_19_37_22_120Z_ios_viewport_failed.png +0 -0
  31. package/logs/screenshot_2021_12_16_19_38_09_461Z_ios_full_page_failed.png +0 -0
  32. package/logs/screenshot_2021_12_16_19_59_45_182Z_ios_viewport_failed.png +0 -0
@@ -9,12 +9,12 @@
9
9
  }
10
10
  },
11
11
  "node_modules/@applitools/screenshoter": {
12
- "version": "3.3.0",
12
+ "version": "3.3.1",
13
13
  "resolved": "file:../dry-run.tgz",
14
- "integrity": "sha512-zYK7fJkhpV4xrOXwkOo/WAjdH8m9vLaWZVaGAGv9iFWdVp/WkdoFfEfU0uo4TAiJeodkq90QWB5krBljy+CBKA==",
14
+ "integrity": "sha512-Nn4m2tV2g1+ECbNzbJ4NJzvpx02lYAZ6MM4HXuT16ShCZPXi2fCuvnJEZX3D5j/EkZjEB6yFZWXrKT70m2Djew==",
15
15
  "license": "SEE LICENSE IN LICENSE",
16
16
  "dependencies": {
17
- "@applitools/snippets": "2.1.8",
17
+ "@applitools/snippets": "2.1.10",
18
18
  "@applitools/utils": "1.2.4",
19
19
  "png-async": "0.9.4"
20
20
  },
@@ -23,9 +23,9 @@
23
23
  }
24
24
  },
25
25
  "node_modules/@applitools/snippets": {
26
- "version": "2.1.8",
27
- "resolved": "https://registry.npmjs.org/@applitools/snippets/-/snippets-2.1.8.tgz",
28
- "integrity": "sha512-7CGFsbL9vAd6MBiGLVKHpKYywPXN499/fJMzEAVCLuGCY81CIc/PchqPFWrZZKZOY/IV21RJmE3MvqZAeXTIXA==",
26
+ "version": "2.1.10",
27
+ "resolved": "https://registry.npmjs.org/@applitools/snippets/-/snippets-2.1.10.tgz",
28
+ "integrity": "sha512-LGjtd8IZOwbhETqKRDX9CX85+BskkFUkuMuLvriSDEEQiSm0MpFbbcJVMjYaVL2qobaJbY+3WvK0g7+gkZuuqA==",
29
29
  "engines": {
30
30
  "node": ">=8.9.0"
31
31
  }
@@ -47,17 +47,17 @@
47
47
  "dependencies": {
48
48
  "@applitools/screenshoter": {
49
49
  "version": "file:../dry-run.tgz",
50
- "integrity": "sha512-zYK7fJkhpV4xrOXwkOo/WAjdH8m9vLaWZVaGAGv9iFWdVp/WkdoFfEfU0uo4TAiJeodkq90QWB5krBljy+CBKA==",
50
+ "integrity": "sha512-Nn4m2tV2g1+ECbNzbJ4NJzvpx02lYAZ6MM4HXuT16ShCZPXi2fCuvnJEZX3D5j/EkZjEB6yFZWXrKT70m2Djew==",
51
51
  "requires": {
52
- "@applitools/snippets": "2.1.8",
52
+ "@applitools/snippets": "2.1.10",
53
53
  "@applitools/utils": "1.2.4",
54
54
  "png-async": "0.9.4"
55
55
  }
56
56
  },
57
57
  "@applitools/snippets": {
58
- "version": "2.1.8",
59
- "resolved": "https://registry.npmjs.org/@applitools/snippets/-/snippets-2.1.8.tgz",
60
- "integrity": "sha512-7CGFsbL9vAd6MBiGLVKHpKYywPXN499/fJMzEAVCLuGCY81CIc/PchqPFWrZZKZOY/IV21RJmE3MvqZAeXTIXA=="
58
+ "version": "2.1.10",
59
+ "resolved": "https://registry.npmjs.org/@applitools/snippets/-/snippets-2.1.10.tgz",
60
+ "integrity": "sha512-LGjtd8IZOwbhETqKRDX9CX85+BskkFUkuMuLvriSDEEQiSm0MpFbbcJVMjYaVL2qobaJbY+3WvK0g7+gkZuuqA=="
61
61
  },
62
62
  "@applitools/utils": {
63
63
  "version": "1.2.4",
Binary file
package/CHANGELOG.md CHANGED
@@ -4,6 +4,11 @@
4
4
  ## Unreleased
5
5
 
6
6
 
7
+ ## 3.3.2 - 2021/12/20
8
+
9
+ - add basic support of webview screenshots on ios
10
+ - updated to @applitools/snippets@2.1.10 (from 2.1.8)
11
+
7
12
  ## 3.3.1 - 2021/12/17
8
13
 
9
14
  - no changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/screenshoter",
3
- "version": "3.3.1",
3
+ "version": "3.3.2",
4
4
  "description": "Applitools universal screenshoter for web and native applications",
5
5
  "keywords": [
6
6
  "applitools",
@@ -49,12 +49,12 @@
49
49
  }
50
50
  },
51
51
  "dependencies": {
52
- "@applitools/snippets": "2.1.8",
52
+ "@applitools/snippets": "2.1.10",
53
53
  "@applitools/utils": "1.2.4",
54
54
  "png-async": "0.9.4"
55
55
  },
56
56
  "devDependencies": {
57
- "@applitools/driver": "1.4.2",
57
+ "@applitools/driver": "1.4.5",
58
58
  "@applitools/sdk-release-kit": "0.13.4",
59
59
  "@applitools/spec-driver-webdriverio": "1.2.2",
60
60
  "@applitools/test-utils": "1.0.10",
@@ -1,7 +1,8 @@
1
1
  function findImagePattern(image, pattern) {
2
2
  for (let pixel = 0; pixel < image.width * image.height; ++pixel) {
3
3
  if (isPattern(image, pixel, pattern)) {
4
- return {x: (pixel % image.width) - pattern.offset, y: Math.floor(pixel / image.width) - pattern.offset}
4
+ const patterOffset = pattern.offset * pattern.pixelRatio
5
+ return {x: (pixel % image.width) - patterOffset, y: Math.floor(pixel / image.width) - patterOffset}
5
6
  }
6
7
  }
7
8
  return null
@@ -7,6 +7,9 @@ function makeTakeViewportScreenshot(options) {
7
7
  const {driver} = options
8
8
  if (driver.isNative) {
9
9
  return makeTakeNativeScreenshot(options)
10
+ } else if (driver.isIOS) {
11
+ // safari on ios takes screenshot with browser and os interfaces
12
+ return makeTakeMarkedScreenshot(options)
10
13
  } else if (driver.browserName === 'Firefox') {
11
14
  try {
12
15
  const browserVersion = Number.parseInt(driver.browserVersion, 10)
@@ -15,14 +18,9 @@ function makeTakeViewportScreenshot(options) {
15
18
  return makeTakeMainContextScreenshot(options)
16
19
  }
17
20
  } catch (ignored) {}
18
- } else if (driver.browserName === 'Safari') {
19
- if (driver.isIOS) {
20
- // safari on ios takes screenshot with browser and os interfaces
21
- return makeTakeMarkedScreenshot(options)
22
- } else if (driver.browserVersion === '11') {
23
- // safari 11 on macs takes full page screenshot
24
- return makeTakeSafari11Screenshot(options)
25
- }
21
+ } else if (driver.browserName === 'Safari' && driver.browserVersion === '11') {
22
+ // safari 11 on macs takes full page screenshot
23
+ return makeTakeSafari11Screenshot(options)
26
24
  }
27
25
 
28
26
  return makeTakeDefaultScreenshot(options)
@@ -119,6 +117,8 @@ function makeTakeMarkedScreenshot({driver, stabilization = {}, debug, logger}) {
119
117
 
120
118
  async function getViewportRegion() {
121
119
  const marker = await driver.mainContext.execute(snippets.addPageMarker)
120
+ await utils.general.sleep(100)
121
+
122
122
  try {
123
123
  const image = makeImage(await driver.takeScreenshot())
124
124
 
@@ -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',
@@ -100,6 +111,10 @@ describe('screenshoter', () => {
100
111
  return fullApp({type: 'non-scrollable'})
101
112
  })
102
113
 
114
+ it.skip('take webview screenshot', () => {
115
+ return webview()
116
+ })
117
+
103
118
  it('take region screenshot', () => {
104
119
  return region()
105
120
  })
@@ -136,6 +151,10 @@ describe('screenshoter', () => {
136
151
  return fullApp({type: 'collapsing', x: true})
137
152
  })
138
153
 
154
+ it.skip('take full app screenshot (pager)', () => {
155
+ return fullApp({type: 'pager', x: true})
156
+ })
157
+
139
158
  it.skip('take full app screenshot (overlapped status bar)', () => {
140
159
  return fullApp({type: 'overlapped', x: true})
141
160
  })
@@ -161,7 +180,10 @@ describe('screenshoter', () => {
161
180
  }
162
181
  async function fullApp({type, x, ...options} = {}) {
163
182
  let buttonSelector, expectedPath, scrollingElementSelector
164
- if (type === 'overlapped') {
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') {
165
187
  buttonSelector = {type: 'id', selector: 'btn_recycler_view_under_status_bar_activity'}
166
188
  expectedPath = `./test/fixtures/android/x-app-fully-overlapped${options.withStatusBar ? '-statusbar' : ''}.png`
167
189
  } else if (type === 'collapsing') {
@@ -212,6 +234,27 @@ describe('screenshoter', () => {
212
234
  throw err
213
235
  }
214
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
+ }
215
258
  async function region(options) {
216
259
  const screenshot = await takeScreenshot({
217
260
  logger,
@@ -1,5 +1,6 @@
1
1
  const assert = require('assert')
2
2
  const pixelmatch = require('pixelmatch')
3
+ const utils = require('@applitools/utils')
3
4
  const {Driver} = require('@applitools/driver')
4
5
  const spec = require('@applitools/spec-driver-webdriverio')
5
6
  const makeImage = require('../../src/image')
@@ -11,10 +12,10 @@ const env = {
11
12
  name: 'iOS Screenshoter Test',
12
13
  deviceName: 'iPhone 11 Pro Simulator',
13
14
  platformName: 'iOS',
14
- platformVersion: '13.4',
15
- appiumVersion: '1.19.2',
15
+ platformVersion: '14.5',
16
+ appiumVersion: '1.21.0',
16
17
  automationName: 'XCUITest',
17
- app: 'https://applitools.jfrog.io/artifactory/Examples/IOSTestApp/1.8/app/IOSTestApp.zip',
18
+ app: 'https://applitools.jfrog.io/artifactory/Examples/IOSTestApp/1.9/app/IOSTestApp.zip',
18
19
  username: process.env.SAUCE_USERNAME,
19
20
  accessKey: process.env.SAUCE_ACCESS_KEY,
20
21
  },
@@ -24,7 +25,8 @@ const env = {
24
25
  // deviceName: 'iPhone 11 Pro',
25
26
  // platformName: 'iOS',
26
27
  // platformVersion: '14.5',
27
- // app: '/Users/kyrylo/Downloads/IOSTestApp.zip',
28
+ // automationName: 'XCUITest',
29
+ // app: 'https://applitools.jfrog.io/artifactory/Examples/IOSTestApp/1.9/app/IOSTestApp.zip',
28
30
  // },
29
31
  }
30
32
 
@@ -101,6 +103,14 @@ describe('screenshoter ios', () => {
101
103
  return fullApp({type: 'superview'})
102
104
  })
103
105
 
106
+ it('take webview screenshot', () => {
107
+ return webview()
108
+ })
109
+
110
+ it('take full webview screenshot', () => {
111
+ return fullWebview()
112
+ })
113
+
104
114
  it('take region screenshot', () => {
105
115
  return region()
106
116
  })
@@ -119,6 +129,10 @@ describe('screenshoter ios', () => {
119
129
 
120
130
  async function app(options = {}) {
121
131
  const expectedPath = `./test/fixtures/ios/app${options.withStatusBar ? '-statusbar' : ''}.png`
132
+ const buttonSelector = {type: 'accessibility id', selector: 'Empty table view'}
133
+
134
+ const button = await driver.element(buttonSelector)
135
+ await button.click()
122
136
 
123
137
  const screenshot = await takeScreenshot({logger, driver, ...options})
124
138
  try {
@@ -180,7 +194,70 @@ describe('screenshoter ios', () => {
180
194
  throw err
181
195
  }
182
196
  }
197
+ async function webview(options) {
198
+ const expectedPath = `./test/fixtures/ios/webview.png`
199
+ const buttonSelector = {type: 'accessibility id', selector: 'Web view'}
200
+
201
+ const button = await driver.element(buttonSelector)
202
+ await button.click()
203
+ await driver.target.getContexts()
204
+ await utils.general.sleep(500)
205
+ const [, webview] = await driver.target.getContexts()
206
+ await driver.target.switchContext(webview)
207
+
208
+ await driver.init()
209
+
210
+ const screenshot = await takeScreenshot({logger, driver, wait: 1500, ...options})
211
+ try {
212
+ const actual = await screenshot.image.toObject()
213
+ const expected = await makeImage(expectedPath).toObject()
214
+ assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
215
+ } catch (err) {
216
+ await screenshot.image.debug({path: './logs', name: 'webview_failed', suffix: Date.now()})
217
+ throw err
218
+ } finally {
219
+ await driver.target.switchContext('NATIVE_APP')
220
+ }
221
+ }
222
+ async function fullWebview(options) {
223
+ const expectedPath = `./test/fixtures/ios/webview-fully.png`
224
+ const buttonSelector = {type: 'accessibility id', selector: 'Web view'}
225
+
226
+ const button = await driver.element(buttonSelector)
227
+ await button.click()
228
+ await driver.target.getContexts()
229
+ await utils.general.sleep(500)
230
+ const [, webview] = await driver.target.getContexts()
231
+ await driver.target.switchContext(webview)
232
+
233
+ await driver.init()
234
+ const screenshot = await takeScreenshot({
235
+ logger,
236
+ driver,
237
+ wait: 1500,
238
+ fully: true,
239
+ scrollingMode: 'scroll',
240
+ ...options,
241
+ })
242
+ try {
243
+ const actual = await screenshot.image.toObject()
244
+ const expected = await makeImage(expectedPath).toObject()
245
+ assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
246
+ } catch (err) {
247
+ await screenshot.image.debug({path: './logs', name: 'full_webview_failed', suffix: Date.now()})
248
+ throw err
249
+ } finally {
250
+ await driver.target.switchContext('NATIVE_APP')
251
+ }
252
+ }
183
253
  async function region(options) {
254
+ const expectedPath = `./test/fixtures/ios/region.png`
255
+ const buttonSelector = {type: 'accessibility id', selector: 'Empty table view'}
256
+
257
+ const button = await driver.element(buttonSelector)
258
+ await button.click()
259
+
260
+ await driver.init()
184
261
  const screenshot = await takeScreenshot({
185
262
  logger,
186
263
  driver,
@@ -191,7 +268,7 @@ describe('screenshoter ios', () => {
191
268
  })
192
269
  try {
193
270
  const actual = await screenshot.image.toObject()
194
- const expected = await makeImage('./test/fixtures/ios/region.png').toObject()
271
+ const expected = await makeImage(expectedPath).toObject()
195
272
  assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
196
273
  } catch (err) {
197
274
  await screenshot.image.debug({path: './logs', name: 'region_failed'})
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -13,7 +13,7 @@ describe('pattern', () => {
13
13
  {name: 'iPad_5th_portrait', position: {x: 0, y: 140}, offset: 0, pixelRatio: 2},
14
14
  {name: 'iPad_5th_landscape', position: {x: 0, y: 140}, offset: 0, pixelRatio: 2},
15
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},
16
+ {name: 'iPad_9th_landscape', position: {x: 640, y: 136}, offset: 1, pixelRatio: 2},
17
17
  {name: 'iPhone_XS_portrait_noviewport', position: {x: 0, y: 282}, offset: 0, pixelRatio: 3},
18
18
  {name: 'iPhone_XS_portrait_nomarker', position: null, pixelRatio: 3},
19
19
  ]