Skip to content

Instantly share code, notes, and snippets.

@kevinbuhmann
Last active September 24, 2021 17:56
Show Gist options
  • Save kevinbuhmann/afc5d31017e8556b9d04a7c3b60ba32f to your computer and use it in GitHub Desktop.
Save kevinbuhmann/afc5d31017e8556b9d04a7c3b60ba32f to your computer and use it in GitHub Desktop.
jest-screenshot: report/delete obsolete screenshot files
diff --git a/node_modules/jest-screenshot/dist/jest-screenshot.js b/node_modules/jest-screenshot/dist/jest-screenshot.js
index 4c43c6c..18daa4a 100644
--- a/node_modules/jest-screenshot/dist/jest-screenshot.js
+++ b/node_modules/jest-screenshot/dist/jest-screenshot.js
@@ -2,6 +2,8 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupJestScreenshot = void 0;
const to_match_image_snapshot_1 = require("./to-match-image-snapshot");
+const fs = require("fs");
+const path = require("path");
const config_1 = require("./config");
/**
* This function is used to setup and initialize **jest-screenshot**.
@@ -12,11 +14,28 @@ function setupJestScreenshot(customConfig) {
if (typeof expect === "undefined") {
throw new Error("Jest: Could not find `expect`. Can't setup jest-screenshot.");
}
+
+ writeFile("./tmp/used-jest-screenshots.txt", "");
+
expect.extend({
toMatchImageSnapshot(received, parameters) {
return to_match_image_snapshot_1.toMatchImageSnapshot.call(this, received, config_1.config(customConfig), parameters);
},
});
}
+
+function writeFile(filePath, contents) {
+ ensureDirectoryExists(filePath);
+ fs.writeFileSync(filePath, contents);
+}
+
+function ensureDirectoryExists(filePath) {
+ const dirname = path.dirname(filePath);
+
+ if (!fs.existsSync(dirname) || !fs.statSync(dirname).isDirectory()) {
+ ensureDirectoryExists(dirname);
+ fs.mkdirSync(dirname);
+ }
+}
exports.setupJestScreenshot = setupJestScreenshot;
//# sourceMappingURL=jest-screenshot.js.map
\ No newline at end of file
diff --git a/node_modules/jest-screenshot/dist/reporter.js b/node_modules/jest-screenshot/dist/reporter.js
index 8df69b0..a7ce365 100644
--- a/node_modules/jest-screenshot/dist/reporter.js
+++ b/node_modules/jest-screenshot/dist/reporter.js
@@ -20,9 +20,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
const config_1 = require("./config");
const fs_1 = require("fs");
+const glob = require("glob");
const path = __importStar(require("path"));
const rimraf_1 = require("rimraf");
const filenames_1 = require("./filenames");
+const chalk = require("chalk");
const template = (testResults) => `<html>
<head>
<meta charset="utf-8" />
@@ -47,6 +49,12 @@ module.exports = class JestScreenshotReporter {
}
}
onRunComplete(contexts, { testResults, numFailedTests }) {
+ this.generateReport(contexts, { testResults, numFailedTests });
+
+ checkForObsoleteScreenshotFiles();
+ }
+
+ generateReport(contexts, { testResults, numFailedTests }) {
const { reportDir: reportDirName, noReport } = this.config;
const reportDir = filenames_1.getReportDir(reportDirName);
const reportsDir = path.join(reportDir, "reports");
@@ -107,4 +115,80 @@ module.exports = class JestScreenshotReporter {
].forEach(fileName => fs_1.writeFileSync(path.join(reportDir, "dist", fileName), fs_1.readFileSync(path.join(__dirname, fileName))));
}
};
+
+const ARROW = ' \u203A ';
+const DOWN_ARROW = ' \u21B3 ';
+const DOT = ' \u2022 ';
+
+function checkForObsoleteScreenshotFiles() {
+ const snapshotsFolderName = '__snapshots__';
+
+ const screenshotFilePaths = glob.sync(`./src/**/${snapshotsFolderName}/*.snap.png`)
+ .map(screenshotFilePath => path.resolve(screenshotFilePath));
+
+ const usedScreenshotFilePaths = fs_1.readFileSync("./tmp/used-jest-screenshots.txt").toString().split("\n");
+
+ const obsoleteScreenshotFilePaths = screenshotFilePaths
+ .filter(screenshotFilePath => usedScreenshotFilePaths.includes(screenshotFilePath) == false);
+
+ if (obsoleteScreenshotFilePaths.length) {
+ const jestArgs = process.argv.slice(2);
+ const updateSnapshots = jestArgs.includes("-u") || jestArgs.includes("--update-snapshot");
+
+ const obsoleteSnapshotFolderPaths = obsoleteScreenshotFilePaths
+ .map(obsoleteScreenshotFilePath => obsoleteScreenshotFilePath.substr(0, obsoleteScreenshotFilePath.indexOf(snapshotsFolderName) + snapshotsFolderName.length))
+ .filter((value, index, self) => self.indexOf(value) === index)
+ .sort();
+
+ if (updateSnapshots) {
+ removeObsoleteScreenshots(obsoleteScreenshotFilePaths, obsoleteSnapshotFolderPaths);
+ } else {
+ printObsoleteScreenshotReport(obsoleteScreenshotFilePaths, obsoleteSnapshotFolderPaths);
+
+ process.exit(1);
+ }
+
+ console.log();
+ }
+}
+
+function removeObsoleteScreenshots(obsoleteScreenshotFilePaths, obsoleteSnapshotFolderPaths) {
+ for (const obsoleteScreenshotFilePath of obsoleteScreenshotFilePaths) {
+ fs_1.unlinkSync(obsoleteScreenshotFilePath);
+ }
+
+ console.log(`
+${chalk.bold("Screenshot Summary")}
+${chalk.bold.green(`${ARROW}${quantityText(obsoleteScreenshotFilePaths.length, 'screenshot')} removed`)} from ${quantityText(obsoleteSnapshotFolderPaths.length, "folder")}.`);
+}
+
+function printObsoleteScreenshotReport(obsoleteScreenshotFilePaths, obsoleteSnapshotFolderPaths) {
+ const obsoleteSnapshotFolderPathsOutline = obsoleteSnapshotFolderPaths
+ .map(obsoleteSnapshotFolderPath => {
+ const obsoleteScreenshotFilesInFolderOutline = obsoleteScreenshotFilePaths
+ .filter(obsoleteScreenshotFilePath => obsoleteScreenshotFilePath.startsWith(obsoleteSnapshotFolderPath))
+ .map(obsoleteScreenshotFilePath => `${DOT}${path.basename(obsoleteScreenshotFilePath)}`);
+
+ return `${DOWN_ARROW}${path.relative('.', obsoleteSnapshotFolderPath)}\n${indent(obsoleteScreenshotFilesInFolderOutline, 6)}`;
+ });
+
+ console.log(`
+${chalk.bold("Screenshot Summary")}
+${chalk.bold.yellow(`${ARROW}${quantityText(obsoleteScreenshotFilePaths.length, 'screenshot')} obsolete`)} in ${quantityText(obsoleteSnapshotFolderPaths.length, "folder")}. To remove ${itOrThemAll(obsoleteScreenshotFilePaths.length)}, run \`yarn test -u\`.
+${indent(obsoleteSnapshotFolderPathsOutline, 2)}`);
+}
+
+function indent(lines, level) {
+ const spaces = ' '.repeat(level);
+
+ return `${spaces}${lines.join(`\n${spaces}`)}`;
+}
+
+function quantityText(quantity, noun) {
+ return `${quantity} ${quantity === 1 ? noun : `${noun}s`}`;
+}
+
+function itOrThemAll(quantity) {
+ return quantity === 1 ? "it" : "them all";
+}
//# sourceMappingURL=reporter.js.map
\ No newline at end of file
diff --git a/node_modules/jest-screenshot/dist/to-match-image-snapshot.js b/node_modules/jest-screenshot/dist/to-match-image-snapshot.js
index 943c7f2..393c84a 100644
--- a/node_modules/jest-screenshot/dist/to-match-image-snapshot.js
+++ b/node_modules/jest-screenshot/dist/to-match-image-snapshot.js
@@ -111,6 +111,9 @@ function toMatchImageSnapshot(received, configuration, parameters = {}) {
const snapshotPath = typeof parameters.path === "string" ?
parameters.path :
filenames_1.getSnapshotPath(testPath, currentTestName, snapshotState, snapshotsDir);
+
+ fs_1.appendFileSync("./tmp/used-jest-screenshots.txt", `${snapshotPath}\n`);
+
const reportPath = filenames_1.getReportPath(testPath, currentTestName, snapshotState, reportDir);
// Create the path to store the snapshots in.
mkdirp_1.sync(path.dirname(snapshotPath));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment