UNPKG

@plugjs/cov8

Version:

V8 Coverage Plugin for the PlugJS Build System ==============================================

149 lines (147 loc) 6.48 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // coverage.ts var coverage_exports = {}; __export(coverage_exports, { Coverage: () => Coverage }); module.exports = __toCommonJS(coverage_exports); var import_node_path = require("node:path"); var import_cov8_html = require("@plugjs/cov8-html"); var import_asserts = require("@plugjs/plug/asserts"); var import_files = require("@plugjs/plug/files"); var import_logging = require("@plugjs/plug/logging"); var import_paths = require("@plugjs/plug/paths"); var import_utils = require("@plugjs/plug/utils"); var import_analysis = require("./analysis.cjs"); var import_report = require("./report.cjs"); var Coverage = class { constructor(_coverageDir, _options = {}) { this._coverageDir = _coverageDir; this._options = _options; } async pipe(files, context) { const coverageDir = context.resolve(this._coverageDir); const coverageFiles = []; for await (const file of (0, import_utils.walk)(coverageDir, ["coverage-*.json"])) { coverageFiles.push((0, import_paths.resolveAbsolutePath)(coverageDir, file)); } (0, import_asserts.assert)(coverageFiles.length > 0, `No coverage files found in ${(0, import_logging.$p)(coverageDir)}`); const sourceFiles = [...files.absolutePaths()]; const ms1 = Date.now(); const analyser = await (0, import_analysis.createAnalyser)( sourceFiles, coverageFiles, this._options.sourceMapBias || "least_upper_bound", context.log ); context.log.info("Parsed", coverageFiles.length, "coverage files", (0, import_logging.$ms)(Date.now() - ms1)); const ms2 = Date.now(); const report = await (0, import_report.coverageReport)(analyser, sourceFiles, context.log); context.log.info("Analysed", sourceFiles.length, "source files", (0, import_logging.$ms)(Date.now() - ms2)); analyser.destroy(); const { minimumCoverage = 50, minimumFileCoverage = minimumCoverage, optimalCoverage = Math.round((100 + minimumCoverage) / 2), optimalFileCoverage = Math.round((100 + minimumFileCoverage) / 2) } = this._options; let max = 0; for (const file in report) { if (file.length > max) max = file.length; } let maxLength = 0; for (const file in report.results) { if (file.length > maxLength) maxLength = file.length; } let fileErrors = 0; let fileWarnings = 0; const _report = context.log.report("Coverage report"); for (const [_file, result] of Object.entries(report.results)) { const { coverage } = result.nodeCoverage; const file = _file; if (coverage == null) { _report.annotate(import_logging.NOTICE, file, "n/a"); } else if (coverage < minimumFileCoverage) { _report.annotate(import_logging.ERROR, file, `${coverage} %`); fileErrors++; } else if (coverage < optimalFileCoverage) { _report.annotate(import_logging.WARN, file, `${coverage} %`); fileWarnings++; } else { _report.annotate(import_logging.NOTICE, file, `${coverage} %`); } } if (report.nodes.coverage == null) { const message = "No coverage data collected"; _report.add({ level: import_logging.WARN, message }); } else if (report.nodes.coverage < minimumCoverage) { const message = `${(0, import_logging.$red)(`${report.nodes.coverage}%`)} does not meet minimum coverage ${(0, import_logging.$gry)(`(${minimumCoverage}%)`)}`; _report.add({ level: import_logging.ERROR, message }); } else if (report.nodes.coverage < optimalCoverage) { const message = `${(0, import_logging.$ylw)(`${report.nodes.coverage}%`)} does not meet optimal coverage ${(0, import_logging.$gry)(`(${optimalCoverage}%)`)}`; _report.add({ level: import_logging.WARN, message }); } if (fileErrors) { const f = (0, import_logging.$plur)(fileErrors, "file does", "files do"); const message = `${f} not meet minimum file coverage ${(0, import_logging.$gry)(`(${minimumFileCoverage}%)`)}`; _report.add({ level: import_logging.ERROR, message }); } if (fileWarnings) { const f = (0, import_logging.$plur)(fileWarnings, "file does", "files do"); const message = `${f} not meet optimal file coverage ${(0, import_logging.$gry)(`(${optimalFileCoverage}%)`)}`; _report.add({ level: import_logging.WARN, message }); } if (this._options.reportDir == null) return _report.done(false); const reportDir = context.resolve(this._options.reportDir); const builder = import_files.Files.builder(reportDir); const date = (/* @__PURE__ */ new Date()).toISOString(); const thresholds = { minimumCoverage, minimumFileCoverage, optimalCoverage, optimalFileCoverage }; await builder.write("report.json", JSON.stringify({ ...report, thresholds, date })); await builder.write("index.html", import_cov8_html.html); const results = {}; for (const [rel, abs] of files.pathMappings()) { results[rel] = report.results[abs]; } const tree = {}; for (const relative of Object.keys(results)) { const directories = relative.split(import_node_path.sep); const file = directories.pop(); let node = tree; for (const dir of directories) { node = node[dir] = node[dir] || {}; } node[file] = relative; } const jsonp = JSON.stringify({ ...report, results, thresholds, tree, date }); await builder.write("report.js", `${import_cov8_html.initFunction}(${jsonp});`); _report.done(false); return builder.build(); } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Coverage }); //# sourceMappingURL=coverage.cjs.map