Skip to content

Commit b831e94

Browse files
committed
feat: add possibility to change images dirname
Signed-off-by: Jakub Freisler <[email protected]>
1 parent 0704e58 commit b831e94

File tree

5 files changed

+75
-35
lines changed

5 files changed

+75
-35
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ cy.matchImage({
128128
// whether to update images automatically, without making a diff - useful for CI
129129
// default: false
130130
updateImages: true,
131+
// directory path in which screenshot images will be stored
132+
// image visualiser will normalise path separators depending on OS it's being run within, so always use / for nested paths
133+
// default: '__image_snapshots__'
134+
imagesDir: 'this-might-be-your-custom/maybe-nested-directory',
131135
// maximum threshold above which the test should fail
132136
// default: 0.01
133137
maxDiffThreshold: 0.1

src/commands.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ declare global {
88
screenshotConfig?: Partial<Cypress.ScreenshotDefaultsOptions>;
99
diffConfig?: Parameters<typeof pixelmatch>[5];
1010
updateImages?: boolean;
11+
imagesDir?: string;
1112
maxDiffThreshold?: number;
1213
};
1314

@@ -42,6 +43,11 @@ Cypress.Commands.add(
4243
| boolean
4344
| undefined) ||
4445
false;
46+
const imagesDir =
47+
options.imagesDir ||
48+
(Cypress.env("pluginVisualRegressionImagesDir") as string | undefined) ||
49+
"__image_snapshots__";
50+
4551
const maxDiffThreshold =
4652
options.maxDiffThreshold ||
4753
(Cypress.env("pluginVisualRegressionMaxDiffThreshold") as
@@ -67,6 +73,7 @@ Cypress.Commands.add(
6773
TASK.getScreenshotPath,
6874
{
6975
title,
76+
imagesDir,
7077
specPath: Cypress.spec.relative,
7178
},
7279
{ log: false }

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ export const TASK = {
1212
getScreenshotPath: `${PLUGIN_NAME}-getScreenshotPath`,
1313
compareImages: `${PLUGIN_NAME}-compareImages`,
1414
approveImage: `${PLUGIN_NAME}-approveImage`,
15+
doesFileExist: `${PLUGIN_NAME}-doesFileExist`,
1516
};

src/plugins.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,25 @@ export const initPlugin = (
6464
config: Cypress.PluginConfigOptions
6565
) => {
6666
on("task", {
67-
[TASK.getScreenshotPath]({ title, specPath }) {
67+
[TASK.getScreenshotPath]({ title, imagesDir, specPath }) {
6868
return path.join(
6969
IMAGE_SNAPSHOT_PREFIX,
7070
path.dirname(specPath),
71-
"__image_snapshots__",
71+
...imagesDir.split("/"),
7272
`${title}${FILE_SUFFIX.actual}.png`
7373
);
7474
},
75+
[TASK.doesFileExist]({ path }) {
76+
return fs.existsSync(path);
77+
},
7578
[TASK.approveImage]({ img }) {
7679
const oldImg = img.replace(FILE_SUFFIX.actual, "");
7780
if (fs.existsSync(oldImg)) fs.unlinkSync(oldImg);
7881

7982
const diffImg = img.replace(FILE_SUFFIX.actual, FILE_SUFFIX.diff);
8083
if (fs.existsSync(diffImg)) fs.unlinkSync(diffImg);
8184

82-
moveFile.sync(img, oldImg);
85+
if (fs.existsSync(img)) moveFile.sync(img, oldImg);
8386

8487
return null;
8588
},
@@ -163,7 +166,7 @@ export const initPlugin = (
163166
});
164167

165168
on("after:screenshot", (details) => {
166-
if (details.name.indexOf(IMAGE_SNAPSHOT_PREFIX) !== 0) return;
169+
if (details.name?.indexOf(IMAGE_SNAPSHOT_PREFIX) !== 0) return;
167170

168171
return new Promise((resolve, reject) => {
169172
const screenshotsFolder = getConfigVariableOrThrow(

src/support.ts

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@ function generateOverlayTemplate(
1818
title: string,
1919
imgNewBase64: string,
2020
imgOldBase64: string,
21-
imgDiffBase64: string
21+
imgDiffBase64: string,
22+
wasImageNotUpdatedYet: boolean
2223
) {
2324
return `<div class="${OVERLAY_CLASS} runner" style="position:fixed;z-index:10;top:0;bottom:0;left:0;right:0">
2425
<header style="position:static">
2526
<nav style="display:flex;width:100%;align-items:center;justify-content:space-between;padding:10px 15px;">
2627
<h2>${title} - screenshot diff</h2>
2728
<form>
28-
<button type="submit"><i class="fa fa-check"></i> Update screenshot</button>
29+
${
30+
wasImageNotUpdatedYet
31+
? `<button type="submit"><i class="fa fa-check"></i> Update screenshot</button>`
32+
: "Image was already updated, rerun test to see new comparison"
33+
}
2934
<button type="button" data-type="close"><i class="fa fa-times"></i> Close</button>
3035
<form>
3136
</nav>
@@ -99,37 +104,57 @@ after(() => {
99104
imageCache,
100105
imgPath.replace(FILE_SUFFIX.actual, FILE_SUFFIX.diff),
101106
"base64"
102-
).then((imgDiff) => [imgNew, imgOld, imgDiff])
107+
).then((imgDiff) =>
108+
cy
109+
.task(TASK.doesFileExist, { path: imgPath }, { log: false })
110+
.then(
111+
(wasImageNotUpdatedYet) =>
112+
[
113+
imgNew,
114+
imgOld,
115+
imgDiff,
116+
wasImageNotUpdatedYet as boolean,
117+
] as const
118+
)
119+
)
103120
)
104121
)
105-
.then(([imgNewBase64, imgOldBase64, imgDiffBase64]) => {
106-
if (!top) return false;
107-
queueClear();
108-
109-
Cypress.$(
110-
generateOverlayTemplate(
111-
title,
112-
imgNewBase64,
113-
imgOldBase64,
114-
imgDiffBase64
115-
)
116-
).appendTo(top.document.body);
117-
118-
const wrapper = Cypress.$(`.${OVERLAY_CLASS}`, top.document.body);
119-
wrapper.on("click", 'button[data-type="close"]', function () {
120-
wrapper.remove();
121-
});
122-
123-
wrapper.on("submit", "form", function (e) {
124-
e.preventDefault();
125-
126-
cy.task(TASK.approveImage, { img: imgPath }).then(() =>
127-
wrapper.remove()
128-
);
129-
130-
queueRun();
131-
});
132-
});
122+
.then(
123+
([
124+
imgNewBase64,
125+
imgOldBase64,
126+
imgDiffBase64,
127+
wasImageNotUpdatedYet,
128+
]) => {
129+
if (!top) return false;
130+
queueClear();
131+
132+
Cypress.$(
133+
generateOverlayTemplate(
134+
title,
135+
imgNewBase64,
136+
imgOldBase64,
137+
imgDiffBase64,
138+
wasImageNotUpdatedYet
139+
)
140+
).appendTo(top.document.body);
141+
142+
const wrapper = Cypress.$(`.${OVERLAY_CLASS}`, top.document.body);
143+
wrapper.on("click", 'button[data-type="close"]', function () {
144+
wrapper.remove();
145+
});
146+
147+
wrapper.on("submit", "form", function (e) {
148+
e.preventDefault();
149+
150+
cy.task(TASK.approveImage, { img: imgPath }).then(() =>
151+
wrapper.remove()
152+
);
153+
154+
queueRun();
155+
});
156+
}
157+
);
133158

134159
queueRun();
135160

0 commit comments

Comments
 (0)