@feedzai/feedzai-config
Version:
Feedzai's config for repo-analyzer
152 lines (132 loc) • 4.41 kB
JavaScript
var _ = require("lodash");
const logger = require("pino")({
prettyPrint: { colorize: true },
translateTime: true
});
const lcovparse = require("lcov-parse");
const hasYarn = require("has-yarn");
const {
METRIC_GROUPS,
executeCommand
} = require("@feedzai/analyzer-utilities");
const BaseMetric = require("@feedzai/analyzer-utilities/Base.metric");
/**
* CoverageMetric
*
* This class implements the coverage metric
*
* @author Henrique Dias (henrique.dias@feedzai.com)
*
* @extends BaseMetric
*/
class CoverageMetric extends BaseMetric {
/**
* Used to specify details about this metric.
* @returns {object}
*/
info() {
return {
name: "Coverage",
group: METRIC_GROUPS.RANDOM
};
}
schema() {
return {
"statements": {
"type": "float"
},
"branch": {
"type": "float"
}
}
}
/**
* Decides whether the metric can be ran in current repository or not.
* @returns {boolean}
*/
async verify() {
if (_.isObject(this.getPackage().scripts) && _.isString(this.getPackage().scripts.build)
&& this.getPackage().scripts.build.includes("rollup")) {
return false;
}
return _.isString(this.getAllDependencies().jest);
}
/**
* This function is reponsible to calculate the code coverage
* The way it works it's straightforward, at first it parses the lcov.info file generated by jest
* After parsing the file, sums all the metrics for each file and returns the result
* @returns {object}
*/
parseLcov() {
return new Promise((resolve, reject) => {
lcovparse(`${this.getRepoFolder()}/coverage/lcov.info`, function (err, data) {
if (_.isNull(err) && _.isArray(data)) {
// process the data here
let totalBranchs = 0, coveredBranches = 0;
let totalFunctions = 0, coveredFunctions = 0;
for (let i = 0; i < data.length; i++) {
const n = data[i];
totalBranchs += n.branches.found;
coveredBranches += n.branches.hit;
totalFunctions += n.functions.found;
coveredFunctions += n.functions.hit;
}
resolve({
coveredstatements: coveredFunctions,
statements: totalFunctions,
coveredconditionals: coveredBranches,
conditionals: totalBranchs
});
}
reject(err);
});
});
}
/**
* Used to execute the coverage command and parse the results.
* @returns {Object}
*/
async runCoverageAndParseResult() {
let command;
if (hasYarn(this.getRepoFolder())) {
// eslint-disable-next-line quotes
command = 'yarn test --coverage --coverageDirectory="coverage" ';
} else {
// eslint-disable-next-line quotes
command = 'npm run test -- --coverage --coverageDirectory="coverage" ';
}
const result = await executeCommand(this.getRepoFolder(), command);
if (!result) {
// eslint-disable-next-line quotes
logger.error('Error executing npm run test --coverage --coverageDirectory="coverage"');
return null;
}
return this.parseLcov().then((res) => {
if (_.isObject(res)) {
return res;
}
return null;
}).catch(() => {
return null;
});
}
/**
* Returns the calculated metric.
* @returns {Object}
*/
async execute() {
return await this.runCoverageAndParseResult().then((metrics) => {
if (!_.isObject(metrics)) {
return undefined;
}
return {
result:
{
statements: Math.round((metrics.coveredstatements / metrics.statements) * 100),
branch: Math.round((metrics.coveredconditionals / metrics.conditionals) * 100)
}
};
});
}
}
module.exports = CoverageMetric;