diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /remote/test/puppeteer/test/src/golden-utils.ts | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'remote/test/puppeteer/test/src/golden-utils.ts')
-rw-r--r-- | remote/test/puppeteer/test/src/golden-utils.ts | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/remote/test/puppeteer/test/src/golden-utils.ts b/remote/test/puppeteer/test/src/golden-utils.ts new file mode 100644 index 0000000000..939f69c968 --- /dev/null +++ b/remote/test/puppeteer/test/src/golden-utils.ts @@ -0,0 +1,169 @@ +/** + * @license + * Copyright 2017 Google Inc. + * SPDX-License-Identifier: Apache-2.0 + */ +import assert from 'assert'; +import fs from 'fs'; +import path from 'path'; + +import {diffLines} from 'diff'; +import jpeg from 'jpeg-js'; +import mime from 'mime'; +import pixelmatch from 'pixelmatch'; +import {PNG} from 'pngjs'; + +interface DiffFile { + diff: string | Buffer; + ext?: string; +} + +const GoldenComparators = new Map< + string, + ( + actualBuffer: string | Buffer, + expectedBuffer: string | Buffer, + mimeType: string + ) => DiffFile | undefined +>(); + +const addSuffix = ( + filePath: string, + suffix: string, + customExtension?: string +): string => { + const dirname = path.dirname(filePath); + const ext = path.extname(filePath); + const name = path.basename(filePath, ext); + return path.join(dirname, name + suffix + (customExtension || ext)); +}; + +const compareImages = ( + actualBuffer: string | Buffer, + expectedBuffer: string | Buffer, + mimeType: string +): DiffFile | undefined => { + assert(typeof actualBuffer !== 'string'); + assert(typeof expectedBuffer !== 'string'); + + const actual = + mimeType === 'image/png' + ? PNG.sync.read(actualBuffer) + : jpeg.decode(actualBuffer); + + const expected = + mimeType === 'image/png' + ? PNG.sync.read(expectedBuffer) + : jpeg.decode(expectedBuffer); + if (expected.width !== actual.width || expected.height !== actual.height) { + throw new Error( + `Sizes differ: expected image ${expected.width}px X ${expected.height}px, but got ${actual.width}px X ${actual.height}px.` + ); + } + const diff = new PNG({width: expected.width, height: expected.height}); + const count = pixelmatch( + expected.data, + actual.data, + diff.data, + expected.width, + expected.height, + {threshold: 0.1} + ); + return count > 0 ? {diff: PNG.sync.write(diff)} : undefined; +}; + +const compareText = ( + actual: string | Buffer, + expectedBuffer: string | Buffer +): DiffFile | undefined => { + assert(typeof actual === 'string'); + const expected = expectedBuffer.toString('utf-8'); + if (expected === actual) { + return; + } + const result = diffLines(expected, actual); + const html = result.reduce( + (text, change) => { + text += change.added + ? `<span class='ins'>${change.value}</span>` + : change.removed + ? `<span class='del'>${change.value}</span>` + : change.value; + return text; + }, + `<link rel="stylesheet" href="file://${path.join( + __dirname, + 'diffstyle.css' + )}">` + ); + return { + diff: html, + ext: '.html', + }; +}; + +GoldenComparators.set('image/png', compareImages); +GoldenComparators.set('image/jpeg', compareImages); +GoldenComparators.set('text/plain', compareText); + +export const compare = ( + goldenPath: string, + outputPath: string, + actual: string | Buffer, + goldenName: string +): {pass: true} | {pass: false; message: string} => { + goldenPath = path.normalize(goldenPath); + outputPath = path.normalize(outputPath); + const expectedPath = path.join(goldenPath, goldenName); + const actualPath = path.join(outputPath, goldenName); + + const messageSuffix = `Output is saved in "${path.basename( + outputPath + '" directory' + )}`; + + if (!fs.existsSync(expectedPath)) { + ensureOutputDir(); + fs.writeFileSync(actualPath, actual); + return { + pass: false, + message: `${goldenName} is missing in golden results. ${messageSuffix}`, + }; + } + const expected = fs.readFileSync(expectedPath); + const mimeType = mime.getType(goldenName); + assert(mimeType); + const comparator = GoldenComparators.get(mimeType); + if (!comparator) { + return { + pass: false, + message: `Failed to find comparator with type ${mimeType}: ${goldenName}`, + }; + } + const result = comparator(actual, expected, mimeType); + if (!result) { + return {pass: true}; + } + ensureOutputDir(); + if (goldenPath === outputPath) { + fs.writeFileSync(addSuffix(actualPath, '-actual'), actual); + } else { + fs.writeFileSync(actualPath, actual); + // Copy expected to the output/ folder for convenience. + fs.writeFileSync(addSuffix(actualPath, '-expected'), expected); + } + if (result) { + const diffPath = addSuffix(actualPath, '-diff', result.ext); + fs.writeFileSync(diffPath, result.diff); + } + + return { + pass: false, + message: `${goldenName} mismatch! ${messageSuffix}`, + }; + + function ensureOutputDir() { + if (!fs.existsSync(outputPath)) { + fs.mkdirSync(outputPath); + } + } +}; |