Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@codechecks/type-coverage-watcher

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@codechecks/type-coverage-watcher - npm Package Compare versions

Comparing version
0.1.2
to
0.1.3
+1
-1
lib/index.d.ts
import { Options } from "./types";
export declare function typeCoverageWatcher(_options: Options): Promise<void>;
export declare function typeCoverageWatcher(_options?: Options): Promise<void>;
export default typeCoverageWatcher;

@@ -7,3 +7,3 @@ "use strict";

const formatters_1 = require("./formatters");
async function typeCoverageWatcher(_options) {
async function typeCoverageWatcher(_options = {}) {
const options = normalizeOptions(_options);

@@ -10,0 +10,0 @@ const _typeCoverage = await type_coverage_core_1.lint(options.tsconfigPath, {

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}

@@ -17,3 +17,3 @@ {

"author": "Chris Kaczor <chris@kaczor.io>",
"version": "0.1.2",
"version": "0.1.3",
"main": "lib/index.js",

@@ -60,2 +60,5 @@ "types": "lib/index.d.ts",

},
"files": [
"lib/**/*"
],
"publishConfig": {

@@ -62,0 +65,0 @@ "access": "public"

version: 2
jobs:
build:
docker:
- image: circleci/node:10.13.0
working_directory: /home/circleci/app
steps:
- checkout
- restore_cache:
key: v1-dep-{{ checksum "yarn.lock" }}
- run:
name: Install deps
command: yarn install --frozen-lockfile
- save_cache:
paths:
- ./node_modules
- ~/.cache
key: v1-dep-{{ checksum "yarn.lock" }}
- run:
name: Run tests
command: yarn test

Sorry, the diff of this file is not supported yet

{
"printWidth": 120,
"tabWidth": 2,
"semi": true,
"singleQuote": false,
"trailingComma": "all"
}
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "test",
"program": "${workspaceFolder}/node_modules/.bin/jest"
},
{
"type": "node",
"request": "launch",
"name": "test (update snapshots)",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["-u"]
}
]
}
# Contributing
All contributions are welcomed.
Do you have an idea for improving this check? Please, first submit a github issue and describe your
proposal.
When you're done with your changes use `yarn test:fix` to run `prettier` to reformat code, `tslint`
in fix mode, `tsc` to make sure that there are no compilation errors, and unit tests.
Thanks! 🙏🏻
module.exports = {
roots: ["<rootDir>/src"],
transform: {
"^.+\\.tsx?$": "ts-jest",
},
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
};

Sorry, the diff of this file is not supported yet

import * as CC from "@codechecks/client";
import { join } from "path";
export const codechecks: Partial<typeof CC.codechecks> = {
report: jest.fn(),
success: jest.fn(),
failure: jest.fn(),
getValue: jest.fn(),
saveValue: jest.fn(),
getDirectory: jest.fn(),
saveDirectory: jest.fn(),
isPr: jest.fn(),
context: {
workspaceRoot: join(__dirname, "..", ".."),
} as any,
};
import * as TypeCoverage from "type-coverage-core";
export const lint: typeof TypeCoverage.lint = jest.fn();
import { formatShortDescription } from "../formatters";
describe("formatters > formatShortDescription", () => {
it("should work", () => {
const actual = formatShortDescription({ coverageDiffPerc: 1.4, headTypeCoveragePerc: 90.2, newUntypedSymbols: 1 });
expect(actual).toMatchInlineSnapshot(`"Change: +1.40% Total: 90.20% New untyped symbols: 1"`);
});
it("should work with atLeast", () => {
const actual = formatShortDescription({
coverageDiffPerc: 1.4,
headTypeCoveragePerc: 90.2,
newUntypedSymbols: 1,
atLeast: 90,
});
expect(actual).toMatchInlineSnapshot(`"Change: +1.40% Total: 90.20% (min. 90.00%) New untyped symbols: 1"`);
});
});
import { typeCoverageWatcher } from "../index";
import { lint } from "type-coverage-core";
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-core").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: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% New untyped symbols: 0",
"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% New untyped symbols: 1",
"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% New untyped symbols: 0",
"status": "success",
},
],
],
"results": Array [
Object {
"isThrow": false,
"value": undefined,
},
],
}
`);
});
it("should handle atLeast option", async () => {
codechecksMock.isPr.mockReturnValue(true);
typeCoverageMock.mockReturnValue({
correctCount: 4,
totalCount: 10,
anys: [],
program: undefined as any,
});
await typeCoverageWatcher({ tsconfigPath: "./tsconfig.json", atLeast: 50 });
expect(codechecks.report).toMatchInlineSnapshot(`
[MockFunction] {
"calls": Array [
Array [
Object {
"longDescription": "New untyped symbols: 0",
"name": "Type Coverage",
"shortDescription": "Change: +40.00% Total: 40.00% (min. 50.00%) New untyped symbols: 0",
"status": "failure",
},
],
],
"results": Array [
Object {
"isThrow": false,
"value": undefined,
},
],
}
`);
});
});
interface FormatShortDescriptionArgs {
coverageDiffPerc: number;
headTypeCoveragePerc: number;
newUntypedSymbols: number;
atLeast?: number;
}
export function formatShortDescription({
coverageDiffPerc,
atLeast,
headTypeCoveragePerc,
newUntypedSymbols,
}: FormatShortDescriptionArgs): string {
const change = renderSign(coverageDiffPerc) + perc(coverageDiffPerc);
const limit = atLeast === undefined ? "" : ` (min. ${perc(atLeast)})`;
const total = perc(headTypeCoveragePerc);
return `Change: ${change} Total: ${total}${limit} New untyped symbols: ${newUntypedSymbols}`;
}
export function perc(n: number): string {
return n.toFixed(2) + "%";
}
export function renderSign(value: number): string {
if (value > 0) {
return "+";
} else {
// we dont' render signs for negative (it's part of a number xD) or 0
return "";
}
}
import { codechecks, CodeChecksReport } from "@codechecks/client";
import { lint as getTypeCoverageInfo } from "type-coverage-core";
import { RawTypeCoverageReport, TypeCoverageArtifact, Options, SymbolInfo, NormalizedOptions } from "./types";
import { groupBy } from "lodash";
import { formatShortDescription } from "./formatters";
export async function typeCoverageWatcher(_options: Options): Promise<void> {
const options = normalizeOptions(_options);
const _typeCoverage = await getTypeCoverageInfo(options.tsconfigPath, {
debug: false,
ignoreCatch: _options.ignoreCatch,
ignoreFiles: _options.ignoreFiles,
strict: _options.strict,
});
const typeCoverage = normalizeTypeCoverage(_typeCoverage);
await codechecks.saveValue(options.artifactName, typeCoverage);
if (!codechecks.isPr()) {
return;
}
const baseTypeCoverage = await codechecks.getValue<TypeCoverageArtifact>(options.artifactName);
const report = getReport(typeCoverage, baseTypeCoverage, options);
await codechecks.report(report);
}
export default typeCoverageWatcher;
function getReport(
headTypeCoverageArtifact: TypeCoverageArtifact,
baseTypeCoverageArtifact: TypeCoverageArtifact | undefined,
options: NormalizedOptions,
): CodeChecksReport {
const headTypeCoverage = (headTypeCoverageArtifact.typedSymbols / headTypeCoverageArtifact.totalSymbols) * 100;
const baseTypeCoverage = baseTypeCoverageArtifact
? (baseTypeCoverageArtifact.typedSymbols / baseTypeCoverageArtifact.totalSymbols) * 100
: 0;
const coverageDiff = headTypeCoverage - baseTypeCoverage;
const newUntypedSymbols = findNew(
headTypeCoverageArtifact.allUntypedSymbols,
baseTypeCoverageArtifact ? baseTypeCoverageArtifact.allUntypedSymbols : [],
);
const shortDescription = formatShortDescription({
coverageDiffPerc: coverageDiff,
atLeast: options.atLeast,
headTypeCoveragePerc: headTypeCoverage,
newUntypedSymbols: newUntypedSymbols.length,
});
let longDescription = `New untyped symbols: ${newUntypedSymbols.length}`;
if (newUntypedSymbols.length > 0) {
longDescription += `
| File | line:character | Symbol |
|:-----:|:-----:|:-----:|
${newUntypedSymbols
.slice(0, 100)
.map(s => `| ${s.filename} | ${s.line}:${s.character} | ${s.symbol} |`)
.join("\n")}`;
}
const status = options.atLeast === undefined || headTypeCoverage > options.atLeast ? "success" : "failure";
return {
name: options.name,
status,
shortDescription,
longDescription,
};
}
function findNew(headSymbols: SymbolInfo[], baseSymbols: SymbolInfo[]): SymbolInfo[] {
const baseSymbolsByFilename = groupBy(baseSymbols, s => s.filename);
const newSymbols: SymbolInfo[] = [];
for (const headSymbol of headSymbols) {
// we assess if symbols are the same only by looking at filename and symbol name (we ignore line and character)
const baseSymbolMatch =
(baseSymbolsByFilename[headSymbol.filename] || []).filter(s => s.symbol === headSymbol.symbol).length > 0;
if (!baseSymbolMatch) {
newSymbols.push(headSymbol);
}
}
return newSymbols;
}
function normalizeTypeCoverage(rawTypeCoverage: RawTypeCoverageReport): TypeCoverageArtifact {
return {
typedSymbols: rawTypeCoverage.correctCount,
totalSymbols: rawTypeCoverage.totalCount,
allUntypedSymbols: rawTypeCoverage.anys.map(a => ({
filename: a.file,
line: a.line,
character: a.character,
symbol: a.text,
})),
};
}
function normalizeOptions(options: Options = {}): NormalizedOptions {
const name = options.name || "Type Coverage";
return {
name,
tsconfigPath: options.name || "tsconfig.json",
artifactName: `type-coverage:${name}`,
atLeast: options.atLeast,
};
}
import { AnyInfo } from "type-coverage-core";
export interface Options {
tsconfigPath?: string;
name?: string;
ignoreFiles?: string[];
ignoreCatch?: boolean;
atLeast?: number;
strict?: boolean;
}
export interface NormalizedOptions {
tsconfigPath: string;
name: string;
artifactName: string;
atLeast?: number;
}
export interface TypeCoverageArtifact {
typedSymbols: number;
totalSymbols: number;
allUntypedSymbols: SymbolInfo[];
}
export interface SymbolInfo {
filename: string;
line: number;
character: number;
symbol: string;
}
export interface RawTypeCoverageReport {
correctCount: number;
totalCount: number;
anys: AnyInfo[];
}
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"strict": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"forceConsistentCasingInFileNames": true,
"plugins": [
{
"name": "tslint-language-service",
"configFile": "./node_modules/typestrict/tslint.js",
"alwaysShowRuleFailuresAsWarnings": true
}
],
"lib": ["es2015", "esnext.asynciterable"],
"sourceMap": true,
"declaration": true,
"outDir": "lib",
"skipLibCheck": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
{
"extends": "typestrict",
"rules": {
"no-console": true,
"no-debugger": true,
"typedef": [true, "call-signature"],
"mocha-avoid-only": true,
"interface-name": [true, "never-prefix"],
"no-commented-code": true,
"no-use-before-declare": false,
"restrict-plus-operands": false
}
}

Sorry, the diff of this file is too big to display