Compare commits
1 commit
0.x
...
feat-updat
| Author | SHA1 | Date | |
|---|---|---|---|
| eadbc42bb0 |
8 changed files with 925 additions and 1116 deletions
30
.github/workflows/ci.yml
vendored
30
.github/workflows/ci.yml
vendored
|
|
@ -5,16 +5,13 @@ on:
|
|||
pull_request: { branches: ["0.x"] }
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install yarn
|
||||
run: npm i -g yarn
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
|
|
@ -30,28 +27,5 @@ jobs:
|
|||
- name: Type Check
|
||||
run: yarn build
|
||||
|
||||
test:
|
||||
name: Test Node ${{ matrix.node-versions }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [16, 18, 20]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install yarn
|
||||
run: npm i -g yarn
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: yarn
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
|
||||
- name: Test
|
||||
run: yarn test --coverage
|
||||
|
|
|
|||
17
CHANGELOG.md
17
CHANGELOG.md
|
|
@ -1,20 +1,3 @@
|
|||
# [v0.2.0](https://github.com/AdeAttwood/DiffCov/compare/v0.1.0...v0.2.0) (2023-06-13)
|
||||
|
||||
### Features
|
||||
|
||||
* update the coverage to exclude "normal" lines ([9192e62](https://github.com/AdeAttwood/DiffCov/commit/9192e6299547bfb18106af22363f1d10ecfa6ec6))
|
||||
|
||||
# [v0.1.0](https://github.com/AdeAttwood/DiffCov/compare/v0.0.2...v0.1.0) (2023-05-31)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency yargs to v17.7.2 ([cb7441d](https://github.com/AdeAttwood/DiffCov/commit/cb7441db1d886d39a9fba5c3dd908cf75efd8173))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add better error message when the `coverageFile` is not found ([e20a3d3](https://github.com/AdeAttwood/DiffCov/commit/e20a3d3747157a9c4830cd4454850f19aa2b2819))
|
||||
|
||||
## [v0.0.2](https://github.com/AdeAttwood/DiffCov/compare/v0.0.1...v0.0.2) (2022-10-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
|
|
|||
26
README.md
26
README.md
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Diff Cov
|
||||
|
||||
Simple CLI to print git and lcov diffs highlighted with test coverage status
|
||||
Simple CLI to print diffs highlighted with test coverage status
|
||||
|
||||

|
||||
|
||||
|
|
@ -45,8 +45,6 @@ git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/0.x
|
|||
|
||||
## Usage
|
||||
|
||||
### Git diff
|
||||
|
||||
Before you run `diff-cov` you must run your test suite with coverage and output
|
||||
a `lcov` coverage file. You must also have all your changes committed to ensure
|
||||
it's included in the output.
|
||||
|
|
@ -64,25 +62,3 @@ diff-cov --coverageFile coverage/lcov.info
|
|||
|
||||
A report is printed at the bottom and colored with a threshold of `90%`
|
||||
anything below this percentage coverage will be colored red.
|
||||
|
||||
### LCov diff
|
||||
|
||||
You can also print the coverage difference between to lcov.info files. To use
|
||||
this run your tests with coverage for a first time. After its finished you can
|
||||
copy your lcov.info file somewhere for later for example:
|
||||
|
||||
```shell
|
||||
cp ./lcov.info /tmp/lcov.info
|
||||
```
|
||||
|
||||
Then you can work on your test and run the tests once more with coverage to
|
||||
generate you a new `lcov.info` file. Then you can print the difference in
|
||||
coverage between the two files with:
|
||||
|
||||
```shell
|
||||
diff-cov --compare /tmp/lcov.info
|
||||
```
|
||||
|
||||
This can come in handy when you need to find out what a test is testing. You
|
||||
can create your base coverage file, comment out a test, run the tests again and
|
||||
diff the results.
|
||||
|
|
|
|||
24
package.json
24
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@adeattwood/diff-cov",
|
||||
"version": "0.2.0",
|
||||
"version": "0.0.2",
|
||||
"description": "Simple CLI to get test coverage on a diff",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
|
|
@ -31,17 +31,17 @@
|
|||
"yargs": "^17.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.4",
|
||||
"@types/node": "^20.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.4.1",
|
||||
"@typescript-eslint/parser": "^6.4.1",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"jest": "^29.6.4",
|
||||
"prettier": "^3.0.2",
|
||||
"ts-jest": "^29.1.1",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/node": "^18.13.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.51.0",
|
||||
"@typescript-eslint/parser": "^5.51.0",
|
||||
"eslint": "^8.33.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest": "^29.4.2",
|
||||
"prettier": "^2.8.4",
|
||||
"ts-jest": "^29.0.5",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.1.6"
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
63
src/index.ts
63
src/index.ts
|
|
@ -5,7 +5,6 @@ import { hideBin } from "yargs/helpers";
|
|||
import exec from "./exec";
|
||||
|
||||
import report from "./report";
|
||||
import lcovDiff from "./lcov-diff";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const parseDiff = require("./diff-parser");
|
||||
|
|
@ -22,16 +21,11 @@ const options: { [key: string]: Options } = {
|
|||
description: "The path to the lcov report file",
|
||||
type: "string",
|
||||
},
|
||||
compare: {
|
||||
description: "The path to the lcov report you wish to compare to the `coverage-file`",
|
||||
type: "string",
|
||||
},
|
||||
};
|
||||
|
||||
type Argv = Arguments<
|
||||
Partial<{
|
||||
coverageFile: string;
|
||||
compare?: string;
|
||||
}>
|
||||
>;
|
||||
|
||||
|
|
@ -42,46 +36,8 @@ export const validate = async (argv: Argv) => {
|
|||
`Please ensure you have run tests with coverage enabled.`
|
||||
);
|
||||
}
|
||||
|
||||
if (argv.compare && !fs.existsSync(argv.compare)) {
|
||||
return new Error(`Lcov compare file must be a valid file '${argv.compare}' provided.`);
|
||||
}
|
||||
};
|
||||
|
||||
async function isGitRepo() {
|
||||
const isGit = await exec(`git rev-parse --is-inside-work-tree`);
|
||||
return isGit.code === 0;
|
||||
}
|
||||
|
||||
async function isSaplingRepo() {
|
||||
const isSapling = await exec(`sl root`);
|
||||
return isSapling.code === 0;
|
||||
}
|
||||
|
||||
async function getDiff(): Promise<string | undefined> {
|
||||
if (await isGitRepo()) {
|
||||
const diffText = await exec(`git diff origin/HEAD...HEAD`);
|
||||
if (diffText.code > 0) {
|
||||
error("Error loading the diff\n\n" + diffText.stderr);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return diffText.stdout;
|
||||
}
|
||||
|
||||
if (await isSaplingRepo()) {
|
||||
const diffText = await exec(`sl diff -g -r '. % public()'`);
|
||||
if (diffText.code > 0) {
|
||||
error("Error loading the diff\n\n" + diffText.stderr);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return diffText.stdout;
|
||||
}
|
||||
|
||||
error("Unable to get a diff no repo was found\n");
|
||||
}
|
||||
|
||||
export const run = async (argv = process.argv) => {
|
||||
const parsed: Argv = await yargs(hideBin(argv)).options(options).argv;
|
||||
const validationError = await validate(parsed);
|
||||
|
|
@ -89,20 +45,13 @@ export const run = async (argv = process.argv) => {
|
|||
return error(validationError.message);
|
||||
}
|
||||
|
||||
const baseCoverage = await parseLcov.default(parsed.coverageFile);
|
||||
|
||||
if (parsed.compare) {
|
||||
const compareCoverage = await parseLcov.default(parsed.compare);
|
||||
return lcovDiff(baseCoverage, compareCoverage);
|
||||
const diffText = await exec(`git diff origin/HEAD...HEAD`);
|
||||
if (diffText.code > 0) {
|
||||
return error("Error loading the diff\n\n" + diffText.stderr);
|
||||
}
|
||||
|
||||
const diffText = await getDiff();
|
||||
if (!diffText) {
|
||||
return;
|
||||
}
|
||||
const diff = parseDiff.default(diffText.stdout);
|
||||
const coverage = await parseLcov.default(parsed.coverageFile);
|
||||
|
||||
const diff = parseDiff.default(diffText);
|
||||
|
||||
const { percentage } = report(diff, baseCoverage);
|
||||
process.exit(percentage > 90 ? 0 : 1);
|
||||
report(diff, coverage);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
const buildCoverageSet = (report: any) => {
|
||||
const set = new Set<string>();
|
||||
for (const coverage of report) {
|
||||
for (const detail of coverage.lines.details) {
|
||||
if (detail.hit > 0) {
|
||||
set.add(`${coverage.file}:${detail.line}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
};
|
||||
|
||||
function setDiff<T>(a: Set<T>, b: Set<T>) {
|
||||
return new Set([...a].filter((x) => !b.has(x)));
|
||||
}
|
||||
|
||||
export const lcovDiff = async (baseCoverage: any, compareCoverage: any) => {
|
||||
const baseSet = buildCoverageSet(baseCoverage);
|
||||
const compareSet = buildCoverageSet(compareCoverage);
|
||||
|
||||
const map = new Map<string, number>();
|
||||
|
||||
const added = setDiff(baseSet, compareSet);
|
||||
for (const key of added) {
|
||||
map.set(key, 1);
|
||||
}
|
||||
|
||||
const removed = setDiff(compareSet, baseSet);
|
||||
for (const key of removed) {
|
||||
map.set(key, 0);
|
||||
}
|
||||
|
||||
for (const [key, value] of [...map.entries()].sort()) {
|
||||
const color = value > 0 ? "\x1b[32m" : "\x1b[31m";
|
||||
console.log(color, key, "\x1b[0m");
|
||||
}
|
||||
};
|
||||
|
||||
export default lcovDiff;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
const getCoverageForFile = (file: any, coverage: any) => {
|
||||
for (const cov of coverage) {
|
||||
const report: { [k: number]: number } = {};
|
||||
if (cov.file.replace("./", "") === file.to) {
|
||||
if (cov.file === file.to) {
|
||||
for (const detail of cov.lines.details) {
|
||||
report[detail.line] = detail.hit;
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ interface Diff {
|
|||
}
|
||||
|
||||
export const printReport = (diff: Diff[], coverage: any) => {
|
||||
const report = { total: 0, covered: 0, percentage: 0 };
|
||||
const report = { total: 0, covered: 0 };
|
||||
|
||||
for (const file of diff) {
|
||||
const fileCoverage = getCoverageForFile(file, coverage);
|
||||
|
|
@ -77,13 +77,13 @@ export const printReport = (diff: Diff[], coverage: any) => {
|
|||
}
|
||||
}
|
||||
|
||||
report.percentage = (report.covered / report.total) * 100;
|
||||
const color = report.percentage > 90 ? "\x1b[32m" : "\x1b[31m";
|
||||
const percentage = (report.covered / report.total) * 100;
|
||||
const color = percentage > 90 ? "\x1b[32m" : "\x1b[31m";
|
||||
|
||||
console.log("");
|
||||
console.log("Total Lines: ", report.total.toString());
|
||||
console.log("Lines Covered: ", report.covered.toString());
|
||||
console.log("Coverage Percentage", color, report.percentage.toString() + "%", "\x1b[0m");
|
||||
console.log("Coverage Percentage", color, percentage.toString() + "%", "\x1b[0m");
|
||||
|
||||
return report;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue