@applitools/screenshoter 3.3.18 → 3.3.21

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/index.js CHANGED
@@ -1,6 +1,3 @@
1
1
  const takeScreenshot = require('./src/take-screenshot')
2
- const getTarget = require('./src/getTarget')
3
- module.exports = {
4
- takeScreenshot,
5
- getTarget,
6
- }
2
+
3
+ module.exports = {takeScreenshot}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/screenshoter",
3
- "version": "3.3.18",
3
+ "version": "3.3.21",
4
4
  "description": "Applitools universal screenshoter for web and native applications",
5
5
  "keywords": [
6
6
  "applitools",
@@ -36,7 +36,7 @@
36
36
  "test:unit": "mocha ./test/unit/*.spec.js --no-timeouts",
37
37
  "test:it": "mocha ./test/it/*.spec.js --no-timeouts",
38
38
  "test:e2e": "yarn test:e2e:web && yarn && test:e2e:android && yarn test:e2e:ios",
39
- "test:e2e:web": "APPLITOOLS_SHOW_LOGS=true mocha ./test/e2e/web/*.spec.js --no-timeouts -r @applitools/test-utils/mocha-hooks/docker",
39
+ "test:e2e:web": "mocha ./test/e2e/web/*.spec.js --no-timeouts -r @applitools/test-utils/mocha-hooks/docker",
40
40
  "test:e2e:android": "APPLITOOLS_TEST_REMOTE=sauce mocha ./test/e2e/android*/*.spec.js --no-timeouts --parallel --jobs ${MOCHA_JOBS:-2}",
41
41
  "test:e2e:ios": "APPLITOOLS_TEST_REMOTE=sauce mocha ./test/e2e/ios*/*.spec.js --no-timeouts --parallel --jobs ${MOCHA_JOBS:-2}",
42
42
  "setup:web": "yarn docker:setup",
@@ -60,17 +60,18 @@
60
60
  }
61
61
  },
62
62
  "dependencies": {
63
+ "@applitools/logger": "1.1.5",
63
64
  "@applitools/snippets": "2.2.3",
64
65
  "@applitools/utils": "1.3.0",
65
66
  "png-async": "0.9.4"
66
67
  },
