testplane
Version:
Tests framework based on mocha and wdio
145 lines • 6.15 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Image = void 0;
const fs_1 = __importDefault(require("fs"));
const looks_same_1 = __importDefault(require("looks-same"));
const preload_utils_1 = require("./utils/preload-utils");
const eight_bit_rgba_to_png_1 = require("./utils/eight-bit-rgba-to-png");
const png_1 = require("./constants/png");
const initJsquashPromise = new Promise(resolve => {
const wasmLocation = require.resolve("@jsquash/png/codec/pkg/squoosh_png_bg.wasm");
Promise.all([
(0, preload_utils_1.loadEsm)("@jsquash/png/decode.js"),
fs_1.default.promises.readFile(wasmLocation),
])
.then(([mod, wasmBytes]) => mod.init(wasmBytes))
.then(resolve);
});
const jsquashDecode = (buffer) => {
return Promise.all([
(0, preload_utils_1.loadEsm)("@jsquash/png/decode.js"),
initJsquashPromise,
]).then(([mod]) => mod.decode(buffer, { bitDepth: png_1.BITS_IN_BYTE }));
};
class Image {
static create(buffer) {
return new this(buffer);
}
constructor(buffer) {
this._imgData = null;
this._composeImages = [];
this._width = buffer.readUInt32BE(png_1.PNG_WIDTH_OFFSET);
this._height = buffer.readUInt32BE(png_1.PNG_HEIGHT_OFFSET);
this._imgDataPromise = jsquashDecode(buffer).then(({ data }) => {
return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
});
}
async _getImgData() {
if (this._imgData) {
return this._imgData;
}
return (this._imgData = await this._imgDataPromise);
}
_ensureImagesHaveSameWidth() {
for (const image of this._composeImages) {
if (image._width !== this._width) {
throw new Error([
`It looks like viewport width changed while performing long page screenshot (${this._width}px -> ${image._width}px)`,
"Please make sure page is fully loaded before making screenshot",
].join("\n"));
}
}
}
async getSize() {
this._ensureImagesHaveSameWidth();
const height = this._composeImages.reduce((acc, img) => acc + img._height, this._height);
return { height, width: this._width };
}
async crop(rect) {
const imgData = await this._getImgData();
let bufferPointer = 0;
let sourceOffset = (rect.top * this._width + rect.left) * png_1.RGBA_CHANNELS;
const bytesToCopy = Math.min(rect.width, this._width - rect.left) * png_1.RGBA_CHANNELS;
const bytesToIterate = this._width * png_1.RGBA_CHANNELS;
for (let i = 0; i < Math.min(rect.height, this._height - rect.top); i++) {
imgData.copy(imgData, bufferPointer, sourceOffset, sourceOffset + bytesToCopy);
bufferPointer += bytesToCopy;
sourceOffset += bytesToIterate;
}
this._imgData = imgData.subarray(0, bufferPointer);
this._width = rect.width;
this._height = rect.height;
}
addJoin(attachedImages) {
this._composeImages = this._composeImages.concat(attachedImages);
}
async applyJoin() {
if (!this._composeImages.length)
return;
this._ensureImagesHaveSameWidth();
const resultHeight = this._composeImages.reduce((acc, img) => acc + img._height, this._height);
const imageBuffers = await Promise.all([this, ...this._composeImages].map(img => img._getImgData()));
this._imgData = Buffer.concat(imageBuffers);
this._height = resultHeight;
this._composeImages = [];
}
async clearArea(rect) {
const imgData = await this._getImgData();
let sourceOffset = (rect.top * this._width + rect.left) * png_1.RGBA_CHANNELS;
const bytesToCopyAmount = Math.min(rect.width, this._width - rect.left) * png_1.RGBA_CHANNELS;
const bytesToIterate = this._width * png_1.RGBA_CHANNELS;
const bytesToFill = Buffer.from([0, 0, 0, 255]); // black RGBA
for (let i = 0; i < Math.min(rect.height, this._height - rect.top); i++) {
imgData.fill(bytesToFill, sourceOffset, sourceOffset + bytesToCopyAmount);
sourceOffset += bytesToIterate;
}
}
async getRGB(x, y) {
const imgData = await this._getImgData();
const idx = (this._width * y + x) * png_1.RGBA_CHANNELS;
return {
R: imgData[idx],
G: imgData[idx + 1],
B: imgData[idx + 2],
};
}
async _getPngBuffer() {
const imageData = await this._getImgData();
return (0, eight_bit_rgba_to_png_1.convertRgbaToPng)(imageData, this._width, this._height);
}
async save(file) {
const data = await this._getPngBuffer();
await fs_1.default.promises.writeFile(file, data);
}
static fromBase64(base64) {
return new this(Buffer.from(base64, "base64"));
}
async toPngBuffer(opts = { resolveWithObject: true }) {
const data = await this._getPngBuffer();
return opts.resolveWithObject ? { data, size: { width: this._width, height: this._height } } : data;
}
static compare(path1, path2, opts = {}) {
const compareOptions = {
ignoreCaret: opts.canHaveCaret,
pixelRatio: opts.pixelRatio,
...opts.compareOpts,
};
if (opts.tolerance) {
compareOptions.tolerance = opts.tolerance;
}
if (opts.antialiasingTolerance) {
compareOptions.antialiasingTolerance = opts.antialiasingTolerance;
}
return (0, looks_same_1.default)(path1, path2, { ...compareOptions, createDiffImage: true });
}
static buildDiff(opts) {
const { diffColor: highlightColor, ...otherOpts } = opts;
const diffOptions = { highlightColor, ...otherOpts };
return looks_same_1.default.createDiff(diffOptions);
}
}
exports.Image = Image;
//# sourceMappingURL=image.js.map