Skip to content

Commit

Permalink
feat: add forceDeviceFactor option
Browse files Browse the repository at this point in the history
when forceDeviceFactor=true scale images to match 1x device scale factor
set additional chrome flags to make sure of proper device scale factor

Signed-off-by: Jakub Freisler <jakub@frsource.org>
  • Loading branch information
FRSgit committed Feb 24, 2022
1 parent 8bb9bb0 commit 8d69632
Show file tree
Hide file tree
Showing 5 changed files with 388 additions and 18 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ cy.matchImage({
imagesDir: 'this-might-be-your-custom/maybe-nested-directory',
// maximum threshold above which the test should fail
// default: 0.01
maxDiffThreshold: 0.1
maxDiffThreshold: 0.1,
// forces scale factor to be set as value "1"
// helps with screenshots being scaled 2x on high-density screens like Mac Retina
// default: true
forceDeviceScaleFactor: false,
})
```

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@semantic-release/release-notes-generator": "^10.0.2",
"@types/pixelmatch": "^5.2.4",
"@types/pngjs": "^6.0.1",
"@types/sharp": "^0.29.5",
"@typescript-eslint/eslint-plugin": "^5.1.0",
"@typescript-eslint/parser": "^5.1.0",
"cypress": "^8.6.0",
Expand Down Expand Up @@ -63,7 +64,8 @@
"dependencies": {
"move-file": "^2.1.0",
"pixelmatch": "^5.2.1",
"pngjs": "^6.0.0"
"pngjs": "^6.0.0",
"sharp": "^0.30.1"
},
"publishConfig": {
"access": "public"
Expand Down
6 changes: 6 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ Cypress.Commands.add(
nameCacheCounter[title] = -1;
title += ` #${++nameCacheCounter[title]}`;

const scaleFactor =
Cypress.env("pluginVisualRegressionForceDeviceScaleFactor") === false
? 1
: 1 / window.devicePixelRatio;

const updateImages =
options.updateImages ||
(Cypress.env("pluginVisualRegressionUpdateImages") as
Expand Down Expand Up @@ -97,6 +102,7 @@ Cypress.Commands.add(
.task(
TASK.compareImages,
{
scaleFactor,
imgNew: imgPath,
imgOld: imgPath.replace(FILE_SUFFIX.actual, ""),
updateImages,
Expand Down
46 changes: 42 additions & 4 deletions src/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import path from "path";
import pixelmatch from "pixelmatch";
import fs from "fs";
import { PNG } from "pngjs";
import { PNG, PNGWithMetadata } from "pngjs";
import { FILE_SUFFIX, IMAGE_SNAPSHOT_PREFIX, TASK } from "./constants";
import moveFile from "move-file";
import sharp from "sharp";

type NotFalsy<T> = T extends false | null | undefined ? never : T;

Expand All @@ -29,7 +30,25 @@ const fillSizeDifference = (width: number, height: number) => (image: PNG) => {
return image;
};

const alignImagesToSameSize = (firstImage: PNG, secondImage: PNG) => {
const importAndScaleImage = async (cfg: {
scaleFactor: number;
path: string;
}) => {
const imgBuffer = fs.readFileSync(cfg.path);
const rawImgNew = PNG.sync.read(imgBuffer);
if (cfg.scaleFactor === 1) return rawImgNew;

const newImageWidth = Math.ceil(rawImgNew.width * cfg.scaleFactor);
const newImageHeight = Math.ceil(rawImgNew.height * cfg.scaleFactor);
await sharp(imgBuffer).resize(newImageWidth, newImageHeight).toFile(cfg.path);

return PNG.sync.read(fs.readFileSync(cfg.path));
};

const alignImagesToSameSize = (
firstImage: PNGWithMetadata,
secondImage: PNGWithMetadata
) => {
const firstImageWidth = firstImage.width;
const firstImageHeight = firstImage.height;
const secondImageWidth = secondImage.width;
Expand Down Expand Up @@ -63,6 +82,21 @@ export const initPlugin = (
on: Cypress.PluginEvents,
config: Cypress.PluginConfigOptions
) => {
if (config.env["pluginVisualRegressionForceDeviceScaleFactor"] !== false) {
// based on https://github.com/cypress-io/cypress/issues/2102#issuecomment-521299946
on("before:browser:launch", (browser, launchOptions) => {
if (browser.name === "chrome" || browser.name === "chromium") {
launchOptions.args.push("--force-device-scale-factor=1");
launchOptions.args.push("--high-dpi-support=1");
} else if (browser.name === "electron" && browser.isHeaded) {
// eslint-disable-next-line no-console
console.log(
"There isn't currently a way of setting the device scale factor in Cypress when running headed electron so we disable the image regression commands."
);
}
});
}

on("task", {
[TASK.getScreenshotPath]({ title, imagesDir, specPath }) {
return path.join(
Expand All @@ -86,8 +120,9 @@ export const initPlugin = (

return null;
},
[TASK.compareImages](
async [TASK.compareImages](
cfg: {
scaleFactor: number;
title: string;
imgNew: string;
imgOld: string;
Expand All @@ -100,7 +135,10 @@ export const initPlugin = (
let errorMsg: string | undefined;

if (fs.existsSync(cfg.imgOld) && !cfg.updateImages) {
const rawImgNew = PNG.sync.read(fs.readFileSync(cfg.imgNew));
const rawImgNew = await importAndScaleImage({
scaleFactor: cfg.scaleFactor,
path: cfg.imgNew,
});
const rawImgOld = PNG.sync.read(fs.readFileSync(cfg.imgOld));
const isImgSizeDifferent =
rawImgNew.height !== rawImgOld.height ||
Expand Down
Loading

0 comments on commit 8d69632

Please sign in to comment.