diff --git a/server/src/api.js b/server/src/api.js
index 6d2f179..db66c31 100644
--- a/server/src/api.js
+++ b/server/src/api.js
@@ -1,6 +1,11 @@
import fastify from "fastify";
import { compare } from "./compare.js";
import { render } from "./render.js";
+import pino from "pino";
+
+const logger = pino({
+ level: process.env.LOG_LEVEL || "info",
+});
export function buildFastify(renderFn, compareFn) {
const server = fastify({
@@ -25,6 +30,7 @@ export function buildFastify(renderFn, compareFn) {
actualHtml: { type: "string" },
fullpage: { type: "boolean" },
viewport: { $ref: "#viewport" },
+ style: { type: "string" },
},
required: ["actualHtml", "expected", "viewport"],
});
@@ -36,6 +42,7 @@ export function buildFastify(renderFn, compareFn) {
actualHtml: { type: "string" },
fullpage: { type: "boolean" },
viewport: { $ref: "#viewport" },
+ style: { type: "string" },
},
required: ["actualHtml", "viewport"],
});
@@ -51,8 +58,9 @@ export function buildFastify(renderFn, compareFn) {
const actualHtml = request.body.actualHtml;
const viewport = request.body.viewport;
const fullpage = request.body.fullpage ?? false;
+ const style = request.body.style;
- const actual = await renderFn(actualHtml, viewport, fullpage);
+ const actual = await renderFn(actualHtml, viewport, fullpage, style);
const result = await compareFn(expected, actual);
return {
@@ -74,8 +82,9 @@ export function buildFastify(renderFn, compareFn) {
const actualHtml = request.body.actualHtml;
const viewport = request.body.viewport;
const fullpage = request.body.fullpage ?? false;
+ const style = request.body.style;
- const actual = await renderFn(actualHtml, viewport, fullpage);
+ const actual = await renderFn(actualHtml, viewport, fullpage, style);
return {
actual: actual.toString("base64"),
@@ -83,6 +92,16 @@ export function buildFastify(renderFn, compareFn) {
},
});
+ server.setErrorHandler((error, request, reply) => {
+ logger.error(error.message);
+ const errorResponse = {
+ message: error.message,
+ error: error.error,
+ statusCode: error.statusCode || 500,
+ };
+ reply.code(errorResponse.statusCode).send(errorResponse);
+ });
+
return server;
}
diff --git a/server/src/api.test.js b/server/src/api.test.js
index 99bd56d..4f048ba 100644
--- a/server/src/api.test.js
+++ b/server/src/api.test.js
@@ -58,6 +58,7 @@ describe("api", () => {
actualHtml: "
Hello World
",
expected: expected,
viewport: { width: 1920, height: 1024 },
+ style: "svg { visibility: hidden; }",
},
});
@@ -100,6 +101,7 @@ describe("api", () => {
payload: {
actualHtml: "Hello World
",
viewport: { width: 1920, height: 1024 },
+ style: "svg { visibility: hidden; }",
},
});
diff --git a/server/src/compare.js b/server/src/compare.js
index 9555215..e816483 100644
--- a/server/src/compare.js
+++ b/server/src/compare.js
@@ -2,15 +2,21 @@ import pixelmatch from "pixelmatch";
import { PNG } from "pngjs";
export async function compare(expected, actual, options = { threshold: 0.01 }) {
- const { width, height, data: expectedPng } = PNG.sync.read(expected);
- const { data: actualPng } = PNG.sync.read(actual);
- const diffPng = new PNG({ width, height });
+ const expectedPng = PNG.sync.read(expected);
+ const actualPng = PNG.sync.read(actual);
+ const diffDimensions = {
+ width: Math.max(expectedPng.width, actualPng.width),
+ height: Math.max(expectedPng.height, actualPng.height),
+ };
+ const resizedExpectedPng = createResized(expectedPng, diffDimensions);
+ const resizedActualPng = createResized(actualPng, diffDimensions);
+ const diffPng = new PNG(diffDimensions);
const numDiffPixels = pixelmatch(
- expectedPng,
- actualPng,
+ resizedExpectedPng.data,
+ resizedActualPng.data,
diffPng.data,
- width,
- height,
+ diffDimensions.width,
+ diffDimensions.height,
options,
);
const diff = PNG.sync.write(diffPng);
@@ -22,3 +28,20 @@ export async function compare(expected, actual, options = { threshold: 0.01 }) {
diff,
};
}
+
+/** Cretes a copy of {@link img}, with the {@link dimensions}.
+ * @param {PNG} img
+ * @param {{width: number, height: number}} dimensions
+ * @returns {PNG}
+ */
+function createResized(img, dimensions) {
+ if (img.width > dimensions.width || img.height > dimensions.height) {
+ throw new Error(
+ `New dimensions expected to be greater than or equal to the original dimensions!`,
+ );
+ }
+ const resized = new PNG(dimensions);
+ PNG.bitblt(img, resized, 0, 0, img.width, img.height);
+
+ return resized;
+}
diff --git a/server/src/render.js b/server/src/render.js
index 97e617f..0d5f4a9 100644
--- a/server/src/render.js
+++ b/server/src/render.js
@@ -32,13 +32,13 @@ export class BrowserRenderer {
logger.debug("Rendering browser started");
}
- async screenshot(url, viewport, fullPage) {
+ async screenshot(url, viewport, fullPage, style) {
logger.debug("Creating screenshot", { url });
const page = await this.browser.newPage({ viewport });
logger.debug("Waiting for page to load", { url });
await page.goto(url);
logger.debug(`Page loaded`, { url });
- const screenshot = await page.screenshot({ fullPage });
+ const screenshot = await page.screenshot({ fullPage, style });
logger.debug(`Screenshot taken`);
return screenshot;
}