mirror of
https://github.com/dorny/test-reporter.git
synced 2025-12-17 06:47:09 +01:00
Merge 2c5485e682 into 5edc9e96e2
This commit is contained in:
commit
60a394a30d
13 changed files with 593 additions and 0 deletions
21
__tests__/__outputs__/lcov-report-results.md
Normal file
21
__tests__/__outputs__/lcov-report-results.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|

|
||||||
|
## ❌ <a id="user-content-r0" href="#r0">fixtures/lcov.info</a>
|
||||||
|
**6** tests were completed in **0ms** with **4** passed, **2** failed and **0** skipped.
|
||||||
|
|Test suite|Passed|Failed|Skipped|Time|
|
||||||
|
|:---|---:|---:|---:|---:|
|
||||||
|
|[src/services/notifier/NotifierService.js](#r0s0)|2✅|1❌||0ms|
|
||||||
|
|[src/services/notifier/providers/DiscordNotifierProvider.js](#r0s1)|2✅|1❌||0ms|
|
||||||
|
### ❌ <a id="user-content-r0s0" href="#r0s0">src/services/notifier/NotifierService.js</a>
|
||||||
|
```
|
||||||
|
src/services/notifier/NotifierService.js
|
||||||
|
✅ lines 100% (21/21)
|
||||||
|
✅ functions 100% (10/10)
|
||||||
|
❌ branches 50% (3/6)
|
||||||
|
```
|
||||||
|
### ❌ <a id="user-content-r0s1" href="#r0s1">src/services/notifier/providers/DiscordNotifierProvider.js</a>
|
||||||
|
```
|
||||||
|
src/services/notifier/providers/DiscordNotifierProvider.js
|
||||||
|
✅ lines 100% (17/17)
|
||||||
|
✅ functions 100% (3/3)
|
||||||
|
❌ branches 75% (3/4)
|
||||||
|
```
|
||||||
62
__tests__/__snapshots__/lcov.test.ts.snap
Normal file
62
__tests__/__snapshots__/lcov.test.ts.snap
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`lcov report coverage report from facebook/jest test results matches snapshot 1`] = `
|
||||||
|
TestRunResult {
|
||||||
|
"path": "fixtures/lcov.info",
|
||||||
|
"suites": [
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "src/services/notifier/NotifierService.js",
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"name": "lines 100% (21/21)",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "functions 100% (10/10)",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "branches 50% (3/6)",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "src/services/notifier/NotifierService.js",
|
||||||
|
"totalTime": undefined,
|
||||||
|
},
|
||||||
|
TestSuiteResult {
|
||||||
|
"groups": [
|
||||||
|
TestGroupResult {
|
||||||
|
"name": "src/services/notifier/providers/DiscordNotifierProvider.js",
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"name": "lines 100% (17/17)",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "functions 100% (3/3)",
|
||||||
|
"result": "success",
|
||||||
|
"time": 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "branches 75% (3/4)",
|
||||||
|
"result": "failed",
|
||||||
|
"time": 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "src/services/notifier/providers/DiscordNotifierProvider.js",
|
||||||
|
"totalTime": undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"totalTime": undefined,
|
||||||
|
}
|
||||||
|
`;
|
||||||
92
__tests__/fixtures/lcov.info
Normal file
92
__tests__/fixtures/lcov.info
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
TN:
|
||||||
|
SF:src/services/notifier/NotifierService.js
|
||||||
|
FN:9,(anonymous_0)
|
||||||
|
FN:10,(anonymous_1)
|
||||||
|
FN:26,(anonymous_2)
|
||||||
|
FN:27,(anonymous_3)
|
||||||
|
FN:29,(anonymous_4)
|
||||||
|
FN:30,(anonymous_5)
|
||||||
|
FN:46,(anonymous_6)
|
||||||
|
FN:47,(anonymous_7)
|
||||||
|
FN:48,(anonymous_8)
|
||||||
|
FN:49,(anonymous_9)
|
||||||
|
FNF:10
|
||||||
|
FNH:10
|
||||||
|
FNDA:1,(anonymous_0)
|
||||||
|
FNDA:1,(anonymous_1)
|
||||||
|
FNDA:1,(anonymous_2)
|
||||||
|
FNDA:3,(anonymous_3)
|
||||||
|
FNDA:3,(anonymous_4)
|
||||||
|
FNDA:3,(anonymous_5)
|
||||||
|
FNDA:1,(anonymous_6)
|
||||||
|
FNDA:3,(anonymous_7)
|
||||||
|
FNDA:3,(anonymous_8)
|
||||||
|
FNDA:3,(anonymous_9)
|
||||||
|
DA:9,1
|
||||||
|
DA:10,1
|
||||||
|
DA:11,1
|
||||||
|
DA:13,1
|
||||||
|
DA:14,1
|
||||||
|
DA:26,1
|
||||||
|
DA:27,3
|
||||||
|
DA:29,1
|
||||||
|
DA:30,3
|
||||||
|
DA:31,3
|
||||||
|
DA:33,3
|
||||||
|
DA:34,3
|
||||||
|
DA:46,1
|
||||||
|
DA:47,3
|
||||||
|
DA:48,3
|
||||||
|
DA:51,3
|
||||||
|
DA:53,3
|
||||||
|
DA:54,3
|
||||||
|
DA:58,3
|
||||||
|
DA:61,1
|
||||||
|
DA:64,1
|
||||||
|
LF:21
|
||||||
|
LH:21
|
||||||
|
BRDA:11,0,0,1
|
||||||
|
BRDA:11,0,1,0
|
||||||
|
BRDA:31,1,0,3
|
||||||
|
BRDA:31,1,1,0
|
||||||
|
BRDA:51,2,0,3
|
||||||
|
BRDA:51,2,1,0
|
||||||
|
BRF:6
|
||||||
|
BRH:3
|
||||||
|
end_of_record
|
||||||
|
TN:
|
||||||
|
SF:src/services/notifier/providers/DiscordNotifierProvider.js
|
||||||
|
FN:12,(anonymous_0)
|
||||||
|
FN:33,(anonymous_1)
|
||||||
|
FN:51,(anonymous_2)
|
||||||
|
FNF:3
|
||||||
|
FNH:3
|
||||||
|
FNDA:1,(anonymous_0)
|
||||||
|
FNDA:1,(anonymous_1)
|
||||||
|
FNDA:1,(anonymous_2)
|
||||||
|
DA:3,1
|
||||||
|
DA:12,1
|
||||||
|
DA:13,1
|
||||||
|
DA:14,1
|
||||||
|
DA:22,1
|
||||||
|
DA:23,1
|
||||||
|
DA:33,1
|
||||||
|
DA:34,1
|
||||||
|
DA:35,1
|
||||||
|
DA:40,1
|
||||||
|
DA:41,1
|
||||||
|
DA:51,1
|
||||||
|
DA:52,1
|
||||||
|
DA:53,1
|
||||||
|
DA:58,1
|
||||||
|
DA:59,1
|
||||||
|
DA:62,1
|
||||||
|
LF:17
|
||||||
|
LH:17
|
||||||
|
BRDA:18,0,0,0
|
||||||
|
BRDA:18,0,1,1
|
||||||
|
BRDA:20,1,0,1
|
||||||
|
BRDA:20,1,1,1
|
||||||
|
BRF:4
|
||||||
|
BRH:3
|
||||||
|
end_of_record
|
||||||
23
__tests__/lcov.test.ts
Normal file
23
__tests__/lcov.test.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import * as fs from 'fs'
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
import {getReport} from '../src/report/get-report'
|
||||||
|
import {normalizeFilePath} from '../src/utils/path-utils'
|
||||||
|
import {LcovParser} from '../src/parsers/lcov/lcov-parser'
|
||||||
|
|
||||||
|
describe('lcov report coverage', () => {
|
||||||
|
it('report from facebook/jest test results matches snapshot', async () => {
|
||||||
|
const fixturePath = path.join(__dirname, 'fixtures', 'lcov.info')
|
||||||
|
const outputPath = path.join(__dirname, '__outputs__', 'lcov-report-results.md')
|
||||||
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
|
const parser = new LcovParser({parseErrors: true, trackedFiles: []})
|
||||||
|
const result = await parser.parse(filePath, fileContent)
|
||||||
|
expect(result).toMatchSnapshot()
|
||||||
|
|
||||||
|
const report = getReport([result])
|
||||||
|
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
|
||||||
|
fs.writeFileSync(outputPath, report)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -32,6 +32,7 @@ inputs:
|
||||||
- jest-junit
|
- jest-junit
|
||||||
- mocha-json
|
- mocha-json
|
||||||
- swift-xunit
|
- swift-xunit
|
||||||
|
- lcov
|
||||||
required: true
|
required: true
|
||||||
list-suites:
|
list-suites:
|
||||||
description: |
|
description: |
|
||||||
|
|
|
||||||
250
dist/index.js
generated
vendored
250
dist/index.js
generated
vendored
|
|
@ -268,6 +268,7 @@ const mocha_json_parser_1 = __nccwpck_require__(6043);
|
||||||
const swift_xunit_parser_1 = __nccwpck_require__(5366);
|
const swift_xunit_parser_1 = __nccwpck_require__(5366);
|
||||||
const path_utils_1 = __nccwpck_require__(4070);
|
const path_utils_1 = __nccwpck_require__(4070);
|
||||||
const github_utils_1 = __nccwpck_require__(3522);
|
const github_utils_1 = __nccwpck_require__(3522);
|
||||||
|
const lcov_parser_1 = __nccwpck_require__(5698);
|
||||||
function main() {
|
function main() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
|
|
@ -436,6 +437,8 @@ class TestReporter {
|
||||||
return new mocha_json_parser_1.MochaJsonParser(options);
|
return new mocha_json_parser_1.MochaJsonParser(options);
|
||||||
case 'swift-xunit':
|
case 'swift-xunit':
|
||||||
return new swift_xunit_parser_1.SwiftXunitParser(options);
|
return new swift_xunit_parser_1.SwiftXunitParser(options);
|
||||||
|
case 'lcov':
|
||||||
|
return new lcov_parser_1.LcovParser(options);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`);
|
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`);
|
||||||
}
|
}
|
||||||
|
|
@ -1290,6 +1293,120 @@ class JestJunitParser {
|
||||||
exports.JestJunitParser = JestJunitParser;
|
exports.JestJunitParser = JestJunitParser;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 5698:
|
||||||
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.LcovParser = void 0;
|
||||||
|
const test_results_1 = __nccwpck_require__(2768);
|
||||||
|
const lcov_utils_1 = __nccwpck_require__(4750);
|
||||||
|
class LcovParser {
|
||||||
|
constructor(options) {
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
parse(path, content) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const report = yield this.parseFile(path, content);
|
||||||
|
return this.getTestRunResult(path, report);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
parseFile(path, content) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
try {
|
||||||
|
return (0, lcov_utils_1.parseProm)(content);
|
||||||
|
//return JSON.parse(content) as LcovReport
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new Error(`Invalid JSON at ${path}\n\n${e}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getTestRunResult(path, report) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const suites = [];
|
||||||
|
for (const reportElement of report) {
|
||||||
|
const fileName = reportElement.file;
|
||||||
|
const statementCaseResult = {
|
||||||
|
name: `lines ${this.getPartInfo(reportElement.lines)}`,
|
||||||
|
time: 0,
|
||||||
|
result: this.getPercentage(reportElement.lines) >= 80 ? 'success' : 'failed'
|
||||||
|
};
|
||||||
|
const fonctionCaseResult = {
|
||||||
|
name: `functions ${this.getPartInfo(reportElement.functions)}`,
|
||||||
|
time: 0,
|
||||||
|
result: this.getPercentage(reportElement.functions) >= 80 ? 'success' : 'failed'
|
||||||
|
};
|
||||||
|
const brancheCaseResult = {
|
||||||
|
name: `branches ${this.getPartInfo(reportElement.branches)}`,
|
||||||
|
time: 0,
|
||||||
|
result: this.getPercentage(reportElement.branches) >= 80 ? 'success' : 'failed'
|
||||||
|
};
|
||||||
|
const testCases = [statementCaseResult, fonctionCaseResult, brancheCaseResult];
|
||||||
|
const groups = [new test_results_1.TestGroupResult(fileName, testCases)];
|
||||||
|
const suite = new test_results_1.TestSuiteResult(fileName, groups);
|
||||||
|
suites.push(suite);
|
||||||
|
}
|
||||||
|
return new test_results_1.TestRunResult(path, suites);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getPercentage(stat) {
|
||||||
|
return stat ? (stat.hit / stat.found) * 100 : 100;
|
||||||
|
}
|
||||||
|
getPartInfo(stat) {
|
||||||
|
return `${this.getPercentage(stat)}% (${stat.hit}/${stat.found})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.LcovParser = LcovParser;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 4750:
|
||||||
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.parseProm = void 0;
|
||||||
|
const lcov_parse_1 = __importDefault(__nccwpck_require__(7454));
|
||||||
|
const parseProm = (pathOrStr) => __awaiter(void 0, void 0, void 0, function* () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
(0, lcov_parse_1.default)(pathOrStr, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
resolve(data !== null && data !== void 0 ? data : []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
exports.parseProm = parseProm;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 6043:
|
/***/ 6043:
|
||||||
|
|
@ -23434,6 +23551,139 @@ class Keyv extends EventEmitter {
|
||||||
module.exports = Keyv;
|
module.exports = Keyv;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 7454:
|
||||||
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (c) 2012, Yahoo! Inc. All rights reserved.
|
||||||
|
Code licensed under the BSD License:
|
||||||
|
http://yuilibrary.com/license/
|
||||||
|
*/
|
||||||
|
|
||||||
|
var fs = __nccwpck_require__(7147),
|
||||||
|
path = __nccwpck_require__(1017);
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
var exists = fs.exists || path.exists;
|
||||||
|
|
||||||
|
var walkFile = function(str, cb) {
|
||||||
|
var data = [], item;
|
||||||
|
|
||||||
|
[ 'end_of_record' ].concat(str.split('\n')).forEach(function(line) {
|
||||||
|
line = line.trim();
|
||||||
|
var allparts = line.split(':'),
|
||||||
|
parts = [allparts.shift(), allparts.join(':')],
|
||||||
|
lines, fn;
|
||||||
|
|
||||||
|
switch (parts[0].toUpperCase()) {
|
||||||
|
case 'TN':
|
||||||
|
item.title = parts[1].trim();
|
||||||
|
break;
|
||||||
|
case 'SF':
|
||||||
|
item.file = parts.slice(1).join(':').trim();
|
||||||
|
break;
|
||||||
|
case 'FNF':
|
||||||
|
item.functions.found = Number(parts[1].trim());
|
||||||
|
break;
|
||||||
|
case 'FNH':
|
||||||
|
item.functions.hit = Number(parts[1].trim());
|
||||||
|
break;
|
||||||
|
case 'LF':
|
||||||
|
item.lines.found = Number(parts[1].trim());
|
||||||
|
break;
|
||||||
|
case 'LH':
|
||||||
|
item.lines.hit = Number(parts[1].trim());
|
||||||
|
break;
|
||||||
|
case 'DA':
|
||||||
|
lines = parts[1].split(',');
|
||||||
|
item.lines.details.push({
|
||||||
|
line: Number(lines[0]),
|
||||||
|
hit: Number(lines[1])
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'FN':
|
||||||
|
fn = parts[1].split(',');
|
||||||
|
item.functions.details.push({
|
||||||
|
name: fn[1],
|
||||||
|
line: Number(fn[0])
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'FNDA':
|
||||||
|
fn = parts[1].split(',');
|
||||||
|
item.functions.details.some(function(i, k) {
|
||||||
|
if (i.name === fn[1] && i.hit === undefined) {
|
||||||
|
item.functions.details[k].hit = Number(fn[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'BRDA':
|
||||||
|
fn = parts[1].split(',');
|
||||||
|
item.branches.details.push({
|
||||||
|
line: Number(fn[0]),
|
||||||
|
block: Number(fn[1]),
|
||||||
|
branch: Number(fn[2]),
|
||||||
|
taken: ((fn[3] === '-') ? 0 : Number(fn[3]))
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'BRF':
|
||||||
|
item.branches.found = Number(parts[1]);
|
||||||
|
break;
|
||||||
|
case 'BRH':
|
||||||
|
item.branches.hit = Number(parts[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.indexOf('end_of_record') > -1) {
|
||||||
|
data.push(item);
|
||||||
|
item = {
|
||||||
|
lines: {
|
||||||
|
found: 0,
|
||||||
|
hit: 0,
|
||||||
|
details: []
|
||||||
|
},
|
||||||
|
functions: {
|
||||||
|
hit: 0,
|
||||||
|
found: 0,
|
||||||
|
details: []
|
||||||
|
},
|
||||||
|
branches: {
|
||||||
|
hit: 0,
|
||||||
|
found: 0,
|
||||||
|
details: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
data.shift();
|
||||||
|
|
||||||
|
if (data.length) {
|
||||||
|
cb(null, data);
|
||||||
|
} else {
|
||||||
|
cb('Failed to parse string');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var parse = function(file, cb) {
|
||||||
|
exists(file, function(x) {
|
||||||
|
if (!x) {
|
||||||
|
return walkFile(file, cb);
|
||||||
|
}
|
||||||
|
fs.readFile(file, 'utf8', function(err, str) {
|
||||||
|
walkFile(str, cb);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = parse;
|
||||||
|
module.exports.source = walkFile;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 9662:
|
/***/ 9662:
|
||||||
|
|
|
||||||
29
dist/licenses.txt
generated
vendored
29
dist/licenses.txt
generated
vendored
|
|
@ -1053,6 +1053,35 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
keyv
|
keyv
|
||||||
MIT
|
MIT
|
||||||
|
|
||||||
|
lcov-parse
|
||||||
|
BSD-3-Clause
|
||||||
|
Copyright 2012 Yahoo! Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the Yahoo! Inc. nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
lowercase-keys
|
lowercase-keys
|
||||||
MIT
|
MIT
|
||||||
MIT License
|
MIT License
|
||||||
|
|
|
||||||
16
package-lock.json
generated
16
package-lock.json
generated
|
|
@ -15,6 +15,7 @@
|
||||||
"adm-zip": "^0.5.10",
|
"adm-zip": "^0.5.10",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
|
"lcov-parse": "^1.0.0",
|
||||||
"picomatch": "^3.0.1",
|
"picomatch": "^3.0.1",
|
||||||
"xml2js": "^0.6.2"
|
"xml2js": "^0.6.2"
|
||||||
},
|
},
|
||||||
|
|
@ -25,6 +26,7 @@
|
||||||
"@types/adm-zip": "^0.5.5",
|
"@types/adm-zip": "^0.5.5",
|
||||||
"@types/github-slugger": "^1.3.0",
|
"@types/github-slugger": "^1.3.0",
|
||||||
"@types/jest": "^29.5.11",
|
"@types/jest": "^29.5.11",
|
||||||
|
"@types/lcov-parse": "^1.0.2",
|
||||||
"@types/node": "^20.10.4",
|
"@types/node": "^20.10.4",
|
||||||
"@types/picomatch": "^2.3.3",
|
"@types/picomatch": "^2.3.3",
|
||||||
"@types/xml2js": "^0.4.14",
|
"@types/xml2js": "^0.4.14",
|
||||||
|
|
@ -1702,6 +1704,12 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/lcov-parse": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/lcov-parse/-/lcov-parse-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-tdoxiYm04XdDEdR7UMwkWj78UAVo9U2IOcxI6tmX2/s9TK/ue/9T8gbpS/07yeWyVkVO0UumFQ5EUIBQbVejzQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.10.4",
|
"version": "20.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
|
||||||
|
|
@ -5858,6 +5866,14 @@
|
||||||
"language-subtag-registry": "~0.3.2"
|
"language-subtag-registry": "~0.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lcov-parse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==",
|
||||||
|
"bin": {
|
||||||
|
"lcov-parse": "bin/cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/leven": {
|
"node_modules/leven": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
"adm-zip": "^0.5.10",
|
"adm-zip": "^0.5.10",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
|
"lcov-parse": "^1.0.0",
|
||||||
"picomatch": "^3.0.1",
|
"picomatch": "^3.0.1",
|
||||||
"xml2js": "^0.6.2"
|
"xml2js": "^0.6.2"
|
||||||
},
|
},
|
||||||
|
|
@ -48,6 +49,7 @@
|
||||||
"@types/adm-zip": "^0.5.5",
|
"@types/adm-zip": "^0.5.5",
|
||||||
"@types/github-slugger": "^1.3.0",
|
"@types/github-slugger": "^1.3.0",
|
||||||
"@types/jest": "^29.5.11",
|
"@types/jest": "^29.5.11",
|
||||||
|
"@types/lcov-parse": "^1.0.2",
|
||||||
"@types/node": "^20.10.4",
|
"@types/node": "^20.10.4",
|
||||||
"@types/picomatch": "^2.3.3",
|
"@types/picomatch": "^2.3.3",
|
||||||
"@types/xml2js": "^0.4.14",
|
"@types/xml2js": "^0.4.14",
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser'
|
||||||
|
|
||||||
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
|
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
|
||||||
import {getCheckRunContext} from './utils/github-utils'
|
import {getCheckRunContext} from './utils/github-utils'
|
||||||
|
import {LcovParser} from './parsers/lcov/lcov-parser'
|
||||||
|
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
|
@ -225,6 +226,8 @@ class TestReporter {
|
||||||
return new MochaJsonParser(options)
|
return new MochaJsonParser(options)
|
||||||
case 'swift-xunit':
|
case 'swift-xunit':
|
||||||
return new SwiftXunitParser(options)
|
return new SwiftXunitParser(options)
|
||||||
|
case 'lcov':
|
||||||
|
return new LcovParser(options)
|
||||||
default:
|
default:
|
||||||
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`)
|
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
59
src/parsers/lcov/lcov-parser.ts
Normal file
59
src/parsers/lcov/lcov-parser.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import {ParseOptions, TestParser} from '../../test-parser'
|
||||||
|
|
||||||
|
import {TestCaseResult, TestGroupResult, TestRunResult, TestSuiteResult} from '../../test-results'
|
||||||
|
import {parseProm} from './lcov-utils'
|
||||||
|
import {LcovBranch, LcovFile, LcovFunc, LcovLine, LcovPart} from 'lcov-parse'
|
||||||
|
|
||||||
|
export class LcovParser implements TestParser {
|
||||||
|
constructor(readonly options: ParseOptions) {}
|
||||||
|
async parse(path: string, content: string): Promise<TestRunResult> {
|
||||||
|
const report = await this.parseFile(path, content)
|
||||||
|
return this.getTestRunResult(path, report)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async parseFile(path: string, content: string): Promise<LcovFile[]> {
|
||||||
|
try {
|
||||||
|
return parseProm(content)
|
||||||
|
//return JSON.parse(content) as LcovReport
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Invalid JSON at ${path}\n\n${e}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async getTestRunResult(path: string, report: LcovFile[]): Promise<TestRunResult> {
|
||||||
|
const suites: TestSuiteResult[] = []
|
||||||
|
|
||||||
|
for (const reportElement of report) {
|
||||||
|
const fileName = reportElement.file
|
||||||
|
|
||||||
|
const statementCaseResult: TestCaseResult = {
|
||||||
|
name: `lines ${this.getPartInfo(reportElement.lines)}`,
|
||||||
|
time: 0,
|
||||||
|
result: this.getPercentage(reportElement.lines) >= 80 ? 'success' : 'failed'
|
||||||
|
}
|
||||||
|
const fonctionCaseResult: TestCaseResult = {
|
||||||
|
name: `functions ${this.getPartInfo(reportElement.functions)}`,
|
||||||
|
time: 0,
|
||||||
|
result: this.getPercentage(reportElement.functions) >= 80 ? 'success' : 'failed'
|
||||||
|
}
|
||||||
|
const brancheCaseResult: TestCaseResult = {
|
||||||
|
name: `branches ${this.getPartInfo(reportElement.branches)}`,
|
||||||
|
time: 0,
|
||||||
|
result: this.getPercentage(reportElement.branches) >= 80 ? 'success' : 'failed'
|
||||||
|
}
|
||||||
|
|
||||||
|
const testCases: TestCaseResult[] = [statementCaseResult, fonctionCaseResult, brancheCaseResult]
|
||||||
|
const groups: TestGroupResult[] = [new TestGroupResult(fileName, testCases)]
|
||||||
|
const suite: TestSuiteResult = new TestSuiteResult(fileName, groups)
|
||||||
|
|
||||||
|
suites.push(suite)
|
||||||
|
}
|
||||||
|
return new TestRunResult(path, suites)
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPercentage(stat: LcovPart<LcovLine | LcovFunc | LcovBranch>): number {
|
||||||
|
return stat ? (stat.hit / stat.found) * 100 : 100
|
||||||
|
}
|
||||||
|
private getPartInfo(stat: LcovPart<LcovLine | LcovFunc | LcovBranch>): string {
|
||||||
|
return `${this.getPercentage(stat)}% (${stat.hit}/${stat.found})`
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/parsers/lcov/lcov-types.ts
Normal file
21
src/parsers/lcov/lcov-types.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
export interface LcovReport {
|
||||||
|
[str: string]: {
|
||||||
|
path: string
|
||||||
|
statementMap: unknown
|
||||||
|
fnMap: unknown
|
||||||
|
branchMap: unknown
|
||||||
|
s: CovStats
|
||||||
|
f: CovStats
|
||||||
|
b: CovStats
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CovStats {
|
||||||
|
[str: string]: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CovParsedStat {
|
||||||
|
max: number
|
||||||
|
nonCovered: number
|
||||||
|
percentage: number
|
||||||
|
}
|
||||||
14
src/parsers/lcov/lcov-utils.ts
Normal file
14
src/parsers/lcov/lcov-utils.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import parse, {LcovFile} from 'lcov-parse'
|
||||||
|
|
||||||
|
const parseProm = async (pathOrStr: string): Promise<LcovFile[]> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
parse(pathOrStr, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
resolve(data ?? [])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export {parseProm}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue