c8
c8 copied to clipboard
0% coverage for files only containing TypeScript interfaces
- Version: node v18.7.0 + c8 v8.0.1
- Platform: 64-bit (Windows)
I'm running c8
using mocha
with ts-node/register
and I'm wondering if that might cause the issue. Essentially, I have a file task-result.ts
that only contains a ITaskResult
interface. This is used from task-runner.ts
(import { ITaskResult } from "./task-result"
). I have tests with 100% coverage for task-runner.ts
, but using the --all
flag, c8
reports 0% coverage for task-result.ts
.
If I move the interface into task-runner.ts
instead, task-runner.ts
still reports 100% coverage as expected.
Is this an artefact from TS interfaces not being transpiled to JS and/or related to the same underlying issue in #182? Or is there a way to solve it while keeping the interface in its own file (I'd prefer not having to exclude individual files like this)?
// .c8rc.json
{
"all": true,
"src": ["./src"],
"extension": [".ts"],
"report-dir": "./coverage"
}
// package.json (snippet)
"scripts": {
"test": "mocha -r ts-node/register -r mocha-suppress-logs './tests/**/*.test.ts'",
"coverage": "c8 npm test"
},
If necessary, I can create a small example to reproduce it.
@Xerillio could you please provide a reproduction for this issue.
@bcoe You got it 😉
/package.json
:
{
"scripts": {
"test": "mocha -r ts-node/register './tests/**/*.test.ts'",
"coverage": "c8 npm test"
},
"devDependencies": {
"@types/chai": "^4.3.9",
"@types/mocha": "^10.0.3",
"c8": "^8.0.1",
"chai": "^4.3.10",
"mocha": "^10.2.0",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
}
}
/tsconfig.json
:
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"esModuleInterop": true,
"strict": true
}
}
/.c8rc.json
:
{
"all": true,
"src": ["./src"],
"extension": [".ts"],
"report-dir": "./coverage"
}
/src/power.ts
:
import type { IPower } from "./ipower";
export class Power implements IPower {
calculate(base: number, exponent: number): number {
if (!Number.isInteger(exponent)) throw new Error("The exponent must be an integer");
let result = 1;
for (let i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
}
/src/ipower.ts
:
export interface IPower {
calculate(base: number, exponent: number): number
}
/tests/power.test.ts
:
import { Power } from "../src/power";
import { expect } from "chai";
describe("Power", () => {
describe("#calculate", () => {
it("should return 1 when the exponent is 0", () => {
const sut = new Power();
const result = sut.calculate(9.876, 0);
expect(result).to.equal(1);
});
it("should throw when the exponent is not an integer", () => {
const sut = new Power();
expect(() => sut.calculate(9.876, 1.1)).to.throw(
Error,
"The exponent must be an integer");
});
});
});
Running coverage
then produces this result (0% for ipower.ts
):
$ npm run coverage
...
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 70.58 | 60 | 50 | 70.58 |
ipower.ts | 0 | 0 | 0 | 0 | 1-3
power.ts | 85.71 | 75 | 100 | 85.71 | 9-10
-----------|---------|----------|---------|---------|-------------------
Funny thing I noticed now because I didn't add tests for 100% coverage... if you move the contents of ipower.ts
into power.ts
the coverage of power.ts
is strangely enough higher than before:
$ npm run coverage
...
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 87.5 | 75 | 100 | 87.5 |
power.ts | 87.5 | 75 | 100 | 87.5 | 7-8
----------|---------|----------|---------|---------|-------------------
Is there news about this issue?