UNPKG

html-reporter

Version:

Html-reporter and GUI for viewing and managing results of a tests run. Currently supports Testplane and Hermione.

167 lines 8.69 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ImagesInfoSaver = void 0; const util_1 = __importDefault(require("util")); const debug_1 = __importDefault(require("debug")); const eventemitter2_1 = __importDefault(require("eventemitter2")); const fs_extra_1 = __importDefault(require("fs-extra")); const image_size_1 = __importDefault(require("image-size")); const lodash_1 = __importDefault(require("lodash")); const p_queue_1 = __importDefault(require("p-queue")); const utils_1 = require("./adapters/test-result/utils"); const image_cache_1 = require("./image-cache"); const constants_1 = require("./constants"); const server_utils_1 = require("./server-utils"); const common_utils_1 = require("./common-utils"); const debug = (0, debug_1.default)('html-reporter:images-info-saver'); class ImagesInfoSaver extends eventemitter2_1.default { constructor(options) { super(); this._imageFileSaver = options.imageFileSaver; this._reportPath = options.reportPath; this._imageStore = options.imageStore; this._expectedPathsCache = options.expectedPathsCache; } async save(testResult, workers) { const testDebug = debug.extend(testResult.imageDir); testDebug(`Saving images of ${testResult.id}`); const newImagesInfos = await Promise.all(testResult.imagesInfo.map(async (imagesInfo, index) => { const imageDebug = testDebug.extend(index.toString()); imageDebug.enabled && imageDebug('Handling %j', (0, utils_1.removeBufferFromImagesInfo)(imagesInfo)); const newImagesInfo = lodash_1.default.clone(imagesInfo); const { stateName } = imagesInfo; const actions = new p_queue_1.default(); actions.add(async () => { newImagesInfo.actualImg = await this._saveActualImageIfNeeded(testResult, imagesInfo, stateName, { logger: imageDebug }); }); actions.add(async () => { newImagesInfo.diffImg = await this._saveDiffImageIfNeeded(testResult, imagesInfo, stateName, { workers, logger: imageDebug }); }); actions.add(async () => { newImagesInfo.expectedImg = await this._saveExpectedImageIfNeeded(testResult, imagesInfo, stateName, { logger: imageDebug }); }); await actions.onIdle(); return lodash_1.default.omitBy(newImagesInfo, lodash_1.default.isNil); })); await this.emitAsync(constants_1.PluginEvents.TEST_SCREENSHOTS_SAVED, { testId: (0, common_utils_1.mkTestId)(testResult.fullName, testResult.browserId), attempt: testResult.attempt, imagesInfo: newImagesInfos }); return (0, utils_1.copyAndUpdate)(testResult, { imagesInfo: newImagesInfos }); } setImageFileSaver(imageFileSaver) { this._imageFileSaver = imageFileSaver; } async _createDiffInFile(imagesInfo, filePath, workers) { await (0, server_utils_1.makeDirFor)(filePath); const actualPath = imagesInfo.actualImg.path; const expectedPath = imagesInfo.expectedImg.path; const [currBuffer, refBuffer] = await Promise.all([ fs_extra_1.default.readFile(actualPath), fs_extra_1.default.readFile(expectedPath) ]); const hash = (0, server_utils_1.createHash)(currBuffer) + (0, server_utils_1.createHash)(refBuffer); if (image_cache_1.cacheDiffImages.has(hash)) { const cachedDiffPath = image_cache_1.cacheDiffImages.get(hash); await fs_extra_1.default.copy(cachedDiffPath, filePath); } else { await workers.saveDiffTo({ ...imagesInfo.diffOptions, reference: expectedPath, current: actualPath }, filePath); image_cache_1.cacheDiffImages.set(hash, filePath); } return { path: filePath, size: lodash_1.default.pick((0, image_size_1.default)(filePath), ['height', 'width']) }; } _getReusedExpectedPath(testResult, imagesInfo) { if (imagesInfo.status === constants_1.UPDATED) { return null; } const { stateName } = imagesInfo; if (this._expectedPathsCache.has([testResult, stateName])) { return this._expectedPathsCache.get([testResult, stateName]); } const lastImageInfo = this._imageStore.getLastImageInfoFromDb(testResult, stateName); if (lastImageInfo && lastImageInfo.expectedImg) { this._expectedPathsCache.set([testResult, stateName], lastImageInfo.expectedImg.path); return lastImageInfo.expectedImg.path; } return null; } async _saveImage(imageData, destPath) { const sourceFilePath = (0, common_utils_1.isImageBufferData)(imageData) || (0, common_utils_1.isBase64Image)(imageData) ? (0, server_utils_1.getTempPath)(destPath) : imageData.path; if ((0, common_utils_1.isImageBufferData)(imageData)) { await (0, server_utils_1.makeDirFor)(sourceFilePath); await fs_extra_1.default.writeFile(sourceFilePath, Buffer.from(imageData.buffer)); } else if ((0, common_utils_1.isBase64Image)(imageData)) { await (0, server_utils_1.makeDirFor)(sourceFilePath); await fs_extra_1.default.writeFile(sourceFilePath, Buffer.from(imageData.base64, 'base64'), 'base64'); } const savedFilePath = await this._imageFileSaver.saveImg(sourceFilePath, { destPath, reportDir: this._reportPath }); return savedFilePath || destPath; } async _saveActualImageIfNeeded(testResult, imagesInfo, stateName, { logger }) { const actualImg = imagesInfo.actualImg; if (!actualImg) { return actualImg; } const reportActualPath = (0, server_utils_1.getCurrentPath)(testResult, stateName); const newActualPath = await this._saveImage(actualImg, reportActualPath); logger(`Saved actual image from ${actualImg.path ?? '<buffer>'} to ${newActualPath}`); return { path: newActualPath, size: actualImg.size }; } async _saveDiffImageIfNeeded(testResult, imagesInfo, stateName, { workers, logger }) { const shouldSaveDiff = imagesInfo.status === constants_1.TestStatus.FAIL && (imagesInfo.diffImg || (imagesInfo.actualImg && imagesInfo.expectedImg)); if (!shouldSaveDiff) { return; } let { diffImg } = imagesInfo; const reportDiffPath = (0, server_utils_1.getDiffPath)(testResult, stateName); if (!diffImg) { if (!workers) { throw new Error('Couldn\'t generate diff image, because workers were not passed.\n' + util_1.default.format('Test result: %o\n', testResult) + `Please report this error to html-reporter team: ${constants_1.NEW_ISSUE_LINK}.`); } diffImg = await this._createDiffInFile(imagesInfo, reportDiffPath, workers); logger(`Created new diff in file ${reportDiffPath}`); } const newDiffPath = await this._saveImage(diffImg, reportDiffPath); logger(`Saved diff image from ${diffImg.path ?? '<buffer>'} to ${newDiffPath}`); const size = lodash_1.default.pick((0, image_size_1.default)((0, common_utils_1.isImageBufferData)(diffImg) ? Buffer.from(diffImg.buffer) : diffImg.path), ['height', 'width']); return { path: newDiffPath, size }; } async _saveExpectedImageIfNeeded(testResult, imagesInfo, stateName, { logger }) { if (!imagesInfo.expectedImg) { return; } const { expectedImg } = imagesInfo; const reusedExpectedPath = this._getReusedExpectedPath(testResult, imagesInfo); const reportDiffPath = reusedExpectedPath ?? (0, server_utils_1.getReferencePath)(testResult, stateName); let newExpectedPath = reportDiffPath; if (!reusedExpectedPath) { newExpectedPath = await this._saveImage(expectedImg, reportDiffPath); logger(`Saved expected image from ${expectedImg.path ?? '<buffer>'} to ${newExpectedPath}`); } else { logger(`Reused expected image from ${reusedExpectedPath}`); } return { path: newExpectedPath, size: expectedImg.size }; } } exports.ImagesInfoSaver = ImagesInfoSaver; //# sourceMappingURL=images-info-saver.js.map