html-reporter
Version:
Html-reporter and GUI for viewing and managing results of a tests run. Currently supports Testplane and Hermione.
189 lines • 8.66 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergeReports = void 0;
const url = __importStar(require("url"));
const path = __importStar(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const axios_1 = __importDefault(require("axios"));
const _ = __importStar(require("lodash"));
const serverUtils = __importStar(require("../server-utils"));
const common_utils_1 = require("../common-utils");
const dbServerUtils = __importStar(require("../db-utils/server"));
const constants_1 = require("../constants");
const mergeReports = async (toolAdapter, srcPaths, { destPath, headers }) => {
await validateOpts({ srcPaths, destPath, headers });
let headersFromEnv;
const { htmlReporter, reporterConfig } = toolAdapter;
try {
headersFromEnv = JSON.parse(process.env.html_reporter_headers || '{}');
}
catch (e) {
const error = e;
throw new Error(`Couldn't parse headers from "html_reporter_headers" env variable: ${error.message}`);
}
const headersFromCli = headers.reduce((acc, header) => {
const [key, ...values] = header.split('=');
return _.set(acc, key, values.join('='));
}, {});
const parsedHeaders = { ...headersFromCli, ...headersFromEnv };
const resolvedUrls = await tryResolveUrls(srcPaths, parsedHeaders);
const resolvedDbFiles = resolvedUrls.filter(serverUtils.isDbFile);
const { true: remoteDbUrls = [], false: localDbPaths = [] } = _.groupBy(resolvedDbFiles, common_utils_1.isUrl);
const dbPaths = localDbPaths.map((db, ind, arr) => {
const dbName = arr.length > 1 ? genUniqDbName(db, ind + 1) : path.basename(db);
return { src: path.resolve(process.cwd(), db), dest: path.resolve(destPath, dbName) };
});
const allDbPaths = [...remoteDbUrls, ...dbPaths.map(({ dest }) => path.parse(dest).base)];
const copyFilePromises = [];
await fs_extra_1.default.ensureDir(destPath);
if (!_.isEmpty(localDbPaths)) {
const srcReportPaths = _.uniq(localDbPaths.map(db => path.resolve(process.cwd(), path.parse(db).dir)));
copyFilePromises.push(...[
copyDbFiles(dbPaths),
copyArtifacts({ srcPaths: srcReportPaths, destPath, folderName: constants_1.IMAGES_PATH }),
copyArtifacts({ srcPaths: srcReportPaths, destPath, folderName: constants_1.SNAPSHOTS_PATH }),
copyArtifacts({ srcPaths: srcReportPaths, destPath, folderName: constants_1.ERROR_DETAILS_PATH })
]);
}
await Promise.all([
serverUtils.saveStaticFilesToReportDir(htmlReporter, reporterConfig, destPath),
serverUtils.writeDatabaseUrlsFile(destPath, allDbPaths),
...copyFilePromises
]);
await htmlReporter.emitAsync(htmlReporter.events.REPORT_SAVED, { reportPath: destPath });
};
exports.mergeReports = mergeReports;
async function validateOpts({ srcPaths, destPath, headers }) {
if (!srcPaths.length) {
throw new Error('Nothing to merge, no source reports are passed');
}
if (srcPaths.length === 1) {
console.warn(`Only one source report is passed: ${srcPaths[0]}, which is usually not what you want. Now, a copy of source report will just be created.`);
}
if (srcPaths.includes(destPath)) {
throw new Error(`Destination report path: ${destPath}, exists in source report paths`);
}
for (const srcPath of srcPaths) {
if ((0, common_utils_1.isUrl)(srcPath)) {
continue;
}
let srcPathStat;
try {
srcPathStat = await fs_extra_1.default.stat(srcPath);
}
catch (err) {
const error = err;
if (error.code !== 'ENOENT') {
throw err;
}
else {
throw new Error(`Specified source path: ${srcPath} doesn't exists on file system`);
}
}
if (srcPathStat.isDirectory()) {
const dbUrlsJsonPath = path.join(srcPath, constants_1.DATABASE_URLS_JSON_NAME);
const isDbUrlsJsonPathExists = await fs_extra_1.default.pathExists(dbUrlsJsonPath);
if (!isDbUrlsJsonPathExists) {
throw new Error(`${constants_1.DATABASE_URLS_JSON_NAME} doesn't exist in specified source path: ${srcPath}`);
}
}
else {
if (!srcPath.endsWith(constants_1.DATABASE_URLS_JSON_NAME) && !srcPath.endsWith(constants_1.LOCAL_DATABASE_NAME)) {
throw new Error(`Specified source path: ${srcPath} must be a directory or one of the following files: ${constants_1.DATABASE_URLS_JSON_NAME}, ${constants_1.LOCAL_DATABASE_NAME}.`);
}
}
}
for (const header of headers) {
if (!header.includes('=')) {
throw new Error(`Header must has key and value separated by "=" symbol, but got "${header}"`);
}
}
}
async function tryResolveUrls(urls, headers) {
const resolvedUrls = [];
const results = await Promise.all(urls.map(async (u) => {
const extName = path.extname((0, common_utils_1.isUrl)(u) ? url.parse(u).pathname || '' : u);
if (!extName) {
u = (0, common_utils_1.isUrl)(u) ? new URL(constants_1.DATABASE_URLS_JSON_NAME, u).href : path.join(u, constants_1.DATABASE_URLS_JSON_NAME);
}
return tryResolveUrl(u, headers);
}));
results.forEach(({ jsonUrls, dbUrls }) => {
resolvedUrls.push(...jsonUrls.concat(dbUrls));
});
return resolvedUrls;
}
async function tryResolveUrl(url, headers) {
const jsonUrls = [];
const dbUrls = [];
if (serverUtils.isDbFile(url)) {
dbUrls.push(url);
}
else if (serverUtils.isJsonUrl(url)) {
try {
const data = (0, common_utils_1.isUrl)(url)
? (await axios_1.default.get(url, { headers })).data
: await fs_extra_1.default.readJSON(url);
const currentDbUrls = _.get(data, 'dbUrls', []);
const currentJsonUrls = _.get(data, 'jsonUrls', []);
const preparedDbUrls = dbServerUtils.prepareUrls(currentDbUrls, url);
const preparedJsonUrls = dbServerUtils.prepareUrls(currentJsonUrls, url);
const responses = await Promise.all(preparedJsonUrls.map((url) => tryResolveUrl(url, headers)));
dbUrls.push(...preparedDbUrls);
responses.forEach(response => {
dbUrls.push(...response.dbUrls);
jsonUrls.push(...response.jsonUrls);
});
}
catch (e) {
const error = e;
common_utils_1.logger.warn(`Failed to handle ${url}: ${error.message}`);
jsonUrls.push(url);
}
}
return { jsonUrls, dbUrls };
}
function genUniqDbName(dbPath, num) {
return `${path.basename(dbPath, constants_1.DB_FILE_EXTENSION)}_${num}${constants_1.DB_FILE_EXTENSION}`;
}
async function copyDbFiles(dbPaths) {
await Promise.all(dbPaths.map(({ src, dest }) => fs_extra_1.default.copy(src, dest)));
}
async function copyArtifacts({ srcPaths, destPath, folderName }) {
for (const reportPath of srcPaths) {
const src = path.resolve(reportPath, folderName);
const dest = path.resolve(destPath, folderName);
const exists = await fs_extra_1.default.pathExists(src);
if (!exists) {
continue;
}
await fs_extra_1.default.copy(src, dest, { recursive: true, overwrite: false });
}
}
//# sourceMappingURL=index.js.map