67
68
  "devDependencies": {
68
69
  "@applitools/bongo": "^2.0.3",
69
- "@applitools/driver": "1.8.2",
70
+ "@applitools/driver": "^1.8.11",
70
71
  "@applitools/scripts": "1.1.0",
71
72
  "@applitools/spec-driver-webdriverio": "1.2.9",
72
73
  "@applitools/test-utils": "1.3.2",
73
- "appium": "^1.22.2",
74
+ "appium": "^1.22.3",
74
75
  "chromedriver": "^95.0.0",
75
76
  "eslint": "^7.9.0",
76
77
  "eslint-plugin-mocha-no-only": "^1.1.1",
@@ -1,29 +1,41 @@
1
1
  const utils = require('@applitools/utils')
2
+ const makeScroller = require('./scroller')
2
3
 
3
- async function getTarget({window, context, region, fully, scrollingMode}) {
4
+ async function getTarget({window, context, region, fully, scrollingMode, logger}) {
4
5
  if (window) {
5
6
  // window/app
7
+ logger.log('Window screenshot target detected')
6
8
  const scrollingElement = await context.main.getScrollingElement()
7
9
  return {
8
10
  context: context.main,
9
- scrollingElement,
11
+ scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
10
12
  }
11
13
  } else if (region) {
12
14
  if (utils.types.has(region, ['x', 'y', 'width', 'height'])) {
13
15
  // region by coordinates
16
+ logger.log('Region screenshot target detected with static region:', region)
14
17
  const scrollingElement = await context.getScrollingElement()
15
18
  return {
16
19
  context,
17
20
  region,
18
- scrollingElement,
21
+ scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
19
22
  }
20
23
  } else {
21
24
  // region by element or selector
25
+ logger.log('Region screenshot target detected with element:', region)
22
26
  const element = await context.element(region)
23
27
  if (!element) throw new Error('Element not found!')
24
28
 
25
29
  const elementContext = element.context
26
30
 
31
+ if (element.driver.isNative) {
32
+ // 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
+ const scrollingElement = await elementContext.getScrollingElement()
34
+ if (scrollingElement && (await scrollingElement.contains(element))) {
35
+ await scrollingElement.scrollTo(await element.getRegion())
36
+ }
37
+ }
38
+
27
39
  if (fully) {
28
40
  const isScrollable = await element.isScrollable()
29
41
  // if element is scrollable, then take screenshot of the full element content, otherwise take screenshot of full element
@@ -34,25 +46,25 @@ async function getTarget({window, context, region, fully, scrollingMode}) {
34
46
  return {
35
47
  context: elementContext,
36
48
  region,
37
- scrollingMode,
38
- scrollingElement,
49
+ scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
39
50
  }
40
51
  } else {
41
52
  const scrollingElement = await context.getScrollingElement()
42
53
  return {
43
54
  context: elementContext,
44
55
  region: await element.getRegion(),
45
- scrollingElement,
56
+ scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
46
57
  }
47
58
  }
48
59
  }
49
60
  } else if (!context.isMain) {
50
61
  // context
62
+ logger.log('Context screenshot target detected')
51
63
  if (fully) {
52
64
  const scrollingElement = await context.getScrollingElement()
53
65
  return {
54
66
  context,
55
- scrollingElement,
67
+ scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
56
68
  }
57
69
  } else {
58
70
  const scrollingElement = await context.parent.getScrollingElement()
@@ -60,9 +72,10 @@ async function getTarget({window, context, region, fully, scrollingMode}) {
60
72
  return {
61
73
  context: context.parent,
62
74
  region: await element.getRegion(), // IMHO we should use CLIENT (without borders) region here
63
- scrollingElement,
75
+ scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
64
76
  }
65
77
  }
66
78
  }
67
79
  }
80
+
68
81
  module.exports = getTarget
@@ -1,10 +1,6 @@
1
1
  const utils = require('@applitools/utils')
2
2
 
3
- async function scrollIntoViewport({context, scroller, region, logger}) {
4
- if (context.driver.isNative) {
5
- logger.verbose(`NATIVE context identified, skipping 'ensure element visible'`)
6
- return
7
- }
3
+ async function scrollIntoViewport({context, scroller, region}) {
8
4
  const elementContextRegion = region ? {...region} : await scroller.getClientRegion()
9
5
  const contextViewportLocation = await context.getLocationInViewport()
10
6
  const elementViewportRegion = utils.geometry.offset(elementContextRegion, contextViewportLocation)
package/src/scroller.js CHANGED
@@ -1,6 +1,8 @@
1
1
  const utils = require('@applitools/utils')
2
2
 
3
3
  function makeScroller({logger, element, scrollingMode = 'mixed'}) {
4
+ if (!element) return null
5
+
4
6
  const defaultElement = element
5
7
 
6
8
  return {
@@ -1,6 +1,6 @@
1
+ const {makeLogger} = require('@applitools/logger')
2
+ const getTarget = require('./get-target')
1
3
  const scrollIntoViewport = require('./scroll-into-viewport')
2
- const getTarget = require('./getTarget')
3
- const makeScroller = require('./scroller')
4
4
  const takeStitchedScreenshot = require('./take-stitched-screenshot')
5
5
  const takeSimpleScreenshot = require('./take-simple-screenshot')
6
6
 
@@ -21,6 +21,10 @@ async function takeScreenshot({
21
21
  debug,
22
22
  logger,
23
23
  }) {
24
+ debug =
25
+ debug ||
26
+ (process.env.APPLITOOLS_DEBUG_SCREENSHOTS_DIR ? {path: process.env.APPLITOOLS_DEBUG_SCREENSHOTS_DIR} : debug)
27
+ logger = logger ? logger.extend({label: 'screenshoter'}) : makeLogger({label: 'screenshoter'})
24
28
  // screenshot of a window/app was requested (fully or viewport)
25
29
  const window = !region && (!frames || frames.length === 0)
26
30
  // framed screenshots could be taken only when screenshot of window/app fully was requested
@@ -48,27 +52,22 @@ async function takeScreenshot({
48
52
  // blur active element in target context
49
53
  const activeElement = driver.isWeb && hideCaret ? await context.blurElement() : null
50
54
 
51
- const target = await getTarget({window, context, region, fully, scrollingMode})
52
- // in some cases getTarget logic manipulates the 'scrollingMode'
53
- scrollingMode = target.scrollingMode || scrollingMode
55
+ const target = await getTarget({window, context, region, fully, scrollingMode, logger})
54
56
 
55
- const scroller = target.scrollingElement
56
- ? makeScroller({element: target.scrollingElement, scrollingMode, logger})
57
- : null
58
-
59
- if (scroller) {
60
- await scroller.preserveState()
61
- if (driver.isWeb && hideScrollbars) await scroller.hideScrollbars()
57
+ if (target.scroller) {
58
+ await target.scroller.preserveState()
59
+ if (driver.isWeb && hideScrollbars) await target.scroller.hideScrollbars()
62
60
  }
63
61
 
64
62
  try {
65
- if (!window) await scrollIntoViewport({context: target.context, region: target.region, scroller, logger})
63
+ if (!window && !driver.isNative) {
64
+ await scrollIntoViewport({context: target.context, region: target.region, scroller: target.scroller, logger})
65
+ }
66
66
 
67
67
  const screenshot =
68
- fully && scroller
68
+ fully && target.scroller
69
69
  ? await takeStitchedScreenshot({
70
70
  ...target,
71
- scroller,
72
71
  withStatusBar,
73
72
  overlap,
74
73
  framed,
@@ -77,19 +76,19 @@ async function takeScreenshot({
77
76
  debug,
78
77
  logger,
79
78
  })
80
- : await takeSimpleScreenshot({...target, scroller, withStatusBar, wait, stabilization, debug, logger})
79
+ : await takeSimpleScreenshot({...target, withStatusBar, wait, stabilization, debug, logger})
81
80
 
82
81
  screenshot.image.scale(driver.viewportScale)
83
82
 
84
83
  if (hooks && hooks.afterScreenshot) {
85
- await hooks.afterScreenshot({driver, scroller, screenshot})
84
+ await hooks.afterScreenshot({driver, scroller: target.scroller, screenshot})
86
85
  }
87
86
 
88
87
  return screenshot
89
88
  } finally {
90
- if (scroller) {
91
- await scroller.restoreScrollbars()
92
- await scroller.restoreState()
89
+ if (target.scroller) {
90
+ await target.scroller.restoreScrollbars()
91
+ await target.scroller.restoreState()
93
92
  }
94
93
 
95
94
  // if there was active element and we have blurred it, then restore focus
@@ -49,13 +49,12 @@ async function takeStitchedScreenshot({
49
49
  const targetRegion = region
50
50
  ? utils.geometry.intersect(utils.geometry.region(postMoveOffset, scrollerRegion), region)
51
51
  : scrollerRegion
52
+ logger.log('Target region calculated: ', targetRegion)
52
53
 
53
- // TODO the solution should not check driver specifics,
54
- // in this case target region coordinate should be already related to the scrolling element of the context
55
- let cropRegion = driver.isNative ? targetRegion : await driver.getRegionInViewport(context, targetRegion)
54
+ const cropRegion = await driver.getRegionInViewport(context, targetRegion)
55
+ logger.log('Crop region calculated: ', cropRegion)
56
56
  if (utils.geometry.isEmpty(cropRegion)) throw new Error('Screenshot region is out of viewport')
57
57
 
58
- logger.verbose('cropping... cropRegion is', cropRegion)
59
58
  image.crop(withStatusBar ? utils.geometry.offset(cropRegion, {x: 0, y: driver.statusBarHeight}) : cropRegion)
60
59
  await image.debug({...debug, name: 'initial', suffix: 'region'})
61
60
 
@@ -161,21 +161,18 @@ function makeTakeNativeScreenshot({driver, stabilization = {}, debug, logger}) {
161
161
  if (stabilization.crop) image.crop(stabilization.crop)
162
162
  else {
163
163
  const viewportSize = await driver.getViewportSize()
164
- const cropRegion = withStatusBar
165
- ? {x: 0, y: 0, width: viewportSize.width, height: viewportSize.height + driver.statusBarHeight}
166
- : {
167
- top: driver.statusBarHeight,
168
- bottom: driver.orientation === 'landscape' ? 0 : driver.navigationBarHeight,
169
- left:
170
- driver.isAndroid && driver.orientation === 'landscape' && driver.platformVersion > 7
171
- ? driver.navigationBarHeight
172
- : 0,
173
- right:
174
- driver.isAndroid && driver.orientation === 'landscape' && driver.platformVersion < 8
175
- ? driver.navigationBarHeight
176
- : 0,
177
- }
178
- image.crop(cropRegion)
164
+ if (withStatusBar) {
165
+ image.crop({x: 0, y: 0, width: viewportSize.width, height: viewportSize.height + driver.statusBarHeight})
166
+ } else if (driver.isAndroid && driver.orientation === 'landscape') {
167
+ image.crop({
168
+ top: driver.statusBarHeight,
169
+ bottom: driver.orientation === 'landscape' ? 0 : driver.navigationBarHeight,
170
+ left: driver.platformVersion > 7 ? driver.navigationBarHeight : 0,
171
+ right: driver.platformVersion < 8 ? driver.navigationBarHeight : 0,
172
+ })
173
+ } else {
174
+ image.crop({x: 0, y: driver.statusBarHeight, width: viewportSize.width, height: viewportSize.height})
175
+ }
179
176
  }
180
177
 
181
178
  await image.debug({...debug, name, suffix: `viewport${withStatusBar ? '-with-statusbar' : ''}`})