UNPKG

@salesforce/apex-node

Version:

Salesforce JS library for Apex

204 lines 8.29 kB
"use strict"; 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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __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.CoverageReporter = exports.DefaultReportOptions = exports.DefaultWatermarks = void 0; const libReport = __importStar(require("istanbul-lib-report")); const reports = __importStar(require("istanbul-reports")); const libCoverage = __importStar(require("istanbul-lib-coverage")); const path = __importStar(require("path")); const fast_glob_1 = __importDefault(require("fast-glob")); const fs = __importStar(require("fs")); const i18n_1 = require("../i18n"); const utils_1 = require("../utils"); const os = __importStar(require("node:os")); const startOfSource = (source) => { if (source) { return source.search(/\S/) || 0; } return 0; }; const endOfSource = (source) => { if (source) { return source.search(/\S$/) || 0; } return 0; }; exports.DefaultWatermarks = { statements: [50, 75], functions: [50, 75], branches: [50, 75], lines: [50, 75] }; exports.DefaultReportOptions = { clover: { file: 'clover.xml', projectRoot: '.' }, cobertura: { file: 'cobertura.xml', projectRoot: '.' }, 'html-spa': { verbose: false, skipEmpty: false, subdir: 'html-spa', linkMapper: undefined, metricsToShow: ['lines', 'statements', 'branches'] }, html: { verbose: false, skipEmpty: false, subdir: 'html', linkMapper: undefined }, json: { file: 'coverage.json' }, 'json-summary': { file: 'coverage-summary.json' }, lcovonly: { file: 'lcovonly.info', projectRoot: '.' }, none: {}, teamcity: { file: 'teamcity.txt', blockName: 'coverage' }, text: { file: 'text.txt', maxCols: 160, skipEmpty: false, skipFull: false }, 'text-summary': { file: 'text-summary.txt' } }; /** * Utility class to produce various well-known code coverage reports from Apex test coverage results. */ class CoverageReporter { coverage; reportDir; sourceDir; options; coverageMap; /** * * @param coverage - instance of either a ApexCodeCoverageAggregate or ApexCodeCoverage object * @param reportDir - Directory to where the requested coverage reports will be written * @param sourceDir - Source directory for those Apex classes or triggers included in coverage data * @param options - CoverageReporterOptions */ constructor(coverage, reportDir, sourceDir, options) { this.coverage = coverage; this.reportDir = reportDir; this.sourceDir = sourceDir; this.options = options; } generateReports() { try { this.coverageMap = this.buildCoverageMap(); fs.statSync(this.reportDir); const context = libReport.createContext({ dir: this.reportDir, defaultSummarizer: 'nested', watermarks: this.options?.watermark || exports.DefaultWatermarks, coverageMap: this.coverageMap }); const formats = this.options?.reportFormats || ['text-summary']; formats.forEach((format) => { const report = reports.create(format, this.options?.reportOptions[format] || exports.DefaultReportOptions[format]); report.execute(context); }); } catch (e) { throw new Error(i18n_1.nls.localize('coverageReportCreationError', e.message)); } } buildCoverageMap() { const pathsToFiles = this.findFullPathToClass(['cls', 'trigger']); const coverageMap = libCoverage.createCoverageMap(); this.coverage.records.forEach((record) => { const fileCoverageData = {}; const fileRegEx = new RegExp(`${record.ApexClassOrTrigger.Name}\.(cls|trigger)`); fileCoverageData.fnMap = {}; fileCoverageData.branchMap = {}; fileCoverageData.path = path.join(this.sourceDir, pathsToFiles.find((file) => fileRegEx.test(file)) || record.ApexClassOrTrigger.Name); fileCoverageData.f = {}; fileCoverageData.b = {}; fileCoverageData.s = [ ...record.Coverage.coveredLines.map((line) => [line, 1]), ...record.Coverage.uncoveredLines.map((line) => [line, 0]) ] .map(([line, covered]) => [Number(line).toString(10), covered]) .reduce((acc, [line, value]) => Object.assign(acc, { [line]: value }), {}); let sourceLines = []; try { sourceLines = fs .readFileSync(fileCoverageData.path, 'utf8') .split(os.EOL); } catch { // file not found } fileCoverageData.statementMap = [ ...record.Coverage.coveredLines, ...record.Coverage.uncoveredLines ] .sort() .map((line) => { const statement = { start: { line, column: startOfSource(sourceLines[line - 1]) }, end: { line, column: endOfSource(sourceLines[line - 1]) } }; return [Number(line).toString(10), statement]; }) .reduce((acc, [line, value]) => Object.assign(acc, { [Number(line).toString()]: value }), {}); coverageMap.addFileCoverage(fileCoverageData); }); return coverageMap; } findFullPathToClass(listOfExtensions) { const searchPattern = `**/*.{${listOfExtensions.join(',')}}`; return fast_glob_1.default.sync(searchPattern, { cwd: this.sourceDir }); } } exports.CoverageReporter = CoverageReporter; __decorate([ (0, utils_1.elapsedTime)() ], CoverageReporter.prototype, "generateReports", null); __decorate([ (0, utils_1.elapsedTime)() ], CoverageReporter.prototype, "buildCoverageMap", null); __decorate([ (0, utils_1.elapsedTime)() ], CoverageReporter.prototype, "findFullPathToClass", null); //# sourceMappingURL=coverageReporter.js.map