pdf-visual-diff
Version:
Visual Regression Testing for PDFs in JavaScript
249 lines • 14.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const node_test_1 = require("node:test");
const assert = __importStar(require("node:assert/strict"));
const node_path_1 = require("node:path");
const promises_1 = require("node:fs/promises");
const node_os_1 = require("node:os");
const jimp_1 = require("jimp");
const compare_pdf_to_snapshot_1 = require("./compare-pdf-to-snapshot");
const compare_images_1 = require("./compare-images");
const types_1 = require("./types");
const testDataDir = (0, node_path_1.join)(__dirname, './test-data');
const pdfs = (0, node_path_1.join)(testDataDir, 'pdfs');
const singlePageSmallPdfPath = (0, node_path_1.join)(pdfs, 'single-page-small.pdf');
const singlePagePdfPath = (0, node_path_1.join)(pdfs, 'single-page.pdf');
const barcodes1PdfPath = (0, node_path_1.join)(pdfs, 'barcodes-1.pdf');
const twoPagePdfPath = (0, node_path_1.join)(pdfs, 'two-page.pdf');
// Tolerance for cross-platform font rendering differences
// Snapshots are generated on Linux, so use strict tolerance there
const isLinux = (0, node_os_1.platform)() === 'linux';
const crossPlatformTolerance = isLinux ? 0 : 0.05;
async function removeIfExists(filePath) {
try {
await (0, promises_1.unlink)(filePath);
}
catch {
// File doesn't exist, no need to remove
}
}
async function fileExists(filePath) {
try {
await (0, promises_1.access)(filePath);
return true;
}
catch {
return false;
}
}
(0, node_test_1.describe)('comparePdfToSnapshot()', () => {
(0, node_test_1.it)('should create new snapshot, when one does not exists', async () => {
const snapshotName = 'single-page-small';
const snapshotPath = (0, node_path_1.join)(__dirname, compare_pdf_to_snapshot_1.SNAPSHOTS_DIR_NAME, `${snapshotName}.png`);
await removeIfExists(snapshotPath);
const isEqual = await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(singlePageSmallPdfPath, __dirname, snapshotName);
assert.strictEqual(isEqual, true);
assert.strictEqual(await fileExists(snapshotPath), true);
await removeIfExists(snapshotPath);
});
(0, node_test_1.it)('should fail and create diff with new version', async () => {
const isEqual = await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(singlePagePdfPath, __dirname, 'two-page');
// Should not match
assert.strictEqual(isEqual, false);
const snapshotDiffPath = (0, node_path_1.join)(__dirname, compare_pdf_to_snapshot_1.SNAPSHOTS_DIR_NAME, 'two-page.diff.png');
assert.strictEqual(await fileExists(snapshotDiffPath), true, 'diff is not created');
const snapshotNewPath = (0, node_path_1.join)(__dirname, compare_pdf_to_snapshot_1.SNAPSHOTS_DIR_NAME, 'two-page.new.png');
assert.strictEqual(await fileExists(snapshotNewPath), true, 'new is not created');
});
(0, node_test_1.it)('should remove diff and new snapshots when matches with reference snapshot', async () => {
const snapshotName = 'should-remove-diff-and-new';
const snapshotBase = (0, node_path_1.join)(__dirname, compare_pdf_to_snapshot_1.SNAPSHOTS_DIR_NAME, snapshotName);
const snapshotPathDiff = `${snapshotBase}.diff.png`;
const snapshotPathNew = `${snapshotBase}.new.png`;
await removeIfExists(snapshotPathDiff);
await removeIfExists(snapshotPathNew);
await new jimp_1.Jimp({ width: 100, height: 100 }).write(snapshotPathDiff);
await new jimp_1.Jimp({ width: 100, height: 100 }).write(snapshotPathNew);
const isEqual = await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(singlePageSmallPdfPath, __dirname, snapshotName);
assert.strictEqual(isEqual, true);
assert.strictEqual(await fileExists(snapshotPathDiff), false, 'Snapshot diff should not exists.');
assert.strictEqual(await fileExists(snapshotPathNew), false, 'Snapshot new should not exists.');
});
(0, node_test_1.describe)('should pass', () => {
(0, node_test_1.it)('should pass', () => (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(twoPagePdfPath, __dirname, 'two-page-success').then((x) => assert.strictEqual(x, true)));
const testDataDir = (0, node_path_1.join)(__dirname, './test-data');
const pdfs = (0, node_path_1.join)(testDataDir, 'pdfs');
const singlePageSmall = (0, node_path_1.join)(pdfs, 'single-page-small.pdf');
const singlePage = (0, node_path_1.join)(pdfs, 'single-page.pdf');
const tamReview = (0, node_path_1.join)(pdfs, 'TAMReview.pdf');
const twoPage = (0, node_path_1.join)(pdfs, 'two-page.pdf');
const expectedDir = (0, node_path_1.join)(testDataDir, 'pdf2png-expected');
const testPdf2png = (pdf, expectedImageName, options) => {
return (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(pdf, expectedDir, expectedImageName, options).then((x) => {
assert.strictEqual(x, true);
});
};
(0, node_test_1.it)('single-page-small.pdf', () => testPdf2png(singlePageSmall, 'single-page-small'));
(0, node_test_1.it)('single-page.pdf', () => testPdf2png(singlePage, 'single-page'));
(0, node_test_1.it)('TAMReview.pdf', () => testPdf2png(tamReview, 'TAMReview', { tolerance: crossPlatformTolerance }));
(0, node_test_1.it)('TAMReview.pdf without scaling', () => testPdf2png(tamReview, 'TAMReview_without_scaling', {
pdf2PngOptions: { dpi: types_1.Dpi.Low },
tolerance: crossPlatformTolerance,
}));
(0, node_test_1.it)('two-page.pdf', () => testPdf2png(twoPage, 'two-page'));
(0, node_test_1.it)('two-page.pdf buffer', () => (0, promises_1.readFile)(twoPage).then((x) => testPdf2png(x, 'two-page')));
});
(0, node_test_1.describe)('mask regions', () => {
const blueMask = {
type: 'rectangle-mask',
x: 50,
y: 75,
width: 140,
height: 100,
color: 'Blue',
};
const greenMask = {
type: 'rectangle-mask',
x: 110,
y: 200,
width: 90,
height: 50,
color: 'Green',
};
const opts = {
maskRegions: () => [blueMask, greenMask],
};
(0, node_test_1.it)('should succeed comparing masked pdf', () => (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(singlePagePdfPath, __dirname, 'mask-rectangle-masks', opts).then((x) => assert.strictEqual(x, true)));
(0, node_test_1.it)('should succeed comparing masked pdf without scaling', () => {
const blueMaskSmall = {
type: 'rectangle-mask',
x: 25,
y: 37,
width: 70,
height: 50,
color: 'Blue',
};
const greenMaskSmall = {
type: 'rectangle-mask',
x: 55,
y: 100,
width: 45,
height: 25,
color: 'Green',
};
return (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(singlePagePdfPath, __dirname, 'mask-rectangle-masks_without_scaling', {
pdf2PngOptions: { dpi: 72 },
maskRegions: () => [blueMaskSmall, greenMaskSmall],
}).then((x) => assert.strictEqual(x, true));
});
(0, node_test_1.it)('should mask multi page pdf', () => (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(twoPagePdfPath, __dirname, 'mask-multi-page-pdf', opts).then((x) => assert.strictEqual(x, true)));
(0, node_test_1.it)('should have different mask per page', () => (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(twoPagePdfPath, __dirname, 'mask-different-mask-per-page', {
maskRegions: (page) => {
switch (page) {
case 1:
return [blueMask];
case 2:
return [greenMask];
default:
return [];
}
},
}).then((x) => assert.strictEqual(x, true)));
(0, node_test_1.it)('should mask only second page of the pdf', () => (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(twoPagePdfPath, __dirname, 'mask-only-second-page-of-the-pdf', {
maskRegions: (page) => (page === 2 ? [blueMask, greenMask] : []),
}).then((x) => assert.strictEqual(x, true)));
(0, node_test_1.it)('should mask only second page of the pdf and handle undefined masks', () => (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(twoPagePdfPath, __dirname, 'mask-only-second-page-of-the-pdf-with-undefined', {
maskRegions: (page) => (page === 2 ? [blueMask, greenMask] : undefined),
}).then((x) => assert.strictEqual(x, true)));
(0, node_test_1.it)('should create initial masked image', async () => {
const snapshotName = 'initial-rectangle-masks';
const snapshotPath = (0, node_path_1.join)(__dirname, compare_pdf_to_snapshot_1.SNAPSHOTS_DIR_NAME, snapshotName + '.png');
const expectedImagePath = (0, node_path_1.join)(__dirname, './test-data', 'expected-initial-rectangle-masks.png');
await removeIfExists(snapshotPath);
const isEqual = await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(singlePagePdfPath, __dirname, snapshotName, opts);
assert.strictEqual(isEqual, true);
const img = (await jimp_1.Jimp.read(snapshotPath));
const { equal } = await (0, compare_images_1.compareImages)(expectedImagePath, [img], { tolerance: 0 });
assert.strictEqual(equal, true, 'Rectangle masks does not match expected one');
await removeIfExists(snapshotPath);
});
});
(0, node_test_1.describe)('when reference snapshot does not exist', () => {
(0, node_test_1.it)('should be created when `failOnMissingSnapshot` is not set', async () => {
const snapshotName = 'allow-create-snapshot-when-failOnMissingSnapshot-is-not-set';
const snapshotPath = (0, node_path_1.join)(__dirname, compare_pdf_to_snapshot_1.SNAPSHOTS_DIR_NAME, snapshotName + '.png');
await removeIfExists(snapshotPath);
const isEqual = await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(singlePageSmallPdfPath, __dirname, snapshotName);
assert.strictEqual(isEqual, true);
assert.strictEqual(await fileExists(snapshotPath), true, 'Snapshot should be created');
removeIfExists(snapshotPath);
});
(0, node_test_1.it)('should be created when `failOnMissingSnapshot` is set to `false`', async () => {
const snapshotName = 'allow-create-snapshot-when-failOnMissingSnapshot-is-set-to-false';
const snapshotPath = (0, node_path_1.join)(__dirname, compare_pdf_to_snapshot_1.SNAPSHOTS_DIR_NAME, snapshotName + '.png');
await removeIfExists(snapshotPath);
const isEqual = await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(singlePageSmallPdfPath, __dirname, snapshotName, {
failOnMissingSnapshot: false,
});
assert.strictEqual(isEqual, true);
assert.strictEqual(await fileExists(snapshotPath), true, 'Snapshot should be created');
await removeIfExists(snapshotPath);
});
(0, node_test_1.it)('should not be created and return `false` when `failOnMissingSnapshot` is set to `true`', async () => {
const snapshotName = 'fail-on-missing-snapshot-when-failOnMissingSnapshot-is-set-to-true';
const snapshotPath = (0, node_path_1.join)(__dirname, compare_pdf_to_snapshot_1.SNAPSHOTS_DIR_NAME, snapshotName + '.png');
await removeIfExists(snapshotPath);
const isEqual = await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(singlePageSmallPdfPath, __dirname, snapshotName, {
failOnMissingSnapshot: true,
});
assert.strictEqual(isEqual, false);
assert.strictEqual(await fileExists(snapshotPath), false, 'Snapshot should not be created');
});
});
(0, node_test_1.describe)('github issue', () => {
// TODO: Investigate why this test fails on Windows/macOS and fix the underlying issue
(0, node_test_1.it)('#89 discrepancy between windows and linux/mac using v0.14.0', { skip: !isLinux }, async () => {
await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(barcodes1PdfPath, __dirname, 'barcodes-1-default-opts').then((x) => assert.strictEqual(x, true));
await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(barcodes1PdfPath, __dirname, 'barcodes-1-dpi-low', {
pdf2PngOptions: { dpi: types_1.Dpi.Low },
}).then((x) => assert.strictEqual(x, true));
await (0, compare_pdf_to_snapshot_1.comparePdfToSnapshot)(barcodes1PdfPath, __dirname, 'barcodes-1-default-low-x-4', {
pdf2PngOptions: { dpi: types_1.Dpi.Low * 4 },
}).then((x) => assert.strictEqual(x, true));
});
});
});
//# sourceMappingURL=compare-pdf-to-snapshot.test.js.map