creevey
Version:
Cross-browser screenshot testing tool for Storybook with fancy UI Runner
113 lines • 4.91 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
const pngjs_1 = require("pngjs");
const pixelmatch_1 = __importDefault(require("pixelmatch"));
function normalizeImageSize(image, width, height) {
const normalizedImage = Buffer.alloc(4 * width * height);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const i = (y * width + x) * 4;
if (x < image.width && y < image.height) {
const j = (y * image.width + x) * 4;
normalizedImage[i + 0] = image.data[j + 0];
normalizedImage[i + 1] = image.data[j + 1];
normalizedImage[i + 2] = image.data[j + 2];
normalizedImage[i + 3] = image.data[j + 3];
}
else {
normalizedImage[i + 0] = 0;
normalizedImage[i + 1] = 0;
normalizedImage[i + 2] = 0;
normalizedImage[i + 3] = 0;
}
}
}
return normalizedImage;
}
function hasDiffPixels(diff) {
for (let i = 0; i < diff.length; i += 4) {
if (diff[i + 0] == 255 && diff[i + 1] == 0 && diff[i + 2] == 0 && diff[i + 3] == 255)
return true;
}
return false;
}
function compareImages(expect, actual, diffOptions) {
const expectImage = pngjs_1.PNG.sync.read(expect);
const actualImage = pngjs_1.PNG.sync.read(actual);
const width = Math.max(actualImage.width, expectImage.width);
const height = Math.max(actualImage.height, expectImage.height);
const diffImage = new pngjs_1.PNG({ width, height });
let actualImageData = actualImage.data;
if (actualImage.width < width || actualImage.height < height) {
actualImageData = normalizeImageSize(actualImage, width, height);
}
let expectImageData = expectImage.data;
if (expectImage.width < width || expectImage.height < height) {
expectImageData = normalizeImageSize(expectImage, width, height);
}
(0, pixelmatch_1.default)(expectImageData, actualImageData, diffImage.data, width, height, diffOptions);
return {
isEqual: !hasDiffPixels(diffImage.data),
diff: pngjs_1.PNG.sync.write(diffImage),
};
}
function default_1(getExpected, diffOptions) {
return function chaiImage({ Assertion }, utils) {
async function assertImage(actual, imageName) {
let onCompare = () => Promise.resolve();
let expected = await getExpected(imageName);
if (!(expected instanceof Buffer) && expected != null)
({ expected, onCompare } = expected);
if (expected == null) {
await onCompare(actual);
return imageName ? `Expected image '${imageName}' does not exists` : 'Expected image does not exists';
}
if (actual.equals(expected)) {
await onCompare(actual);
return;
}
const { isEqual, diff } = compareImages(expected, actual, diffOptions);
if (isEqual) {
await onCompare(actual);
return;
}
await onCompare(actual, expected, diff);
return imageName ? `Expected image '${imageName}' to match` : 'Expected image to match';
}
utils.addMethod(Assertion.prototype, 'matchImage', async function matchImage(imageName) {
const actual = utils.flag(this, 'object');
const errorMessage = await assertImage(typeof actual == 'string' ? Buffer.from(actual, 'base64') : actual, imageName);
if (errorMessage) {
throw createImageError(imageName ? { [imageName]: errorMessage } : errorMessage);
}
});
utils.addMethod(Assertion.prototype, 'matchImages', async function matchImages() {
const errors = {};
await Promise.all(Object.entries(utils.flag(this, 'object')).map(async ([imageName, imageOrBase64]) => {
let errorMessage;
try {
errorMessage = await assertImage(typeof imageOrBase64 == 'string' ? Buffer.from(imageOrBase64, 'base64') : imageOrBase64, imageName);
}
catch (error) {
errorMessage = error.stack;
}
if (errorMessage) {
errors[imageName] = errorMessage;
}
}));
if (Object.keys(errors).length > 0) {
throw createImageError(errors);
}
});
};
}
function createImageError(imageErrors) {
const error = new Error('Expected image to match');
error.images = imageErrors;
return error;
}
//# sourceMappingURL=chai-image.js.map