codecheck-type-coverage
Version:
Track missing type coverage in TypeScript projects to ensure type safety
164 lines (151 loc) • 4.43 kB
text/typescript
import { typeCoverageWatcher } from "../index";
import { lint } from "type-coverage";
import { codeChecks } from "@codechecks/client";
import { TypeCoverageArtifact, RawTypeCoverageReport } from "../types";
type Mocked<T> = { [k in keyof T]: jest.Mock<T[k]> };
describe("type-coverage", () => {
const codeChecksMock = require("../__mocks__/@codechecks/client").codeChecks as Mocked<typeof codeChecks>;
const typeCoverageMock = require("../__mocks__/type-coverage").lint as jest.Mock<typeof lint>;
beforeEach(() => jest.resetAllMocks());
it("should work not in PR context", async () => {
codeChecksMock.isPr.mockReturnValue(false);
typeCoverageMock.mockReturnValue({
correctCount: 2,
totalCount: 2,
anys: [],
program: undefined as any,
});
await typeCoverageWatcher({ tsconfigPath: "./tsconfig.json" });
expect(codeChecks.report).toBeCalledTimes(0);
expect(codeChecks.saveValue).toMatchInlineSnapshot(`
[MockFunction] {
"calls": Array [
Array [
"type-coverage",
Object {
"allUntypedSymbols": Array [],
"totalSymbols": 2,
"typedSymbols": 2,
},
],
],
"results": Array [
Object {
"isThrow": false,
"value": undefined,
},
],
}
`);
});
it("should work in PR context", async () => {
codeChecksMock.isPr.mockReturnValue(true);
codeChecksMock.getValue.mockReturnValue({
typedSymbols: 2,
totalSymbols: 4,
allUntypedSymbols: [
{ filename: "index.ts", character: 1, line: 10, symbol: "app" },
{ filename: "index.ts", character: 1, line: 15, symbol: "res" },
{ filename: "index.ts", character: 2, line: 15, symbol: "key" }, // here we test that plugin doesnt care about exact place of a symbol, just it's name
],
} as TypeCoverageArtifact);
typeCoverageMock.mockReturnValue({
correctCount: 3,
totalCount: 4,
anys: [
{ file: "index.ts", character: 1, line: 15, text: "res" },
{ file: "index.ts", character: 3, line: 16, text: "key" },
],
program: undefined as any,
} as RawTypeCoverageReport);
await typeCoverageWatcher({ tsconfigPath: "./tsconfig.json" });
expect(codeChecks.report).toMatchInlineSnapshot(`
[MockFunction] {
"calls": Array [
Array [
Object {
"longDescription": "New untyped symbols: 0",
"name": "Type Coverage",
"shortDescription": "Change: +25.00% Total: 75.00%",
"status": "success",
},
],
],
"results": Array [
Object {
"isThrow": false,
"value": undefined,
},
],
}
`);
});
it("should work in PR context 2", async () => {
codeChecksMock.isPr.mockReturnValue(true);
codeChecksMock.getValue.mockReturnValue({
typedSymbols: 4,
totalSymbols: 5,
allUntypedSymbols: [],
} as TypeCoverageArtifact);
typeCoverageMock.mockReturnValue({
correctCount: 3,
totalCount: 4,
anys: [{ file: "index.ts", character: 1, line: 15, text: "res" }],
program: undefined as any,
} as RawTypeCoverageReport);
await typeCoverageWatcher({ tsconfigPath: "./tsconfig.json" });
expect(codeChecks.report).toMatchInlineSnapshot(`
[MockFunction] {
"calls": Array [
Array [
Object {
"longDescription": "New untyped symbols: 1
| File | line:character | Symbol |
|:-----:|:-----:|:-----:|
| index.ts | 15:1 | res |",
"name": "Type Coverage",
"shortDescription": "Change: -5.00% Total: 75.00%",
"status": "success",
},
],
],
"results": Array [
Object {
"isThrow": false,
"value": undefined,
},
],
}
`);
});
it("should work in PR context without baseline", async () => {
codeChecksMock.isPr.mockReturnValue(true);
typeCoverageMock.mockReturnValue({
correctCount: 2,
totalCount: 2,
anys: [],
program: undefined as any,
});
await typeCoverageWatcher({ tsconfigPath: "./tsconfig.json" });
expect(codeChecks.report).toMatchInlineSnapshot(`
[MockFunction] {
"calls": Array [
Array [
Object {
"longDescription": "New untyped symbols: 0",
"name": "Type Coverage",
"shortDescription": "Change: +100.00% Total: 100.00%",
"status": "success",
},
],
],
"results": Array [
Object {
"isThrow": false,
"value": undefined,
},
],
}
`);
});
});