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
JavaScript
;
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