Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@applitools/screenshoter

Package Overview
Dependencies
Maintainers
22
Versions
173
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@applitools/screenshoter - npm Package Compare versions

Comparing version 3.1.0 to 3.2.0

src/calculate-screenshot-regions.js

10

.bongo/dry-run/package-lock.json

@@ -7,6 +7,6 @@ {

"version": "file:../dry-run.tgz",
"integrity": "sha512-FDyK0CsvbGvDngoG0ZWcaoBwko0y1SsQKnJrGzsgsw6baI/yYlA2z7V8NdhOhS+js2sQ8YblsMWd+oTj5ZPFZQ==",
"integrity": "sha512-bvdZsaxQAxKmnJ8gZFCXKrDZbgDLTokO34q5EpO8fr/r2uyg7BilM6AcbrtOqOn1jNfzJxkEgUdWlfawp7wt9Q==",
"requires": {
"@applitools/snippets": "2.1.4",
"@applitools/utils": "1.2.1",
"@applitools/utils": "1.2.2",
"png-async": "0.9.4"

@@ -21,5 +21,5 @@ }

"@applitools/utils": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@applitools/utils/-/utils-1.2.1.tgz",
"integrity": "sha512-lIHYqgirhkyL+xAc9+FwidAvcI7apB/6Y7uyVimHdTRjjIwAqoazymwYiFZiia+q81F/smPLvMw2RUwU6wi13w=="
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@applitools/utils/-/utils-1.2.2.tgz",
"integrity": "sha512-SyHY41J+hkZR9gma/M8gjbJXLXeLoVS5DQVYd/RinzWAq62Yvg9eA97+8oHDl8s+6ELK6wMcs4yajjqCPdpF0A=="
},

