@applitools/screenshoter 3.7.32 → 3.7.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/screenshoter",
3
- "version": "3.7.32",
3
+ "version": "3.7.34",
4
4
  "description": "Applitools universal screenshoter for web and native applications",
5
5
  "keywords": [
6
6
  "applitools",
@@ -69,15 +69,15 @@
69
69
  "dependencies": {
70
70
  "@applitools/image": "1.0.28",
71
71
  "@applitools/logger": "1.1.48",
72
- "@applitools/snippets": "2.4.17",
72
+ "@applitools/snippets": "2.4.19",
73
73
  "@applitools/utils": "1.3.32",
74
74
  "jpeg-js": "0.4.4",
75
75
  "png-async": "0.9.4"
76
76
  },
77
77
  "devDependencies": {
78
78
  "@applitools/bongo": "^3.0.3",
79
- "@applitools/driver": "^1.11.37",
80
- "@applitools/spec-driver-webdriverio": "^1.4.33",
79
+ "@applitools/driver": "^1.11.39",
80
+ "@applitools/spec-driver-webdriverio": "^1.4.35",
81
81
  "@applitools/test-utils": "^1.5.15",
82
82
  "appium": "^1.22.3",
83
83
  "chromedriver": "^101.0.0",
@@ -16,6 +16,7 @@ async function extractCoordinatesForSelectorsAndElements({regionsToCalculate, sc
16
16
  const contextLocationInViewport = await elements[0].context.getLocationInViewport()
17
17
  const scaledRegions = []
18
18
  for (const element of elements) {
19
+ const viewport = await element.driver.getViewport()
19
20
  const elementRegion = await element.getRegion()
20
21
  const region = utils.geometry.offset(elementRegion, contextLocationInViewport)
21
22
  const scaledRegion = utils.geometry.scale(
@@ -25,7 +26,7 @@ async function extractCoordinatesForSelectorsAndElements({regionsToCalculate, sc
25
26
  width: region.width,
26
27
  height: region.height,
27
28
  },
28
- context.driver.viewportScale,
29
+ viewport.viewportScale,
29
30
  )
30
31
  logger.log('scaled region', scaledRegion)
31
32
  scaledRegions.push(scaledRegion)
package/src/get-target.js CHANGED
@@ -27,8 +27,9 @@ async function getTarget({window, context, region, fully, scrollingMode, logger}
27
27
  if (!element) throw new Error('Element not found!')
28
28
 
29
29
  const elementContext = element.context
30
+ const environment = await element.driver.getEnvironment()
30
31
 
31
- if (element.driver.isNative) {
32
+ if (environment.isNative) {
32
33
  // if element is in a native context, then scroll it to the top, otherwise, it will be not possible to get all of its size
33
34
  const scrollingElement = await elementContext.getScrollingElement()
34
35
  if (scrollingElement && (await scrollingElement.contains(element))) {
@@ -51,7 +52,7 @@ async function getTarget({window, context, region, fully, scrollingMode, logger}
51
52
  returnRegion = await element.getRegion()
52
53
  }
53
54
  const scroller = makeScroller({element: scrollingElement, scrollingMode, logger})
54
- if (returnRegion && !element.driver.isNative && !(await scrollingElement.isRoot())) {
55
+ if (returnRegion && !environment.isNative && !(await scrollingElement.isRoot())) {
55
56
  const scrollerOffset = await scroller.getScrollOffset()
56
57
  returnRegion = utils.geometry.offset(returnRegion, scrollerOffset)
57
58
  }
package/src/scroller.js CHANGED
@@ -111,7 +111,8 @@ function makeScroller({logger, element, scrollingMode = 'mixed'}) {
111
111
  if (utils.geometry.equals(scrollOffset, offset) && !formerlyCssScrollingMode) return scrollOffset
112
112
 
113
113
  // there is a "bug" in iOS that will not move a root element if it already scrolled, so it should be translated all the way
114
- if (element.driver.isIOS && (await element.isRoot())) {
114
+ const environment = await element.driver.getEnvironment()
115
+ if (environment.isIOS && (await element.isRoot())) {
115
116
  const translateOffset = await element.translateTo(offset)
116
117
  return translateOffset
117
118
  }
@@ -33,15 +33,24 @@ async function takeScreenshot({
33
33
  // screenshot of a window/app was requested (fully or viewport)
34
34
  const window = !region && (!frames || frames.length === 0)
35
35
 
36
+ const environment = await driver.getEnvironment()
37
+
36
38
  // switch worlds as needed
37
- if (webview && driver.isNative) await driver.switchWorld(typeof webview === 'string' ? {id: webview} : null)
38
- if (window && !webview && driver.isWebView) await driver.switchWorld({goHome: true})
39
+ let activeWorld
40
+ if (environment.isNative && (webview || (window && environment.isWeb))) {
41
+ if (webview === true) {
42
+ const worlds = await driver.getWorlds()
43
+ webview = worlds && worlds.find(name => name.includes('WEBVIEW'))
44
+ }
45
+ activeWorld = await driver.getCurrentWorld()
46
+ await driver.switchWorld(webview)
47
+ }
39
48
 
40
49
  // framed screenshots could be taken only when screenshot of window/app fully was requested
41
50
  framed = framed && fully && window
42
51
  // screenshots with status bar could be taken only when screenshot of app or framed app fully was requested
43
- withStatusBar = withStatusBar && driver.isNative && window && (!fully || framed)
44
- scrollingMode = driver.isNative ? 'scroll' : scrollingMode
52
+ withStatusBar = withStatusBar && environment.isNative && window && (!fully || framed)
53
+ scrollingMode = environment.isNative ? 'scroll' : scrollingMode
45
54
 
46
55
  const activeContext = driver.currentContext
47
56
  const context =
@@ -54,24 +63,24 @@ async function takeScreenshot({
54
63
  const scrollingElement = await nextContext.getScrollingElement()
55
64
  // unlike web apps, native apps do not always have scrolling element
56
65
  if (scrollingElement) {
57
- if (driver.isWeb && hideScrollbars) await scrollingElement.hideScrollbars()
66
+ if (environment.isWeb && hideScrollbars) await scrollingElement.hideScrollbars()
58
67
  // this is unwanted but necessary side effect, because it is not possible to extract initial scroll position
59
- if (driver.isNative && !window) await scrollingElement.scrollTo({x: 0, y: 0}, {force: true})
68
+ if (environment.isNative && !window) await scrollingElement.scrollTo({x: 0, y: 0}, {force: true})
60
69
  await scrollingElement.preserveState()
61
70
  }
62
71
  }
63
72
 
64
73
  // blur active element in target context
65
- const activeElement = driver.isWeb && hideCaret ? await context.blurElement() : null
74
+ const activeElement = environment.isWeb && hideCaret ? await context.blurElement() : null
66
75
 
67
76
  const target = await getTarget({window, context, region, fully, scrollingMode, logger})
68
77
 
69
78
  if (target.scroller) {
70
79
  await target.scroller.preserveState()
71
- if (driver.isWeb && hideScrollbars) await target.scroller.hideScrollbars()
80
+ if (environment.isWeb && hideScrollbars) await target.scroller.hideScrollbars()
72
81
  }
73
82
 
74
- if (!window && !driver.isNative) await scrollIntoViewport({...target, logger})
83
+ if (!window && !environment.isNative) await scrollIntoViewport({...target, logger})
75
84
 
76
85
  if (fully && !target.region && target.scroller) await target.scroller.moveTo({x: 0, y: 0})
77
86
 
@@ -90,7 +99,9 @@ async function takeScreenshot({
90
99
  })
91
100
  : await takeSimpleScreenshot({...target, withStatusBar, wait, stabilization, debug, logger})
92
101
 
93
- screenshot.image.scale(driver.viewportScale)
102
+ const viewport = await driver.getViewport()
103
+
104
+ screenshot.image.scale(viewport.viewportScale)
94
105
 
95
106
  const calculatedRegions = await extractCoordinatesForSelectorsAndElements({
96
107
  regionsToCalculate,
@@ -121,7 +132,7 @@ async function takeScreenshot({
121
132
  for (const prevContext of context.path.reverse()) {
122
133
  const scrollingElement = await prevContext.getScrollingElement()
123
134
  if (scrollingElement) {
124
- if (driver.isWeb && hideScrollbars) await scrollingElement.restoreScrollbars()
135
+ if (environment.isWeb && hideScrollbars) await scrollingElement.restoreScrollbars()
125
136
  await scrollingElement.restoreState()
126
137
  }
127
138
  }
@@ -130,7 +141,7 @@ async function takeScreenshot({
130
141
  await activeContext.focus()
131
142
 
132
143
  // return driver to previous app world if switched
133
- await driver.switchWorld({restoreState: true})
144
+ if (activeWorld) await driver.switchWorld(activeWorld)
134
145
  },
135
146
  }
136
147
  }
@@ -5,7 +5,7 @@ async function takeSimpleScreenshot({context, region, withStatusBar, wait, stabi
5
5
  logger.verbose('Taking image of...')
6
6
 
7
7
  const driver = context.driver
8
- const takeViewportScreenshot = makeTakeViewportScreenshot({logger, driver, stabilization, debug})
8
+ const takeViewportScreenshot = await makeTakeViewportScreenshot({logger, driver, stabilization, debug})
9
9
 
10
10
  await utils.general.sleep(wait)
11
11
 
@@ -21,7 +21,10 @@ async function takeStitchedScreenshot({
21
21
  if (await scroller.element.isPager()) overlap = {top: 0, bottom: 0}
22
22
 
23
23
  const driver = context.driver
24
- const takeViewportScreenshot = makeTakeViewportScreenshot({logger, driver, stabilization, debug})
24
+ const environment = await driver.getEnvironment()
25
+ const viewport = await driver.getViewport()
26
+
27
+ const takeViewportScreenshot = await makeTakeViewportScreenshot({logger, driver, stabilization, debug})
25
28
  const scrollerState = await scroller.preserveState()
26
29
 
27
30
  const initialOffset = region ? utils.geometry.location(region) : {x: 0, y: 0}
@@ -58,7 +61,7 @@ async function takeStitchedScreenshot({
58
61
  logger.log('Crop region calculated: ', cropRegion)
59
62
  if (utils.geometry.isEmpty(cropRegion)) throw new Error('Screenshot region is out of viewport')
60
63
 
61
- image.crop(withStatusBar ? utils.geometry.offset(cropRegion, {x: 0, y: driver.statusBarSize}) : cropRegion)
64
+ image.crop(withStatusBar ? utils.geometry.offset(cropRegion, {x: 0, y: viewport.statusBarSize}) : cropRegion)
62
65
  await image.debug({...debug, name: 'initial', suffix: 'region'})
63
66
 
64
67
  const contentRegion = utils.geometry.region({x: 0, y: 0}, contentSize)
@@ -80,7 +83,8 @@ async function takeStitchedScreenshot({
80
83
  }
81
84
  region = utils.geometry.floor(region)
82
85
 
83
- const partSize = lazyLoad && driver.isNative ? {width: image.size.width, height: image.size.height / 2} : image.size
86
+ const partSize =
87
+ lazyLoad && environment.isNative ? {width: image.size.width, height: image.size.height / 2} : image.size
84
88
  const [initialRegion, ...partRegions] = utils.geometry.divide(region, partSize, overlap)
85
89
  logger.verbose('Part regions', partRegions)
86
90
 
@@ -109,7 +113,7 @@ async function takeStitchedScreenshot({
109
113
  let actualOffset = await scroller.moveTo(requiredOffset)
110
114
  // actual scroll position after scrolling might be not equal to required position due to
111
115
  // scrollable region shift during scrolling so actual scroll position should be corrected
112
- if (!utils.geometry.equals(actualOffset, requiredOffset) && driver.isNative) {
116
+ if (!utils.geometry.equals(actualOffset, requiredOffset) && environment.isNative) {
113
117
  const actualScrollerRegion = await scroller.getClientRegion()
114
118
  scrollerRegionShift = {x: scrollerRegion.x - actualScrollerRegion.x, y: scrollerRegion.y - actualScrollerRegion.y}
115
119
  }
@@ -154,7 +158,7 @@ async function takeStitchedScreenshot({
154
158
  stitchedImage.frame(
155
159
  firstImage,
156
160
  lastImage,
157
- withStatusBar ? utils.geometry.offset(cropRegion, {x: 0, y: driver.statusBarSize}) : cropRegion,
161
+ withStatusBar ? utils.geometry.offset(cropRegion, {x: 0, y: viewport.statusBarSize}) : cropRegion,
158
162
  )
159
163
  await stitchedImage.debug({...debug, name: 'framed'})
160
164
 
@@ -3,22 +3,23 @@ const snippets = require('@applitools/snippets')
3
3
  const findImagePattern = require('./find-image-pattern')
4
4
  const {makeImage} = require('@applitools/image')
5
5
 
6
- function makeTakeViewportScreenshot(options) {
6
+ async function makeTakeViewportScreenshot(options) {
7
7
  const {driver} = options
8
- if (driver.isNative) {
8
+ const environment = await driver.getEnvironment()
9
+ if (environment.isNative && !environment.isWeb) {
9
10
  return makeTakeNativeScreenshot(options)
10
- } else if ((!driver.isEmulation && driver.isIOS) || driver.isWebView) {
11
+ } else if ((environment.isIOS && !environment.isEmulation) || (environment.isNative && environment.isWeb)) {
11
12
  // safari on ios takes screenshot with browser and os interfaces
12
13
  return makeTakeMarkedScreenshot(options)
13
- } else if (driver.browserName === 'Firefox') {
14
+ } else if (environment.browserName === 'Firefox') {
14
15
  try {
15
- const browserVersion = Number.parseInt(driver.browserVersion, 10)
16
+ const browserVersion = Number.parseInt(environment.browserVersion, 10)
16
17
  if (browserVersion >= 48 && browserVersion <= 72) {
17
18
  // firefox between versions 48 and 72 takes current frame screenshot only
18
19
  return makeTakeMainContextScreenshot(options)
19
20
  }
20
21
  } catch (ignored) {}
21
- } else if (driver.browserName === 'Safari' && driver.browserVersion === '11') {
22
+ } else if (environment.browserName === 'Safari' && environment.browserVersion === '11') {
22
23
  // safari 11 on macs takes full page screenshot
23
24
  return makeTakeSafari11Screenshot(options)
24
25
  }
@@ -29,11 +30,12 @@ function makeTakeViewportScreenshot(options) {
29
30
  function makeTakeDefaultScreenshot({driver, stabilization = {}, debug, logger}) {
30
31
  return async function takeScreenshot({name} = {}) {
31
32
  logger.verbose('Taking screenshot (default)...')
33
+ const viewport = await driver.getViewport()
32
34
  const image = makeImage(await driver.takeScreenshot())
33
35
  await image.debug({...debug, name, suffix: 'original'})
34
36
 
35
37
  if (stabilization.scale) image.scale(stabilization.scale)
36
- else image.scale(1 / driver.pixelRatio / driver.viewportScale)
38
+ else image.scale(1 / viewport.pixelRatio / viewport.viewportScale)
37
39
 
38
40
  if (stabilization.rotate) image.crop(stabilization.rotate)
39
41
 
@@ -46,6 +48,7 @@ function makeTakeDefaultScreenshot({driver, stabilization = {}, debug, logger})
46
48
  function makeTakeMainContextScreenshot({driver, stabilization = {}, debug, logger}) {
47
49
  return async function takeScreenshot({name} = {}) {
48
50
  logger.verbose('Taking screenshot (with forced main context)...')
51
+ const viewport = await driver.getViewport()
49
52
  const originalContext = driver.currentContext
50
53
  await driver.mainContext.focus()
51
54
  const image = makeImage(await driver.takeScreenshot())
@@ -53,7 +56,7 @@ function makeTakeMainContextScreenshot({driver, stabilization = {}, debug, logge
53
56
  await image.debug({...debug, name, suffix: 'original'})
54
57
 
55
58
  if (stabilization.scale) image.scale(stabilization.scale)
56
- else image.scale(1 / driver.pixelRatio / driver.viewportScale)
59
+ else image.scale(1 / viewport.pixelRatio / viewport.viewportScale)
57
60
 
58
61
  if (stabilization.rotate) image.rotate(stabilization.rotate)
59
62
 
@@ -64,23 +67,21 @@ function makeTakeMainContextScreenshot({driver, stabilization = {}, debug, logge
64
67
  }
65
68
 
66
69
  function makeTakeSafari11Screenshot({driver, stabilization = {}, debug, logger}) {
67
- let viewportSize
68
-
69
70
  return async function takeScreenshot({name} = {}) {
70
71
  logger.verbose('Taking safari 11 driver screenshot...')
72
+ const viewport = await driver.getViewport()
71
73
  const image = makeImage(await driver.takeScreenshot())
72
74
  await image.debug({...debug, name, suffix: 'original'})
73
75
 
74
76
  if (stabilization.scale) image.scale(stabilization.scale)
75
- else image.scale(1 / driver.pixelRatio / driver.viewportScale)
77
+ else image.scale(1 / viewport.pixelRatio / viewport.viewportScale)
76
78
 
77
79
  if (stabilization.rotate) image.rotate(stabilization.rotate)
78
80
 
79
81
  if (stabilization.crop) image.crop(stabilization.crop)
80
82
  else {
81
- if (!viewportSize) viewportSize = await driver.getViewportSize()
82
83
  const viewportLocation = await driver.mainContext.execute(snippets.getElementScrollOffset, [])
83
- image.crop(utils.geometry.region(viewportLocation, viewportSize))
84
+ image.crop(utils.geometry.region(viewportLocation, viewport.viewportSize))
84
85
  }
85
86
 
86
87
  return image
@@ -92,14 +93,15 @@ function makeTakeMarkedScreenshot({driver, stabilization = {}, debug, logger}) {
92
93
 
93
94
  return async function takeScreenshot({name} = {}) {
94
95
  logger.verbose('Taking viewport screenshot (using markers)...')
96
+ const viewport = await driver.getViewport()
95
97
  const image = makeImage(await driver.takeScreenshot())
96
98
  await image.debug({...debug, name, suffix: 'original'})
97
99
 
98
100
  if (stabilization.scale) image.scale(stabilization.scale)
99
- else image.scale(1 / driver.pixelRatio / driver.viewportScale)
101
+ else image.scale(1 / viewport.pixelRatio / viewport.viewportScale)
100
102
 
101
103
  if (stabilization.rotate) image.rotate(stabilization.rotate)
102
- else if (driver.orientation.startsWith('landscape') && image.width < image.height) image.rotate(-90)
104
+ else if (viewport.orientation.startsWith('landscape') && image.width < image.height) image.rotate(-90)
103
105
 
104
106
  if (stabilization.crop) image.crop(stabilization.crop)
105
107
  else {
@@ -113,11 +115,12 @@ function makeTakeMarkedScreenshot({driver, stabilization = {}, debug, logger}) {
113
115
  }
114
116
 
115
117
  async function getViewportRegion() {
118
+ const viewport = await driver.getViewport()
116
119
  // marker is -> bwb bwbb wbw bwbb wbww bbb
117
120
  const marker = await driver.mainContext.execute(snippets.addPageMarker, [
118
121
  {
119
122
  mask: [1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1],
120
- size: utils.math.multiplier(driver.viewportScale * driver.pixelRatio, 0.05),
123
+ size: utils.math.multiplier(viewport.viewportScale * viewport.pixelRatio, 0.05),
121
124
  },
122
125
  ])
123
126
  await utils.general.sleep(100)
@@ -126,18 +129,18 @@ function makeTakeMarkedScreenshot({driver, stabilization = {}, debug, logger}) {
126
129
  const image = makeImage(await driver.takeScreenshot())
127
130
 
128
131
  if (stabilization.rotate) image.rotate(stabilization.rotate)
129
- else if (driver.orientation.startsWith('landscape') && image.width < image.height) image.rotate(-90)
132
+ else if (viewport.orientation.startsWith('landscape') && image.width < image.height) image.rotate(-90)
130
133
 
131
134
  await image.debug({...debug, name: 'marker'})
132
135
 
133
136
  const markerLocation = findImagePattern(await image.toObject(), {
134
137
  ...marker,
135
- scale: driver.viewportScale * driver.pixelRatio,
138
+ scale: viewport.viewportScale * viewport.pixelRatio,
136
139
  })
137
140
  if (!markerLocation) return null
138
141
 
139
142
  return utils.geometry.region(
140
- utils.geometry.scale(markerLocation, 1 / driver.pixelRatio / driver.viewportScale),
143
+ utils.geometry.scale(markerLocation, 1 / viewport.pixelRatio / viewport.viewportScale),
141
144
  await driver.getViewportSize(),
142
145
  )
143
146
  } finally {
@@ -149,22 +152,22 @@ function makeTakeMarkedScreenshot({driver, stabilization = {}, debug, logger}) {
149
152
  function makeTakeNativeScreenshot({driver, stabilization = {}, debug, logger}) {
150
153
  return async function takeScreenshot({name, withStatusBar} = {}) {
151
154
  logger.verbose('Taking native driver screenshot...')
155
+ const viewport = await driver.getViewport()
152
156
  const image = makeImage(await driver.takeScreenshot())
153
157
  await image.debug({...debug, name, suffix: 'original'})
154
158
 
155
159
  if (stabilization.scale) image.scale(stabilization.scale)
156
- else image.scale(1 / driver.pixelRatio / driver.viewportScale)
160
+ else image.scale(1 / viewport.pixelRatio / viewport.viewportScale)
157
161
 
158
162
  if (stabilization.rotate) image.rotate(stabilization.rotate)
159
- else if (driver.orientation.startsWith('landscape') && image.width < image.height) image.rotate(-90)
163
+ else if (viewport.orientation.startsWith('landscape') && image.width < image.height) image.rotate(-90)
160
164
 
161
165
  if (stabilization.crop) image.crop(stabilization.crop)
162
166
  else {
163
- const viewportRegion = await driver.getViewportRegion()
164
- const cropRegion = {...viewportRegion}
167
+ const cropRegion = {...viewport.viewportLocation, ...viewport.viewportSize}
165
168
  if (withStatusBar) {
166
169
  cropRegion.y = 0
167
- cropRegion.height += driver.statusBarSize
170
+ cropRegion.height += viewport.statusBarSize
168
171
  }
169
172
  image.crop(cropRegion)
170
173
  }