@salesforce/apex-node
Version:
Salesforce JS library for Apex
204 lines • 8.29 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 __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