Compare commits

..

17 Commits

Author SHA1 Message Date
Julien Catania
2c5485e682 feat(lcov) fix CI 2024-01-12 16:54:11 +01:00
Julien Catania
6effce6d66 feat(lcov) fix CI 2024-01-12 16:52:34 +01:00
Julien Catania
f19a7213c3 feat(lcov) use really lcov.info file 2024-01-12 16:18:04 +01:00
Julien Catania
712fabc3c8 Merge branch 'main' into feature/lcov-support
# Conflicts:
#	dist/index.js
#	src/main.ts
2024-01-12 16:15:57 +01:00
Julien Catania
fb59f4f91d feat(lcov) use really lcov.info file 2024-01-12 16:10:04 +01:00
Julien Catania
61007344dd Merge pull request #351 from j-catania/main
Adding LCOV Support
2024-01-02 21:25:14 +01:00
Julien Catania
4dff4fc7ee Merge remote-tracking branch 'origin/main'
# Conflicts:
#	__tests__/lcov.test.ts
#	action.yml
#	package-lock.json
#	package.json
#	src/main.ts
2024-01-02 21:23:53 +01:00
Julien Catania
39f548db94 sync fork 2024-01-02 21:21:26 +01:00
Julien Catania
cc150eb989 add lcov as reporter 2024-01-02 21:20:18 +01:00
Julien Catania
440cc5265e add lcov as reporter 2024-01-02 21:19:57 +01:00
Julien Catania
713455873c good start 2024-01-02 21:19:21 +01:00
Julien Catania
883ec99854 add lcov as reporter 2024-01-02 21:05:34 +01:00
Julien Catania
62968bd2b2 add lcov as reporter 2024-01-02 17:05:11 +01:00
Julien Catania
0fc59a15c8 Merge pull request #9 from j-catania/dependabot/npm_and_yarn/xml2js-0.5.0
Bump xml2js from 0.4.23 to 0.5.0
2023-09-18 20:42:44 +02:00
dependabot[bot]
dc9819d851 Bump xml2js from 0.4.23 to 0.5.0
Bumps [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js) from 0.4.23 to 0.5.0.
- [Commits](https://github.com/Leonidas-from-XIV/node-xml2js/commits/0.5.0)

---
updated-dependencies:
- dependency-name: xml2js
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-18 18:41:14 +00:00
Julien Catania
48cc88be3a update dep 2023-09-18 20:38:25 +02:00
Julien Catania
5db7763d84 good start 2023-08-12 15:51:32 +02:00
14 changed files with 593 additions and 46 deletions

View File

@@ -1,46 +0,0 @@
name: Run all reports
on:
pull_request:
branches:
- main
paths-ignore: [ '**.md' ]
push:
paths-ignore: [ '**.md' ]
branches:
- main
workflow_dispatch:
jobs:
reports:
name: Run
runs-on: ubuntu-latest
strategy:
matrix:
reporter: [ jest-junit, mocha-json, swift-xunit, dart-json, dotnet-trx, java-junit, flutter-json ]
include:
- reporter: jest-junit
path: ./__tests__/fixtures/jest-junit.xml
- reporter: mocha-json
path: ./__tests__/fixtures/mocha-json.json
- reporter: swift-xunit
path: ./__tests__/fixtures/swift-xunit.xml
- reporter: dart-json
path: ./__tests__/fixtures/dart-json.json
- reporter: dotnet-trx
path: ./__tests__/fixtures/dotnet-trx.trx
- reporter: java-junit
path: ./__tests__/fixtures/external/java/pulsar-test-report.xml
- reporter: flutter-json
path: ./__tests__/fixtures/external/flutter/provider-test-results.json
steps:
- uses: actions/checkout@v4
- uses: ./
with:
name: ${{ matrix.reporter }} report
path: ${{ matrix.path }}
reporter: ${{ matrix.reporter }}
fail-on-error: false

View File

@@ -0,0 +1,21 @@
![Tests failed](https://img.shields.io/badge/tests-4%20passed%2C%202%20failed-critical)
## ❌ <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)
```

View 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,
}
`;

View 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
View 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)
})
})

View File

@@ -32,6 +32,7 @@ inputs:
- jest-junit
- mocha-json
- swift-xunit
- lcov
required: true
list-suites:
description: |

250
dist/index.js generated vendored
View File

@@ -268,6 +268,7 @@ const mocha_json_parser_1 = __nccwpck_require__(6043);
const swift_xunit_parser_1 = __nccwpck_require__(5366);
const path_utils_1 = __nccwpck_require__(4070);
const github_utils_1 = __nccwpck_require__(3522);
const lcov_parser_1 = __nccwpck_require__(5698);
function main() {
return __awaiter(this, void 0, void 0, function* () {
try {
@@ -436,6 +437,8 @@ class TestReporter {
return new mocha_json_parser_1.MochaJsonParser(options);
case 'swift-xunit':
return new swift_xunit_parser_1.SwiftXunitParser(options);
case 'lcov':
return new lcov_parser_1.LcovParser(options);
default:
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`);
}
@@ -1290,6 +1293,120 @@ class 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:
@@ -23434,6 +23551,139 @@ class Keyv extends EventEmitter {
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:

29
dist/licenses.txt generated vendored
View File

@@ -1053,6 +1053,35 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keyv
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
MIT
MIT License

16
package-lock.json generated
View File

@@ -15,6 +15,7 @@
"adm-zip": "^0.5.10",
"fast-glob": "^3.3.2",
"got": "^11.8.2",
"lcov-parse": "^1.0.0",
"picomatch": "^3.0.1",
"xml2js": "^0.6.2"
},
@@ -25,6 +26,7 @@
"@types/adm-zip": "^0.5.5",
"@types/github-slugger": "^1.3.0",
"@types/jest": "^29.5.11",
"@types/lcov-parse": "^1.0.2",
"@types/node": "^20.10.4",
"@types/picomatch": "^2.3.3",
"@types/xml2js": "^0.4.14",
@@ -1702,6 +1704,12 @@
"@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": {
"version": "20.10.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
@@ -5858,6 +5866,14 @@
"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": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",

View File

@@ -38,6 +38,7 @@
"adm-zip": "^0.5.10",
"fast-glob": "^3.3.2",
"got": "^11.8.2",
"lcov-parse": "^1.0.0",
"picomatch": "^3.0.1",
"xml2js": "^0.6.2"
},
@@ -48,6 +49,7 @@
"@types/adm-zip": "^0.5.5",
"@types/github-slugger": "^1.3.0",
"@types/jest": "^29.5.11",
"@types/lcov-parse": "^1.0.2",
"@types/node": "^20.10.4",
"@types/picomatch": "^2.3.3",
"@types/xml2js": "^0.4.14",

View File

@@ -19,6 +19,7 @@ import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser'
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
import {getCheckRunContext} from './utils/github-utils'
import {LcovParser} from './parsers/lcov/lcov-parser'
async function main(): Promise<void> {
try {
@@ -225,6 +226,8 @@ class TestReporter {
return new MochaJsonParser(options)
case 'swift-xunit':
return new SwiftXunitParser(options)
case 'lcov':
return new LcovParser(options)
default:
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`)
}

View 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})`
}
}

View 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
}

View 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}