@@ -26,0 +26,0 @@ "png-async": {

@@ -7,2 +7,7 @@

## 3.2.0 - 2021/8/7
- change image processing order and improve general algorithm
- updated to @applitools/utils@1.2.2 (from 1.2.1)
## 3.1.0 - 2021/8/4

@@ -9,0 +14,0 @@

{
"name": "@applitools/screenshoter",
"version": "3.1.0",
"version": "3.2.0",
"description": "Applitools universal screenshoter for web and native applications",

@@ -52,7 +52,7 @@ "keywords": [

"@applitools/snippets": "2.1.4",
"@applitools/utils": "1.2.1",
"@applitools/utils": "1.2.2",
"png-async": "0.9.4"
},
"devDependencies": {
"@applitools/driver": "1.1.0",
"@applitools/driver": "1.1.1",
"@applitools/sdk-release-kit": "0.13.0",

@@ -59,0 +59,0 @@ "eslint": "^7.9.0",

@@ -9,2 +9,4 @@ const fs = require('fs')

let image, size
let transforms = {rotate: 0, scale: 1, crop: null}
if (utils.types.isBase64(data)) {

@@ -22,4 +24,5 @@ const buffer = Buffer.from(data, 'base64')

} else if (data.isImage) {
image = data.toObject()
image = data.toRaw()
size = data.size
transforms = data.transforms
} else if (utils.types.has(data, ['width', 'height'])) {

@@ -32,2 +35,6 @@ image = fromSize(data)

if (!transforms.crop) {
transforms.crop = utils.geometry.region({x: 0, y: 0}, size)
}
return {

@@ -38,51 +45,74 @@ get isImage() {

get size() {
return image.width && image.height ? {width: image.width, height: image.height} : size
return {...utils.geometry.scale(size, transforms.scale)}
},
get transforms() {
return {...transforms}
},
get width() {
return image.width || size.width
return size.width
},
get height() {
return image.height || size.height
return size.height
},
async scale(scaleRatio) {
image = await scale(await image, scaleRatio)
scale(ratio) {
transforms.scale *= ratio
return this
},
async crop(region) {
image = await extract(await image, region)
crop(region) {
if (utils.types.has(region, ['left', 'right', 'top', 'bottom'])) {
region = {
x: region.left / transforms.scale,
y: region.top / transforms.scale,
width: image.width - (region.left + region.right) / transforms.scale,
height: image.height - (region.top + region.bottom) / transforms.scale,
}
} else {
region = utils.geometry.scale(region, 1 / transforms.scale)
}
region = utils.geometry.rotate(region, transforms.rotate)
transforms.crop = utils.geometry.intersect(transforms.crop, region)
size = utils.geometry.round(utils.geometry.size(transforms.crop))
return this
},
async rotate(degree) {
image = await rotate(await image, degree)
rotate(degree) {
transforms.rotate = (transforms.rotate + degree) % 360
return this
},
async copy(image2, offset) {
image = await copy(await image, image2, offset)
async copy(srcImage, offset) {
const [dst, src] = await Promise.all([this.toObject(), srcImage.toObject()])
image = await copy(dst, src, offset)
return this
},
async replace(image2, region) {
image = await replace(await image, image2, region)
async combine(firstImage, lastImage, region) {
const [src, first, last] = await Promise.all([this.toObject(), firstImage.toObject(), lastImage.toObject()])
image = await combine(first, last, src, region)
size = {width: image.width, height: image.height}
return this
},
async debug(debug) {
if (!debug || !debug.path) return
const timestamp = new Date().toISOString().replace(/[-T:.]/g, '_')
const filename =
['screenshot', timestamp, debug.name, debug.suffix].filter(part => part).join('_') + '.png'
return toFile(await image, path.join(debug.path, filename)).catch(() => null)
},
async toObject() {
image = await image
return image
},
async toBuffer() {
image = await image
const image = await this.toObject()
return image.data
},
async toPng() {
return toPng(await image)
return toPng(await this.toObject())
},
async toFile(path) {
return toFile(await image, path)
return toFile(await this.toObject(), path)
},
async toRaw() {
return image
},
async toObject() {
image = await transform(await image, transforms)
transforms = {rotate: 0, scale: 1, crop: utils.geometry.region({x: 0, y: 0}, size)}
return image
},
async debug(debug) {
if (!debug || !debug.path) return
const timestamp = new Date().toISOString().replace(/[-T:.]/g, '_')
const filename = ['screenshot', timestamp, debug.name, debug.suffix].filter(part => part).join('_') + '.png'
return toFile(await transform(await image, transforms), path.join(debug.path, filename)).catch(() => null)
},
}

@@ -99,3 +129,3 @@ }

return new Promise((resolve, reject) => {
const image = new png.Image({filterType: 4})
const image = new png.Image()

@@ -110,3 +140,3 @@ image.parse(buffer, (err, image) => {

async function fromSize(size) {
return new png.Image({filterType: 4, width: size.width, height: size.height})
return new png.Image({width: size.width, height: size.height})
}

@@ -140,2 +170,9 @@

async function transform(image, transforms) {
const croppedImage = transforms.crop ? await extract(image, transforms.crop) : image
const scaledImage = transforms.scale !== 1 ? await scale(croppedImage, transforms.scale) : croppedImage
const rotatedImage = transforms.rotate > 0 ? await rotate(scaledImage, transforms.rotate) : scaledImage
return rotatedImage
}
async function scale(image, scaleRatio) {

@@ -171,11 +208,2 @@ if (scaleRatio === 1) return image

async function extract(image, region) {
if (utils.types.has(region, ['left', 'right', 'top', 'bottom'])) {
region = {
x: region.left,
y: region.top,
width: image.width - region.left - region.right,
height: image.height - region.top - region.bottom,
}
}
const srcX = Math.max(0, Math.round(region.x))

@@ -185,5 +213,10 @@ const srcY = Math.max(0, Math.round(region.y))

const dstHeight = Math.round(Math.min(image.height - srcY, region.height))
const dstSize = {width: dstWidth, height: dstHeight}
const extracted = new png.Image({filterType: 4, width: dstWidth, height: dstHeight})
if (utils.geometry.isEmpty(dstSize)) {
throw new Error(`Cannot extract empty region (${srcX};${srcY})${dstWidth}x${dstHeight} from image`)
}
const extracted = new png.Image(dstSize)
if (srcX === 0 && dstWidth === image.width) {

@@ -197,6 +230,3 @@ const srcOffset = srcY * image.width * 4

const srcOffset = ((srcY + chunk) * image.width + srcX) * 4
extracted.data.set(
image.data.subarray(srcOffset, srcOffset + chunkLength),
chunk * chunkLength,
)
extracted.data.set(image.data.subarray(srcOffset, srcOffset + chunkLength), chunk * chunkLength)
}

@@ -211,3 +241,3 @@ }

const dstImage = new png.Image({filterType: 4, width: image.width, height: image.height})
const dstImage = new png.Image({width: image.width, height: image.height})

@@ -270,14 +300,6 @@ if (degrees === 90) {

async function replace(baseImage, srcImage, region) {
region = utils.geometry.intersect(
{x: 0, y: 0, width: baseImage.width, height: baseImage.height},
region,
)
async function combine(firstImage, lastImage, srcImage, region) {
region = utils.geometry.intersect({x: 0, y: 0, width: firstImage.width, height: firstImage.height}, region)
if (
region.x === 0 &&
region.y === 0 &&
region.width >= baseImage.width &&
region.height >= baseImage.height
) {
if (region.x === 0 && region.y === 0 && region.width >= firstImage.width && region.height >= firstImage.height) {
return srcImage

@@ -287,17 +309,16 @@ }

if (region.width === srcImage.width && region.height === srcImage.height) {
await copy(baseImage, srcImage, {x: region.x, y: region.y})
return baseImage
await copy(firstImage, srcImage, {x: region.x, y: region.y})
return firstImage
}
const dstImage = new png.Image({
filterType: 4,
width: baseImage.width - region.width + srcImage.width,
height: baseImage.height - region.height + srcImage.height,
width: firstImage.width - region.width + srcImage.width,
height: firstImage.height - region.height + srcImage.height,
})
if (region.width === srcImage.width) {
const topImage = await extract(baseImage, {
const topImage = await extract(firstImage, {
x: 0,
y: 0,
width: baseImage.width,
width: firstImage.width,
height: region.y + region.height,

@@ -307,11 +328,11 @@ })

} else if (region.height === srcImage.height) {
const leftImage = await extract(baseImage, {
const leftImage = await extract(firstImage, {
x: 0,
y: 0,
width: region.x + region.width,
height: baseImage.height,
height: firstImage.height,
})
await copy(dstImage, leftImage, {x: 0, y: 0})
} else {
const topLeftImage = await extract(baseImage, {
const topLeftImage = await extract(firstImage, {
x: 0,

@@ -323,6 +344,6 @@ y: 0,

await copy(dstImage, topLeftImage, {x: 0, y: 0})
const topRightImage = await extract(baseImage, {
const topRightImage = await extract(firstImage, {
x: region.x + region.width,
y: 0,
width: baseImage.width - (region.x + region.width),
width: firstImage.width - (region.x + region.width),
height: region.y + region.height,

@@ -335,32 +356,32 @@ })

if (baseImage.height > region.y + region.height) {
if (lastImage.height > region.y + region.height) {
if (region.width === srcImage.width) {
const bottomImage = await extract(baseImage, {
const bottomImage = await extract(lastImage, {
x: 0,
y: region.y + region.height,
width: baseImage.width,
height: baseImage.height - (region.y + region.height),
width: lastImage.width,
height: lastImage.height - (region.y + region.height),
})
await copy(dstImage, bottomImage, {x: 0, y: region.y + srcImage.height})
} else if (region.height === srcImage.height) {
const rightImage = await extract(baseImage, {
const rightImage = await extract(lastImage, {
x: region.x + region.width,
y: 0,
width: baseImage.width - (region.x + region.width),
height: baseImage.height,
width: lastImage.width - (region.x + region.width),
height: lastImage.height,
})
await copy(dstImage, rightImage, {x: region.x + srcImage.width, y: 0})
} else {
const bottomLeftImage = await extract(baseImage, {
const bottomLeftImage = await extract(lastImage, {
x: 0,
y: region.y + region.height,
width: region.x + region.width,
height: baseImage.height - (region.y + region.height),
height: lastImage.height - (region.y + region.height),
})
await copy(dstImage, bottomLeftImage, {x: 0, y: region.y + srcImage.height})
const bottomRightImage = await extract(baseImage, {
const bottomRightImage = await extract(lastImage, {
x: region.x + region.width,
y: region.y + region.height,
width: baseImage.width - (region.x + region.width),
height: baseImage.height - (region.y + region.height),
width: lastImage.width - (region.x + region.width),
height: lastImage.height - (region.y + region.height),
})

@@ -423,4 +444,3 @@ await copy(dstImage, bottomRightImage, {

const y2 = bufSrc[kPos + wDst * 4]
const y3 =
yPos < hSrc - 2 ? bufSrc[kPos + wDst * 8] : 2 * bufSrc[kPos + wDst * 4] - bufSrc[kPos]
const y3 = yPos < hSrc - 2 ? bufSrc[kPos + wDst * 8] : 2 * bufSrc[kPos + wDst * 4] - bufSrc[kPos]

@@ -519,3 +539,3 @@ buf[buf2Pos + k] = _interpolateCubic(y0, y1, y2, y3, t)

if (currentWidth > targetWidth) {
currentWidth -= currentWidth / fraction
currentWidth -= Math.floor(currentWidth / fraction)

@@ -531,3 +551,3 @@ // If we cut the width too far it means we are on our last iteration. Just set it to the target width

if (currentHeight > targetHeight) {
currentHeight -= currentHeight / fraction
currentHeight -= Math.floor(currentHeight / fraction)

@@ -534,0 +554,0 @@ // If we cut the height too far it means we are on our last iteration. Just set it to the target height

const utils = require('@applitools/utils')
const snippets = require('@applitools/snippets')
const makeScroller = require('./scroller')
const takeStitchedScreenshot = require('./takeStitchedScreenshot')
const takeViewportScreenshot = require('./takeViewportScreenshot')
const scrollIntoViewport = require('./scrollIntoViewport')
const scrollIntoViewport = require('./scroll-into-viewport')
const takeStitchedScreenshot = require('./take-stitched-screenshot')
const takeViewportScreenshot = require('./take-viewport-screenshot')
async function screenshoter({
logger,
driver,
frames = [],
target,
region,
fully,
scrollingMode,
hideScrollbars,
hideCaret,
scrollingMode,
overlap,
framed,
wait,
dom,
lazyRestorePageState,
stabilization,
hooks,
debug,
takeDomCapture,
logger,
}) {
const originalContext = driver.currentContext
// screenshot of a window/app was requested (fully or viewport)
const window = !region && (!frames || frames.length === 0)
// framed screenshots could be taken only when screenshot of window/app fully was requested
framed = framed && fully && window
const targetContext =
const activeContext = driver.currentContext
const context =
frames.length > 0
? await originalContext.context(frames.reduce((parent, frame) => ({...frame, parent}), null))
: originalContext
? await activeContext.context(frames.reduce((parent, frame) => ({...frame, parent}), null))
: activeContext
for (const nextContext of targetContext.path) {
// traverse from main context to target context to hide scrollbars and preserve context state (scroll/translate position)
for (const nextContext of context.path) {
const scrollingElement = await nextContext.getScrollingElement()
// unlike web apps, native apps do not always have scrolling element
if (scrollingElement) {

@@ -41,68 +44,33 @@ if (driver.isWeb && hideScrollbars) await scrollingElement.hideScrollbars()

const activeElement = hideCaret && !driver.isNative ? await targetContext.blurElement() : null
// blur active element in target context
const activeElement = driver.isWeb && hideCaret ? await context.blurElement() : null
const window = !target && (!frames || frames.length === 0)
const {context, scroller, region} = await getTargetArea({
logger,
context: targetContext,
window,
target,
fully,
scrollingMode,
})
const target = await getTarget({window, context, region, fully, scrollingMode, logger})
// IMHO problem with scrollbars should be solved by extracting client size of the content (without scrollbars),
// here we use a historical solution
if (driver.isWeb && (hideScrollbars || fully)) await scroller.element.hideScrollbars()
const scrollerState = await scroller.preserveState()
if (driver.isWeb && hideScrollbars) await target.scroller.hideScrollbars()
if (!window) await scrollIntoViewport({logger, context, scroller, region})
try {
if (!window) await scrollIntoViewport({...target, logger})
try {
const screenshot = fully
? await takeStitchedScreenshot({
logger,
context,
scroller,
region,
overlap,
framed: framed && !region,
wait,
stabilization,
debug,
})
: await takeViewportScreenshot({logger, context, region, wait, stabilization, debug})
? await takeStitchedScreenshot({...target, overlap, framed, wait, stabilization, debug, logger})
: await takeViewportScreenshot({...target, wait, stabilization, debug, logger})
if (dom) {
// temporary solution
if (fully) {
await context.execute(snippets.setElementAttributes, [
scroller.element,
{'data-applitools-scroll': true},
])
if (hooks && hooks.afterScreenshot) {
// imitate image-like state for the hook
if (window && fully) {
await target.scroller.moveTo({x: 0, y: 0}, await driver.mainContext.getScrollingElement())
}
const scrollingElement = await context.main.getScrollingElement()
await scroller.moveTo({x: 0, y: 0}, scrollingElement)
screenshot.dom = await takeDomCapture()
await hooks.afterScreenshot({driver, scroller: target.scroller, screenshot})
}
if (lazyRestorePageState) {
screenshot.restorePageState = restorePageState
}
return screenshot
} finally {
if (!lazyRestorePageState) await restorePageState()
}
async function restorePageState() {
if (scroller.element) {
await scroller.element.restoreScrollbars()
await scroller.restoreState(scrollerState)
}
await target.scroller.restoreScrollbars()
if (hideCaret && activeElement) await targetContext.focusElement(activeElement)
// if there was active element and we have blurred it, then restore focus
if (activeElement) await context.focusElement(activeElement)
for (const prevContext of targetContext.path.reverse()) {
// traverse from target context to the main context to restore scrollbars and context states
for (const prevContext of context.path.reverse()) {
const scrollingElement = await prevContext.getScrollingElement()

@@ -115,23 +83,27 @@ if (scrollingElement) {

await originalContext.focus()
// restore focus on original active context
await activeContext.focus()
}
}
async function getTargetArea({logger, context, target, window, fully, scrollingMode}) {
async function getTarget({window, context, region, fully, scrollingMode, logger}) {
if (window) {
// window/app
const scrollingElement = await context.main.getScrollingElement()
return {
context: context.main,
scroller: makeScroller({logger, element: scrollingElement, scrollingMode}),
scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
}
} else if (target) {
if (utils.types.has(target, ['x', 'y', 'width', 'height'])) {
} else if (region) {
if (utils.types.has(region, ['x', 'y', 'width', 'height'])) {
// region by coordinates
const scrollingElement = await context.getScrollingElement()
return {
context,
region: target,
scroller: makeScroller({logger, element: scrollingElement, scrollingMode}),
region,
scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
}
} else {
const element = await context.element(target)
// region by element or selector
const element = await context.element(region)
if (!element) throw new Error('Element not found!')

@@ -141,14 +113,11 @@

const isScrollable = await element.isScrollable()
// if element is scrollable, then take screenshot of the full element content, otherwise take screenshot of full element
const region = isScrollable ? null : await element.getRegion()
const scrollingElement = isScrollable ? element : await context.getScrollingElement()
// css stitching could be applied only to root element of its context
scrollingMode = scrollingMode === 'css' && !(await scrollingElement.isRoot()) ? 'mixed' : scrollingMode
return {
context,
region: isScrollable ? null : await element.getRegion(),
scroller: makeScroller({
logger,
element: scrollingElement,
scrollingMode:
scrollingMode === 'css' && !(await scrollingElement.isRoot())
? 'mixed'
: scrollingMode,
}),
region,
scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
}

@@ -160,20 +129,23 @@ } else {

region: await element.getRegion(),
scroller: makeScroller({logger, element: scrollingElement, scrollingMode}),
scroller: makeScroller({element: scrollingElement, scrollingMode, logger}),
}
}
}
} else if (!context.isMain && !fully) {
const scrollingElement = await context.parent.getScrollingElement()
const element = await context.getContextElement()
return {
context: context.parent,
region: await element.getRegion(), // IMHO we should use CLIENT (without borders) region here
scroller: makeScroller({logger, element: scrollingElement, scrollingMode}),
} else if (!context.isMain) {
// context
if (fully) {
const scrollingElement = await context.getScrollingElement()
return {
context,
scroller: makeScroller({logger, element: scrollingElement, scrollingMode}),
}
} else {
const scrollingElement = await context.parent.getScrollingElement()
const element = await context.getContextElement()
return {
context: context.parent,
region: await element.getRegion(), // IMHO we should use CLIENT (without borders) region here
scroller: makeScroller({logger, element: scrollingElement, scrollingMode}),
}
}
} else {
const scrollingElement = await context.getScrollingElement()
return {
context,
scroller: makeScroller({logger, element: scrollingElement, scrollingMode}),
}
}

@@ -180,0 +152,0 @@ }

@@ -20,2 +20,4 @@ const utils = require('@applitools/utils')

restoreState,
hideScrollbars,
restoreScrollbars,
}

@@ -136,4 +138,21 @@

}
async function hideScrollbars(element = defaultElement) {
try {
return element.hideScrollbars()
} catch (err) {
logger.verbose(`Failed to get current transforms!.`, err)
return {}
}
}
async function restoreScrollbars(state, element = defaultElement) {
try {
await element.restoreScrollbars(state)
} catch (err) {
logger.verbose(`Failed to restore state!.`, err)
}
}
}
module.exports = makeScroller

@@ -56,4 +56,8 @@ const assert = require('assert')

it('take full app screenshot (recycler view)', () => {
return fullAppRecyclerViewX()
})
it('take full element screenshot', () => {
return fullElement()
return fullElementX()
})

@@ -64,8 +68,10 @@ })

const screenshot = await screenshoter({logger, driver, ...options})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/app.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/app.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'viewport_failed'})
throw err
}
}

@@ -85,8 +91,10 @@ async function fullAppScrollView(options) {

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/app-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/app-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_app_scroll_failed'})
throw err
}
}

@@ -106,9 +114,33 @@ async function fullAppRecyclerView(options) {

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/app-fully-recycler.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/app-fully-recycler.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_app_recycler_failed'})
throw err
}
}
async function fullAppRecyclerViewX(options) {
const button = await driver.element({type: 'id', selector: 'btn_recycler_view_activity'})
await button.click()
const screenshot = await screenshoter({
logger,
driver,
fully: true,
framed: true,
scrollingMode: 'scroll',
wait: 1500,
...options,
})
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/app-fully-recycler-x.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_app_recycler_x_failed'})
throw err
}
}
async function region(options) {

@@ -118,12 +150,14 @@ const screenshot = await screenshoter({

driver,
target: {x: 30, y: 500, height: 100, width: 200},
region: {x: 30, y: 500, height: 100, width: 200},
scrollingMode: 'scroll',
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/region.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/region.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'region_failed'})
throw err
}
}

@@ -134,3 +168,3 @@ async function fullRegion(options) {

driver,
target: {x: 30, y: 10, height: 700, width: 200},
region: {x: 30, y: 10, height: 700, width: 200},
fully: true,

@@ -140,8 +174,10 @@ scrollingMode: 'scroll',

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/region-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/region-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_region_failed'})
throw err
}
}

@@ -152,14 +188,16 @@ async function element(options) {

driver,
target: {type: 'id', selector: 'btn_recycler_view'},
region: {type: 'id', selector: 'btn_recycler_view'},
scrollingMode: 'scroll',
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/element.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/element.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'element_failed'})
throw err
}
}
async function fullElement(options) {
async function fullElementX(options) {
const button = await driver.element({

@@ -174,3 +212,3 @@ type: 'id',

driver,
target: {type: 'id', selector: 'recyclerView'},
region: {type: 'id', selector: 'recyclerView'},
fully: true,

@@ -181,9 +219,11 @@ scrollingMode: 'scroll',

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/element-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/android/element-fully-x.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_element_x_failed'})
throw err
}
}
})

@@ -54,8 +54,10 @@ const assert = require('assert')

const screenshot = await screenshoter({logger, driver, ...options})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/app.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/app.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'viewport_failed'})
throw err
}
}

@@ -75,8 +77,10 @@ async function fullAppScrollView(options) {

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/app-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/app-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_app_failed'})
throw err
}
}

@@ -96,8 +100,10 @@ async function fullAppTableView(options) {

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/app-fully-table.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/app-fully-table.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_app_table_failed'})
throw err
}
}

@@ -117,8 +123,10 @@ async function fullAppCollectionView(options) {

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/app-fully-collection.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/app-fully-collection.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_app_collection_failed'})
throw err
}
}

@@ -129,3 +137,3 @@ async function region(options) {

driver,
target: {x: 30, y: 500, height: 100, width: 200},
region: {x: 30, y: 500, height: 100, width: 200},
scrollingMode: 'scroll',

@@ -135,8 +143,10 @@ wait: 1500,

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/region.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/region.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'region_failed'})
throw err
}
}

@@ -147,3 +157,3 @@ async function fullRegion(options) {

driver,
target: {x: 30, y: 10, height: 700, width: 200},
region: {x: 30, y: 10, height: 700, width: 200},
fully: true,

@@ -153,8 +163,10 @@ scrollingMode: 'scroll',

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/region-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/region-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_region_failed'})
throw err
}
}

@@ -165,12 +177,14 @@ async function element(options) {

driver,
target: {type: 'accessibility id', selector: 'Table view'},
region: {type: 'accessibility id', selector: 'Table view'},
scrollingMode: 'scroll',
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/element.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/element.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'element_failed'})
throw err
}
}

@@ -187,3 +201,3 @@ async function fullElement(options) {

driver,
target: {type: 'xpath', selector: '//XCUIElementTypeTable[1]'},
region: {type: 'xpath', selector: '//XCUIElementTypeTable[1]'},
fully: true,

@@ -194,9 +208,11 @@ scrollingMode: 'scroll',

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/element-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/ios/element-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_element_failed'})
throw err
}
}
})

@@ -121,36 +121,32 @@ const assert = require('assert')

const screenshot = await screenshoter({logger, driver, ...options})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/page.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/page.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'viewport_failed'})
throw err
}
}
async function fullPage(options) {
const screenshot = await screenshoter({
logger,
driver,
fully: true,
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/page-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
const screenshot = await screenshoter({logger, driver, fully: true, ...options})
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/page-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_page_failed'})
throw err
}
}
async function frame(options) {
const screenshot = await screenshoter({
logger,
driver,
frames: [{reference: 'iframe[name="frame1"]'}],
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/frame.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
const screenshot = await screenshoter({logger, driver, frames: [{reference: 'iframe[name="frame1"]'}], ...options})
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/frame.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'frame_failed'})
throw err
}
}

@@ -165,66 +161,56 @@ async function fullFrame(options) {

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/frame-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/frame-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_frame_failed'})
throw err
}
}
async function region(options) {
const screenshot = await screenshoter({
logger,
driver,
target: {x: 30, y: 500, height: 100, width: 200},
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/region.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
const region = {x: 30, y: 500, height: 100, width: 200}
const screenshot = await screenshoter({logger, driver, region, ...options})
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/region.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'region_failed'})
throw err
}
}
async function fullRegion(options) {
const screenshot = await screenshoter({
logger,
driver,
target: {x: 30, y: 500, height: 700, width: 200},
fully: true,
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/region-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
const region = {x: 30, y: 500, height: 700, width: 200}
const screenshot = await screenshoter({logger, driver, region, fully: true, ...options})
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/region-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_region_failed'})
throw err
}
}
async function element(options) {
const screenshot = await screenshoter({
logger,
driver,
target: '#overflowing-div-image',
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/element.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
const screenshot = await screenshoter({logger, driver, region: '#overflowing-div-image', ...options})
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/element.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'element_failed'})
throw err
}
}
async function fullElement(options) {
const screenshot = await screenshoter({
logger,
driver,
target: '#overflowing-div-image',
fully: true,
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/element-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
const screenshot = await screenshoter({logger, driver, region: '#overflowing-div-image', fully: true, ...options})
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/element-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_element_failed'})
throw err
}
}

@@ -236,11 +222,13 @@ async function regionInFrame(options) {

frames: [{reference: 'iframe[name="frame1"]'}],
target: {x: 10, y: 20, width: 110, height: 120},
region: {x: 10, y: 20, width: 110, height: 120},
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-region.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-region.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'region_in_frame_failed'})
throw err
}
}

@@ -252,12 +240,14 @@ async function fullRegionInFrame(options) {

frames: [{reference: 'iframe[name="frame1"]'}],
target: {x: 10, y: 100, width: 1000, height: 120},
region: {x: 10, y: 100, width: 1000, height: 120},
fully: true,
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-region-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-region-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_region_in_frame_failed'})
throw err
}
}

@@ -269,11 +259,13 @@ async function elementInFrame(options) {

frames: [{reference: 'iframe[name="frame1"]'}],
target: '#inner-frame-div',
region: '#inner-frame-div',
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-element.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-element.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'element_in_frame_failed'})
throw err
}
}

@@ -285,12 +277,14 @@ async function fullElementInFrame(options) {

frames: [{reference: 'iframe[name="frame1"]'}],
target: '#inner-frame-div',
region: '#inner-frame-div',
fully: true,
...options,
})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-element-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-element-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_element_in_frame_failed'})
throw err
}
}

@@ -304,8 +298,10 @@ async function frameInFrame(options) {

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-frame.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-frame.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'frame_in_frame_failed'})
throw err
}
}

@@ -320,9 +316,11 @@ async function fullFrameInFrame(options) {

})
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-frame-fully.png').toObject()
assert.strictEqual(
pixelmatch(actual.data, expected.data, null, expected.width, expected.height),
0,
)
try {
const actual = await screenshot.image.toObject()
const expected = await makeImage('./test/fixtures/web/inner-frame-fully.png').toObject()
assert.strictEqual(pixelmatch(actual.data, expected.data, null, expected.width, expected.height), 0)
} catch (err) {
await screenshot.image.debug({path: './logs', name: 'full_frame_in_frame_failed'})
throw err
}
}
})
const assert = require('assert')
const makeImage = require('../../src/image')
const findPattern = require('../../src/findPattern')
const findPattern = require('../../src/find-image-pattern')

@@ -5,0 +5,0 @@ describe('pattern', () => {

@@ -86,7 +86,5 @@ const assert = require('assert')

replace.data.fill(Buffer.from([0xff, 0, 0, 0xff]))
await image.replace(replace, {x: 200, y: 200, width: 100, height: 100})
await replace.combine(image, image, {x: 200, y: 200, width: 100, height: 100})
const actual = await image.toObject()
const expected = await makeImage(
'./test/fixtures/image/house.replaced-higher-wider.png',
).toObject()
const expected = await makeImage('./test/fixtures/image/house.replaced-higher-wider.png').toObject()
assert.ok(pixelmatch(actual.data, expected.data, null, expected.width, expected.height) === 0)

@@ -99,3 +97,3 @@ })

replace.data.fill(Buffer.from([0, 0xff, 0, 0xff]))
await image.replace(replace, {x: 200, y: 200, width: 200, height: 100})
await replace.combine(image, image, {x: 200, y: 200, width: 200, height: 100})
const actual = await image.toObject()

@@ -110,3 +108,3 @@ const expected = await makeImage('./test/fixtures/image/house.replaced-higher.png').toObject()

replace.data.fill(Buffer.from([0, 0, 0xff, 0xff]))
await image.replace(replace, {x: 200, y: 200, width: 100, height: 200})
await replace.combine(image, image, {x: 200, y: 200, width: 100, height: 200})
const actual = await image.toObject()

@@ -113,0 +111,0 @@ const expected = await makeImage('./test/fixtures/image/house.replaced-wider.png').toObject()

@@ -50,5 +50,3 @@ const webdriverio = require('webdriverio')

if (browser.isDevTools || browser.isIOS) {
return browser
.execute((element1, element2) => element1 === element2, element1, element2)
.catch(() => false)
return browser.execute((element1, element2) => element1 === element2, element1, element2).catch(() => false)
}

@@ -263,4 +261,3 @@ if (!element1 || !element2) return false

automationName: 'XCUITest',
app:
'https://applitools.jfrog.io/artifactory/Examples/IOSTestApp/1.5/app/IOSTestApp-1.5.zip',
app: 'https://applitools.jfrog.io/artifactory/Examples/IOSTestApp/1.5/app/IOSTestApp-1.5.zip',
username: process.env.SAUCE_USERNAME,

@@ -267,0 +264,0 @@ accessKey: process.env.SAUCE_ACCESS_KEY,

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc