@applitools/screenshoter 3.3.10 → 3.3.13

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,2 +1,6 @@
1
- module.exports = require('./src/take-screenshot')
2
- exports.takeScreenshot = require('./src/take-screenshot')
1
+ const takeScreenshot = require('./src/take-screenshot')
2
+ const getTarget = require('./src/getTarget')
3
+ module.exports = {
4
+ takeScreenshot,
5
+ getTarget,
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/screenshoter",
3
- "version": "3.3.10",
3
+ "version": "3.3.13",
4
4
  "description": "Applitools universal screenshoter for web and native applications",
5
5
  "keywords": [
6
6
  "applitools",
@@ -33,15 +33,15 @@
33
33
  "scripts": {
34
34
  "lint": "eslint . --ext .js",
35
35
  "test": "yarn test:it && yarn test:e2e",
36
+ "test:unit": "mocha ./test/unit/*.spec.js --no-timeouts",
36
37
  "test:it": "mocha ./test/it/*.spec.js --no-timeouts",
37
38
  "test:e2e": "mocha ./test/e2e/**/*.spec.js --no-timeouts --parallel --jobs ${MOCHA_JOBS:-1}",
38
- "test:e2e:web": "mocha ./test/e2e/web/*.spec.js --no-timeouts -r @applitools/test-utils/mocha-hooks/docker --parallel --jobs ${MOCHA_JOBS:-15}",
39
- "test:e2e:android": "mocha ./test/e2e/android*/*.spec.js --no-timeouts --parallel --jobs ${MOCHA_JOBS:-1}",
40
- "test:e2e:ios": "mocha ./test/e2e/ios*/*.spec.js --no-timeouts --parallel --jobs ${MOCHA_JOBS:-1}",
41
- "setup": "yarn docker:setup && yarn android:setup && yarn ios:setup && yarn appium:setup",
39
+ "test:e2e:web": "APPLITOOLS_SHOW_LOGS=true mocha ./test/e2e/web/*.spec.js --no-timeouts -r @applitools/test-utils/mocha-hooks/docker",
40
+ "test:e2e:android": "APPLITOOLS_TEST_REMOTE=sauce mocha ./test/e2e/android*/*.spec.js --no-timeouts --parallel --jobs ${MOCHA_JOBS:-2}",
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",
43
- "setup:android": "yarn android:setup && yarn appium:setup",
44
- "setup:ios": "yarn ios:setup && yarn appium:setup",
43
+ "setup:android": "echo \"setup:android - do nothing\"",
44
+ "setup:ios": "echo \"setup:ios - do nothing\"",
45
45
  "android:setup": "node ./scripts/android-emulator.js",
46
46
  "android:shutdown": "adb -s emulator-5555 emu kill || true && adb -s emulator-5557 emu kill || true",
47
47
  "docker:setup": "node ../scripts/scripts/generate-docker-compose-config.js && docker-compose up -d",
@@ -60,15 +60,16 @@
60
60
  }
61
61
  },
62
62
  "dependencies": {
63
- "@applitools/snippets": "2.1.15",
63
+ "@applitools/snippets": "2.2.2",
64
64
  "@applitools/utils": "1.2.13",
65
65
  "png-async": "0.9.4"
66
66
  },
67
67
  "devDependencies": {
68
- "@applitools/driver": "1.4.16",
69
- "@applitools/sdk-release-kit": "0.13.11",
70
- "@applitools/spec-driver-webdriverio": "1.2.7",
71
- "@applitools/test-utils": "1.0.12",
68
+ "@applitools/driver": "1.5.5",
69
+ "@applitools/scripts": "1.1.0",
70
+ "@applitools/sdk-release-kit": "1.0.4",
71
+ "@applitools/spec-driver-webdriverio": "1.2.8",
72
+ "@applitools/test-utils": "1.1.5",
72
73
  "appium": "^1.22.2",
73
74
  "chromedriver": "^95.0.0",
74
75
  "eslint": "^7.9.0",
@@ -0,0 +1,17 @@
1
+ const utils = require('@applitools/utils')
2
+
3
+ function calculateScreenshotRegion({cropRegion, stitchedImage, preMoveOffset, postMoveOffset} = {}) {
4
+ cropRegion = !!cropRegion ? cropRegion : {x: 0, y: 0}
5
+ const screenshotRegion = utils.geometry.region(cropRegion, stitchedImage.size)
6
+
7
+ if (JSON.stringify(preMoveOffset) === JSON.stringify(postMoveOffset)) return screenshotRegion
8
+ const moveOffset = utils.geometry.offsetNegative(postMoveOffset, preMoveOffset)
9
+ const compensatedScreenshotRegion = utils.geometry.offset(screenshotRegion, moveOffset)
10
+
11
+ if (preMoveOffset.y === postMoveOffset.y && preMoveOffset.x !== postMoveOffset.x)
12
+ compensatedScreenshotRegion.x = preMoveOffset.x
13
+
14
+ return compensatedScreenshotRegion
15
+ }
16
+
17
+ module.exports = calculateScreenshotRegion
@@ -0,0 +1,70 @@
1
+ 'use strict'
2
+
3
+ const utils = require('@applitools/utils')
4
+
5
+ async function getTarget({window, context, region, fully, scrollingMode}) {
6
+ if (window) {
7
+ // window/app
8
+ const scrollingElement = await context.main.getScrollingElement()
9
+ return {
10
+ context: context.main,
11
+ scrollingElement,
12
+ }
13
+ } else if (region) {
14
+ if (utils.types.has(region, ['x', 'y', 'width', 'height'])) {
15
+ // region by coordinates
16
+ const scrollingElement = await context.getScrollingElement()
17
+ return {
18
+ context,
19
+ region,
20
+ scrollingElement,
21
+ }
22
+ } else {
23
+ // region by element or selector
24
+ const element = await context.element(region)
25
+ if (!element) throw new Error('Element not found!')
26
+
27
+ const elementContext = element.context
28
+
29
+ if (fully) {
30
+ const isScrollable = await element.isScrollable()
31
+ // if element is scrollable, then take screenshot of the full element content, otherwise take screenshot of full element
32
+ const region = isScrollable ? null : await element.getRegion()
33
+ const scrollingElement = isScrollable ? element : await elementContext.getScrollingElement()
34
+ // css stitching could be applied only to root element of its context
35
+ scrollingMode = scrollingMode === 'css' && !(await scrollingElement.isRoot()) ? 'mixed+' : scrollingMode
36
+ return {
37
+ context: elementContext,
38
+ region,
39
+ scrollingMode,
40
+ scrollingElement,
41
+ }
42
+ } else {
43
+ const scrollingElement = await context.getScrollingElement()
44
+ return {
45
+ context: elementContext,
46
+ region: await element.getRegion(),
47
+ scrollingElement,
48
+ }
49
+ }
50
+ }
51
+ } else if (!context.isMain) {
52
+ // context
53
+ if (fully) {
54
+ const scrollingElement = await context.getScrollingElement()
55
+ return {
56
+ context,
57
+ scrollingElement,
58
+ }
59
+ } else {
60
+ const scrollingElement = await context.parent.getScrollingElement()
61
+ const element = await context.getContextElement()
62
+ return {
63
+ context: context.parent,
64
+ region: await element.getRegion(), // IMHO we should use CLIENT (without borders) region here
65
+ scrollingElement,
66
+ }
67
+ }
68
+ }
69
+ }
70
+ module.exports = getTarget
package/src/image.js CHANGED
@@ -84,6 +84,7 @@ function makeImage(data) {
84
84
  ? utils.geometry.intersect(transforms.crop, utils.geometry.offset(region, transforms.crop))
85
85
  : utils.geometry.intersect({x: 0, y: 0, ...size}, region)
86
86
  transforms.crop = region
87
+ size = utils.geometry.size(transforms.crop)
87
88
  return this
88
89
  },
89
90
  copy(srcImage, offset) {
package/src/scroller.js CHANGED
@@ -25,12 +25,14 @@ function makeScroller({logger, element, scrollingMode = 'mixed'}) {
25
25
  if (scrollingMode === 'scroll') return scrollTo(offset, element)
26
26
  if (scrollingMode === 'css') return translateTo(offset, element)
27
27
  if (scrollingMode === 'mixed') return shiftTo(offset, element)
28
+ if (scrollingMode === 'mixed+') return shiftTo(offset, element, {formerlyCssScrollingMode: true})
28
29
  }
29
30
 
30
31
  async function getInnerOffset(element = defaultElement) {
31
32
  if (scrollingMode === 'scroll') return getScrollOffset(element)
32
33
  if (scrollingMode === 'css') return getTranslateOffset(element)
33
34
  if (scrollingMode === 'mixed') return getShiftOffset(element)
35
+ if (scrollingMode === 'mixed+') return getShiftOffset(element)
34
36
  }
35
37
 
36
38
  async function getContentSize() {
@@ -101,9 +103,10 @@ function makeScroller({logger, element, scrollingMode = 'mixed'}) {
101
103
  }
102
104
  }
103
105
 
104
- async function shiftTo(offset, element = defaultElement) {
106
+ async function shiftTo(offset, element = defaultElement, {formerlyCssScrollingMode} = {}) {
105
107
  try {
106
108
  const scrollOffset = await element.scrollTo(offset)
109
+ if (utils.geometry.equals(scrollOffset, offset) && !formerlyCssScrollingMode) return scrollOffset
107
110
 
108
111
  // 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
109
112
  if (element.driver.isIOS && (await element.isRoot())) {
@@ -1,6 +1,6 @@
1
- const utils = require('@applitools/utils')
2
- const makeScroller = require('./scroller')
3
1
  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
 
@@ -48,32 +48,48 @@ async function takeScreenshot({
48
48
  // blur active element in target context
49
49
  const activeElement = driver.isWeb && hideCaret ? await context.blurElement() : null
50
50
 
51
- const target = await getTarget({window, context, region, fully, scrollingMode, logger})
51
+ const target = await getTarget({window, context, region, fully, scrollingMode})
52
+ // in some cases getTarget logic manipulates the 'scrollingMode'
53
+ scrollingMode = target.scrollingMode || scrollingMode
52
54
 
53
- if (driver.isWeb && hideScrollbars) await target.scroller.hideScrollbars()
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()
62
+ }
54
63
 
55
64
  try {
56
- if (!window) await scrollIntoViewport({...target, logger})
65
+ if (!window) await scrollIntoViewport({context: target.context, region: target.region, scroller, logger})
57
66
 
58
67
  const screenshot =
59
- fully && target.scroller
60
- ? await takeStitchedScreenshot({...target, withStatusBar, overlap, framed, wait, stabilization, debug, logger})
61
- : await takeSimpleScreenshot({...target, withStatusBar, wait, stabilization, debug, logger})
68
+ fully && scroller
69
+ ? await takeStitchedScreenshot({
70
+ ...target,
71
+ scroller,
72
+ withStatusBar,
73
+ overlap,
74
+ framed,
75
+ wait,
76
+ stabilization,
77
+ debug,
78
+ logger,
79
+ })
80
+ : await takeSimpleScreenshot({...target, scroller, withStatusBar, wait, stabilization, debug, logger})
62
81
 
63
82
  screenshot.image.scale(driver.viewportScale)
64
83
 
65
84
  if (hooks && hooks.afterScreenshot) {
66
- // imitate image-like state for the hook
67
- if (window && fully && target.scroller) {
68
- await target.scroller.moveTo({x: 0, y: 0}, await driver.mainContext.getScrollingElement())
69
- }
70
- await hooks.afterScreenshot({driver, scroller: target.scroller, screenshot})
85
+ await hooks.afterScreenshot({driver, scroller, screenshot})
71
86
  }
72
87
 
73
88
  return screenshot
74
89
  } finally {
75
- if (target.scroller) {
76
- await target.scroller.restoreScrollbars()
90
+ if (scroller) {
91
+ await scroller.restoreScrollbars()
92
+ await scroller.restoreState()
77
93
  }
78
94
 
79
95
  // if there was active element and we have blurred it, then restore focus
@@ -93,69 +109,4 @@ async function takeScreenshot({
93
109
  }
94
110
  }
95
111
 
96
- async function getTarget({window, context, region, fully, scrollingMode, logger}) {
97
- if (window) {
98
- // window/app
99
- const scrollingElement = await context.main.getScrollingElement()
100
- return {
101
- context: context.main,
102
- scroller: scrollingElement ? makeScroller({element: scrollingElement, scrollingMode, logger}) : null,
103
- }
104
- } else if (region) {
105
- if (utils.types.has(region, ['x', 'y', 'width', 'height'])) {
106
- // region by coordinates
107
- const scrollingElement = await context.getScrollingElement()
108
- return {
109
- context,
110
- region,
111
- scroller: scrollingElement ? makeScroller({element: scrollingElement, scrollingMode, logger}) : null,
112
- }
113
- } else {
114
- // region by element or selector
115
- const element = await context.element(region)
116
- if (!element) throw new Error('Element not found!')
117
-
118
- const elementContext = element.context
119
-
120
- if (fully) {
121
- const isScrollable = await element.isScrollable()
122
- // if element is scrollable, then take screenshot of the full element content, otherwise take screenshot of full element
123
- const region = isScrollable ? null : await element.getRegion()
124
- const scrollingElement = isScrollable ? element : await elementContext.getScrollingElement()
125
- // css stitching could be applied only to root element of its context
126
- scrollingMode = scrollingMode === 'css' && !(await scrollingElement.isRoot()) ? 'mixed' : scrollingMode
127
- return {
128
- context: elementContext,
129
- region,
130
- scroller: scrollingElement ? makeScroller({element: scrollingElement, scrollingMode, logger}) : null,
131
- }
132
- } else {
133
- const scrollingElement = await context.getScrollingElement()
134
- return {
135
- context: elementContext,
136
- region: await element.getRegion(),
137
- scroller: scrollingElement ? makeScroller({element: scrollingElement, scrollingMode, logger}) : null,
138
- }
139
- }
140
- }
141
- } else if (!context.isMain) {
142
- // context
143
- if (fully) {
144
- const scrollingElement = await context.getScrollingElement()
145
- return {
146
- context,
147
- scroller: scrollingElement ? makeScroller({logger, element: scrollingElement, scrollingMode}) : null,
148
- }
149
- } else {
150
- const scrollingElement = await context.parent.getScrollingElement()
151
- const element = await context.getContextElement()
152
- return {
153
- context: context.parent,
154
- region: await element.getRegion(), // IMHO we should use CLIENT (without borders) region here
155
- scroller: scrollingElement ? makeScroller({logger, element: scrollingElement, scrollingMode}) : null,
156
- }
157
- }
158
- }
159
- }
160
-
161
112
  module.exports = takeScreenshot
@@ -1,6 +1,7 @@
1
1
  const utils = require('@applitools/utils')
2
2
  const makeImage = require('./image')
3
3
  const makeTakeViewportScreenshot = require('./take-viewport-screenshot')
4
+ const calculateScreenshotRegion = require('./calculate-screenshot-region')
4
5
 
5
6
  async function takeStitchedScreenshot({
6
7
  logger,
@@ -21,32 +22,45 @@ async function takeStitchedScreenshot({
21
22
  const scrollerState = await scroller.preserveState()
22
23
 
23
24
  const initialOffset = region ? utils.geometry.location(region) : {x: 0, y: 0}
24
- const actualOffset = await scroller.getInnerOffset()
25
- const expectedRemainingOffset = utils.geometry.offsetNegative(initialOffset, actualOffset)
25
+ const preMoveOffset = await scroller.getInnerOffset()
26
+ const postMoveOffset = await scroller.moveTo(initialOffset)
27
+ const expectedRemainingOffset = utils.geometry.offsetNegative(initialOffset, postMoveOffset)
26
28
 
27
29
  await utils.general.sleep(wait)
28
30
 
29
31
  const contentSize = await scroller.getContentSize()
30
32
 
33
+ logger.verbose(
34
+ 'preMoveOffset',
35
+ preMoveOffset,
36
+ 'initialOffset',
37
+ initialOffset,
38
+ 'postMoveOffset',
39
+ postMoveOffset,
40
+ 'context.isMain',
41
+ context.isMain,
42
+ )
43
+
31
44
  logger.verbose('Getting initial image...')
32
45
  let image = await takeViewportScreenshot({name: 'initial', withStatusBar})
33
46
  const firstImage = framed ? makeImage(image) : null
34
47
 
35
48
  const scrollerRegion = await scroller.getClientRegion()
36
49
  const targetRegion = region
37
- ? utils.geometry.intersect(utils.geometry.region(actualOffset, scrollerRegion), region)
50
+ ? utils.geometry.intersect(utils.geometry.region(postMoveOffset, scrollerRegion), region)
38
51
  : scrollerRegion
39
52
 
40
53
  // TODO the solution should not check driver specifics,
41
54
  // in this case target region coordinate should be already related to the scrolling element of the context
42
55
  let cropRegion = driver.isNative ? targetRegion : await driver.getRegionInViewport(context, targetRegion)
56
+ if (utils.geometry.isEmpty(cropRegion)) throw new Error('Screenshot region is out of viewport')
43
57
 
44
- logger.verbose('cropping...')
58
+ logger.verbose('cropping... cropRegion is', cropRegion)
45
59
  image.crop(withStatusBar ? utils.geometry.offset(cropRegion, {x: 0, y: driver.statusBarHeight}) : cropRegion)
46
60
  await image.debug({...debug, name: 'initial', suffix: 'region'})
47
61
 
48
62
  const contentRegion = utils.geometry.region({x: 0, y: 0}, contentSize)
49
- logger.verbose(`Scroller size: ${contentRegion}`)
63
+ logger.verbose('Scroller size:', contentRegion)
50
64
 
51
65
  if (region) region = utils.geometry.intersect(region, contentRegion)
52
66
  else region = contentRegion
@@ -73,7 +87,7 @@ async function takeStitchedScreenshot({
73
87
  const compensateOffset = {x: 0, y: initialRegion.y !== partRegion.y ? overlap.top : 0}
74
88
  const requiredOffset = utils.geometry.offsetNegative(utils.geometry.location(partRegion), compensateOffset)
75
89
 
76
- logger.verbose(`Move to ${requiredOffset}`)
90
+ logger.verbose('Move to', requiredOffset)
77
91
  let actualOffset = await scroller.moveTo(requiredOffset)
78
92
  // actual scroll position after scrolling might be not equal to required position due to
79
93
  // scrollable region shift during scrolling so actual scroll position should be corrected
@@ -94,7 +108,8 @@ async function takeStitchedScreenshot({
94
108
  width: partRegion.width,
95
109
  height: partRegion.height,
96
110
  }
97
- logger.verbose(`Actual offset is ${actualOffset}, remaining offset is ${remainingOffset}`)
111
+ logger.verbose('Actual offset is', actualOffset, ', remaining offset is', remainingOffset)
112
+ logger.verbose('cropPartRegion is', cropPartRegion)
98
113
 
99
114
  await utils.general.sleep(wait)
100
115
 
@@ -126,12 +141,12 @@ async function takeStitchedScreenshot({
126
141
 
127
142
  return {
128
143
  image: stitchedImage,
129
- region: utils.geometry.region({x: 0, y: 0}, stitchedImage.size),
144
+ region: calculateScreenshotRegion({stitchedImage, preMoveOffset, postMoveOffset}),
130
145
  }
131
146
  } else {
132
147
  return {
133
148
  image: stitchedImage,
134
- region: utils.geometry.region(cropRegion, stitchedImage.size),
149
+ region: calculateScreenshotRegion({cropRegion, stitchedImage, preMoveOffset, postMoveOffset}),
135
150
  }
136
151
  }
137
152
  }
package/CHANGELOG.md DELETED
@@ -1,176 +0,0 @@
1
-
2
- # Change Log
3
-
4
- ## Unreleased
5
-
6
-
7
- ## 3.3.10 - 2022/2/16
8
-
9
- - do not perform initial scrolling in `takeStitchedScreenshot`
10
-
11
- ## 3.3.9 - 2022/2/16
12
-
13
- - remove prevention of translation in `mixed` scrolling mode
14
- - updated to @applitools/snippets@2.1.15 (from 2.1.14)
15
-
16
- ## 3.3.8 - 2022/2/16
17
-
18
- - updated to @applitools/snippets@2.1.14 (from 2.1.13)
19
-
20
- ## 3.3.7 - 2022/2/15
21
-
22
- - fix image scaling on pages without viewport metatag
23
- - fix safari's viewport detection on iOS devices
24
- - updated to @applitools/snippets@2.1.13 (from 2.1.12)
25
- - updated to @applitools/utils@1.2.13 (from 1.2.12)
26
-
27
- ## 3.3.6 - 2022/2/9
28
-
29
- - fix testing
30
- - updated to @applitools/utils@1.2.12 (from 1.2.11)
31
-
32
- ## 3.3.5 - 2022/2/8
33
-
34
- - add "files" field to the package.json to avoid unnecessary files to be published
35
- - updated to @applitools/utils@1.2.11 (from 1.2.5)
36
-
37
- ## 3.3.4 - 2021/12/23
38
-
39
- - updated to @applitools/snippets@2.1.12 (from 2.1.11)
40
-
41
- ## 3.3.3 - 2021/12/22
42
-
43
- - improve default rotation and scaling logic
44
- - improve scroll into viewport algorithm
45
- - fix lazy handling of image rotation
46
- - updated to @applitools/snippets@2.1.11 (from 2.1.10)
47
- - updated to @applitools/utils@1.2.5 (from 1.2.4)
48
-
49
- ## 3.3.2 - 2021/12/20
50
-
51
- - add basic support of webview screenshots on ios
52
- - updated to @applitools/snippets@2.1.10 (from 2.1.8)
53
-
54
- ## 3.3.1 - 2021/12/17
55
-
56
- - no changes
57
-
58
- ## 3.3.0 - 2021/12/16
59
-
60
- - fix ios web screenshots on pages without viewport meta tag
61
- - improve native apps support
62
- - updated to @applitools/snippets@2.1.8 (from 2.1.7)
63
-
64
- ## 3.2.9 - 2021/11/14
65
-
66
- - add support of scrollable elements that change its size during scrolling
67
-
68
- ## 3.2.8 - 2021/10/30
69
-
70
- - updated to @applitools/utils@1.2.4 (from 1.2.3)
71
-
72
- ## 3.2.7 - 2021/10/13
73
-
74
- - handle a case when scrolling element does not exist
75
-
76
- ## 3.2.6 - 2021/10/12
77
-
78
- - handle a case when scrolling element does not exist
79
-
80
- ## 3.2.5 - 2021/10/5
81
-
82
- - fix issue with fractional image size after scaling
83
-
84
- ## 3.2.4 - 2021/9/9
85
-
86
- - handle selectors that evaluate to elements from a different context
87
- - updated to @applitools/snippets@2.1.7 (from 2.1.4)
88
- - updated to @applitools/utils@1.2.3 (from 1.2.2)
89
-
90
- ## 3.2.3 - 2021/8/13
91
-
92
- - remove base64 sanitizing
93
-
94
- ## 3.2.2 - 2021/8/13
95
-
96
- - add `withStatusBar` capability property to take app and full app screenshots with status bar
97
- - fix ios web screenshots
98
-
99
- ## 3.2.1 - 2021/8/8
100
-
101
- - no changes
102
-
103
- ## 3.2.0 - 2021/8/7
104
-
105
- - change image processing order and improve general algorithm
106
- - updated to @applitools/utils@1.2.2 (from 1.2.1)
107
-
108
- ## 3.1.0 - 2021/8/4
109
-
110
- - improve support of native devices
111
- - updated to @applitools/snippets@2.1.4 (from 2.1.3)
112
- - updated to @applitools/utils@1.2.1 (from 1.2.0)
113
-
114
- ## 3.0.8 - 2021/5/24
115
-
116
- - updated to @applitools/utils@1.2.0 (from 1.1.3)
117
-
118
- ## 3.0.7 - 2021/5/13
119
-
120
- - fixed image cropping algorithm to not copy data into a heap
121
- - optimized image rotation and image copping algorithms
122
-
123
- ## 3.0.6 - 2021/5/11
124
-
125
- - updated to @applitools/utils@1.1.3 (from 1.0.1)
126
-
127
- ## 3.0.5 - 2021/2/18
128
-
129
- - fix bug with wrong stitching due to fractional offset
130
-
131
- ## 3.0.4 - 2021/2/15
132
-
133
- - fix scaling issue
134
- - handle firefox buggy versions
135
-
136
- ## 3.0.3 - 2021/1/27
137
-
138
- - no changes
139
- - updated to @applitools/utils@1.0.1 (from 1.0.0)
140
- - updated to @applitools/utils@1.0.1 (from 1.0.0)
141
- ## 3.0.2 - 2021/1/27
142
-
143
- - no changes
144
- ## 3.0.1 - 2021/1/27
145
- - no changes
146
- ## 3.0.0 - 2021/1/26
147
-
148
- - `crop`, `scale` and `rotate` now should be placed in `stabilization` object
149
- - rename `context` to `frames`
150
- - rename `isFully` to `fully`
151
- - integrate dom-capture
152
- - chore: add husky
153
- - fix bug when screenshots on iPad were taken with Safari navigation bar and iOS status bar
154
-
155
- ## 2.1.1 - 2021/1/15
156
-
157
- - fix bug when `toPng` method returns empty buffer
158
- - fix bug when `toPng` method returns empty buffer
159
- ## 2.1.0 - 2021/1/15
160
-
161
- - remove native module dependency (`sharp`)
162
-
163
- ## 2.0.0 - 2021/1/7
164
-
165
- - return image location relative to viewport
166
- - return image location relative to viewport
167
- ## 1.0.2 - 2020/12/29
168
-
169
- - fix saveScreenshot
170
- ## 1.0.1 - 2020/12/1
171
-
172
- - round coordinate and size before image operations
173
-
174
- ## 1.0.0 - 2020/12/1
175
-
176
- - Provide functionality to take screenshots (viewport and full) using Applitools driver wrapper