@o3r/testing
Version:
The module provides testing (e2e, unit test) utilities to help you build your own E2E pipeline integrating visual testing.
170 lines • 9.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.visualTestMessages = exports.toggleVisualTestingRender = exports.prepareVisualTesting = void 0;
exports.toBeVisuallySimilar = toBeVisuallySimilar;
exports.saveScreenshot = saveScreenshot;
exports.writeScreenshotsDiff = writeScreenshotsDiff;
exports.compareScreenshot = compareScreenshot;
exports.o3rVisualTest = o3rVisualTest;
var fs = require("node:fs");
var path = require("node:path");
var pixelmatch = require("pixelmatch");
var pngjs_1 = require("pngjs");
var utils_1 = require("./utils");
Object.defineProperty(exports, "prepareVisualTesting", { enumerable: true, get: function () { return utils_1.prepareVisualTesting; } });
Object.defineProperty(exports, "toggleVisualTestingRender", { enumerable: true, get: function () { return utils_1.toggleVisualTestingRender; } });
/** Error messages in case of visual testing failure */
exports.visualTestMessages = {
imagesSize: 'Image sizes do not match for:',
diffMessage: 'Diff between images is greater than threshold for:',
baseImgNotFound: 'Base screenshot file not found:',
success: 'Visual test successful',
generateMode: 'Run in generate screenshot mode'
};
/**
* Visual test matcher
* Based on the VisualTestResult object return by compareScreenshots function, this matcher will compute the error messages
*/
function toBeVisuallySimilar() {
return {
compare: function (actual, _expected) {
if (actual.generateMode) {
return {
pass: true,
message: exports.visualTestMessages.generateMode
};
}
if (actual.baseScreenshotNotFound) {
return {
pass: false,
message: "".concat(exports.visualTestMessages.baseImgNotFound, " ").concat(actual.baseScreenshotNotFound.baseScreenshotPath)
};
}
if (actual.imagesSize) {
return {
pass: false,
message: "".concat(exports.visualTestMessages.imagesSize, " ").concat(actual.imagesSize.screenshotName)
};
}
if (actual.diff && actual.diff.actualDiff > actual.diff.threshold) {
return {
pass: false,
message: "".concat(actual.diff.actualDiff, " > ").concat(actual.diff.threshold, " : ").concat(exports.visualTestMessages.diffMessage, " ").concat(actual.diff.screenshotName)
};
}
return {
pass: true,
message: exports.visualTestMessages.success
};
}
};
}
/**
* It will create a file for the passed screenshot object.
* The path of the new file will be calculated using the parameters
* Ex: ./dist-screenshots\OWBooking\windows_chrome_91\fare-page-after-click-on-continue-0.png
* distScreenshotsDir/scenarionName/device/filenameWithoutExtension.png
* @param screenshot The screenshot object captured. Ex: for protractor - browser.takeScreenshot()
* @param scenarioName E2e Scenario class name
* @param device Details of the platform on which the test is run. If there are spaces the helper will do the concatenation. Ex: `Windows 10 chrome 89`
* @param filenameWithoutExtension file name to save the screenshot - .png will be added at the end
* @param distScreenshotsDir Name of the directory to save the screenshots
*/
function saveScreenshot(screenshot, scenarioName, device, filenameWithoutExtension, distScreenshotsDir) {
if (distScreenshotsDir === void 0) { distScreenshotsDir = 'dist-screenshots'; }
var screenshotsDir = path.resolve(distScreenshotsDir, scenarioName, "".concat(device.replace(/ +/g, '_')));
if (!fs.existsSync(screenshotsDir)) {
fs.mkdirSync(screenshotsDir, { recursive: true });
}
var fullFileName = "".concat(filenameWithoutExtension, ".png");
var stream = fs.createWriteStream(path.resolve(screenshotsDir, fullFileName));
stream.write(Buffer.from(screenshot, 'base64'));
stream.end();
}
/**
* Write the 3 images (base/new/diff) on the reports folder
* The path inside the reports forlder will be calculated using the parameters
* @param pathToScenarioReport Path where the scenario report is saved inside reports folder
* @param screenshotsDirName Name of the directory which will contain the 3 images
* @param diff diff image
* @param baseImage the base image
* @param currentImg the actual taken screenshot image
*/
function writeScreenshotsDiff(pathToScenarioReport, screenshotsDirName, diff, baseImage, currentImg) {
var destScreenshotsDiffDir = path.join(pathToScenarioReport, 'screenshots-diff', screenshotsDirName);
if (!fs.existsSync(destScreenshotsDiffDir)) {
fs.mkdirSync(destScreenshotsDiffDir, { recursive: true });
}
var diffPath = path.resolve(destScreenshotsDiffDir, 'diff.png');
var oldPath = path.resolve(destScreenshotsDiffDir, 'old.png');
var newPath = path.resolve(destScreenshotsDiffDir, 'new.png');
fs.writeFileSync(diffPath, pngjs_1.PNG.sync.write(diff));
fs.writeFileSync(oldPath, pngjs_1.PNG.sync.write(baseImage));
fs.writeFileSync(newPath, pngjs_1.PNG.sync.write(currentImg));
}
/**
* Compare images helper function. If the comparison fails the 3 images (base/new/diff) will be written inside the reports folder of the actual scenario
* @param screenshot Actual captured screenshot object
* @param baseImagePath The path to the base screenshot
* @param threshold The diff between base screenshot and the current one should not be bigger than this value.
* @param pathToScenarioReport Path where the scenario report is saved inside reports folder. Used to compute the path to write diff images in case there is a diff at comparison
* @returns An object of visual test result type
*/
function compareScreenshot(screenshot, baseImagePath, threshold, pathToScenarioReport) {
var baseImageExists = fs.existsSync(baseImagePath);
if (baseImageExists) {
var baseImage = pngjs_1.PNG.sync.read(fs.readFileSync(baseImagePath));
var width = baseImage.width, height = baseImage.height;
var diff = new pngjs_1.PNG({ width: width, height: height });
var screenshotBuffer = Buffer.from(screenshot, 'base64');
var currentImg = pngjs_1.PNG.sync.read(screenshotBuffer);
var diffDirName = path.basename(baseImagePath, '.png');
var result = void 0;
try {
result = pixelmatch(baseImage.data, currentImg.data, diff.data, width, height, { threshold: 0.1 });
}
catch (err) {
if (!err.toString().includes('Image sizes do not match.')) {
throw err;
}
writeScreenshotsDiff(pathToScenarioReport, diffDirName, diff, baseImage, currentImg);
return { imagesSize: { screenshotName: diffDirName } };
}
var pr = Math.round(100 * 100 * result / (width * height)) / 100;
if (pr > threshold) {
writeScreenshotsDiff(pathToScenarioReport, diffDirName, diff, baseImage, currentImg);
}
return { diff: { actualDiff: pr, threshold: threshold, screenshotName: diffDirName } };
}
else {
return { baseScreenshotNotFound: { baseScreenshotPath: baseImagePath } };
}
}
/**
* Helper function to perform a visual test operation
* @param screenshotObj Ex: for protractor browser.takeScreenshot()
* @param filenameWithoutExtension file name to save the screenshot - .png will be added at the end
* @param device os followed by browser version - ex: `Windows 10 chrome 89`
* @param scenarioName E2e Scenario class name
* @param pathToScenarioReport Path used in compare mode for saving the base,new,diff images in reports in case there is a diff
* @param threshold The diff between base screenshot and the current one should not be bigger than this value.
* If the diff is bigger, 3 png files will be created: base screenshot, new screenshot and diff image
* @param generateMode If true it will generate the screenshot file without screenshots comparison
* @param baseScreenshotsDirPath The folder path to search base screenshots; used only in compare mode
*/
function o3rVisualTest(screenshotObj, filenameWithoutExtension, device, scenarioName, pathToScenarioReport, threshold, generateMode, baseScreenshotsDirPath) {
if (pathToScenarioReport === void 0) { pathToScenarioReport = 'reports'; }
if (threshold === void 0) { threshold = 0; }
if (generateMode === void 0) { generateMode = false; }
if (baseScreenshotsDirPath === void 0) { baseScreenshotsDirPath = 'dist-screenshots-base'; }
if (generateMode) {
saveScreenshot(screenshotObj, scenarioName, device, filenameWithoutExtension);
return { generateMode: true };
}
else {
var baseImagePath = path.resolve(baseScreenshotsDirPath, scenarioName, device, "".concat(filenameWithoutExtension, ".png"));
var visualTestResult = compareScreenshot(screenshotObj, baseImagePath, threshold, pathToScenarioReport);
return visualTestResult;
}
}
//# sourceMappingURL=visual-test.js.map