Compare commits

...

22 commits

Author SHA1 Message Date
3e3d0b5a9d feat: sapling scm support
All checks were successful
CI / Lint (pull_request) Successful in 29s
CI / Test Node (pull_request) Successful in 32s
Conventional Tools Commitlint / Commitlint (pull_request) Successful in 5s
CI / Lint (push) Successful in 27s
CI / Test Node (push) Successful in 32s
Conventional Tools Commitlint / Commitlint (push) Successful in 5s
Now you can run this inside a sapling repo. It will automatically pick what
source control you are using by checking for the root repo.
2024-09-17 08:29:43 +01:00
7610b3bef5 ci: install yarn for actions on forgejo (#2)
All checks were successful
CI / Lint (push) Successful in 29s
CI / Test Node (push) Successful in 31s
Conventional Tools Commitlint / Commitlint (push) Successful in 5s
Summary:

The forgejo action use act under the hood. The default image does not have yarn
installed so, this is installing it.

Test Plan:

CI

Reviewed By: AdeAttwood

Pull Request: #2
Co-authored-by: Ade Attwood <adrian.attwood@marketdojo.com>
Co-committed-by: Ade Attwood <adrian.attwood@marketdojo.com>
2024-09-17 07:13:34 +00:00
renovate[bot]
0d9a76760d chore(deps): update testing packages 2024-01-23 09:02:13 +00:00
renovate[bot]
903e29b7d1 chore(deps): update eslint packages to v6.19.1 2024-01-23 08:09:18 +00:00
renovate[bot]
ff506d4679 chore(deps): lock file maintenance 2024-01-14 16:01:53 +00:00
1b3a85465f chore: update eslint prettier
This updates the following packages, they need to be updated together.

- eslint-config-prettier
- eslint-plugin-prettier
2024-01-14 15:56:21 +00:00
47f5f93b72 chore: update eslint 2024-01-14 15:48:03 +00:00
01c927e131 chore: update dependencies 2023-08-26 10:37:57 +01:00
a10d2819b3 feat: exit with non-zero status code if coverage is below 90% 2023-08-26 10:32:42 +01:00
186c5754d7 ci: run tests on multiple node versions 2023-08-16 19:56:50 +01:00
1d464addfd chore: update dev dependencies 2023-08-16 19:56:50 +01:00
c8ce7f37bd feat: add diffing of lcov files 2023-08-16 19:43:39 +01:00
renovate[bot]
b1c14afd65 chore(deps): lock file maintenance 2023-06-25 05:24:47 -07:00
renovate[bot]
2781d8a124 chore(deps): update eslint packages 2023-06-25 05:24:18 -07:00
renovate[bot]
15724af2ad chore(deps): update dependency @types/node to v18.16.18 2023-06-15 23:00:58 -07:00
github-actions[bot]
46fcffb95c chore(release): v0.2.0 [skip ci] 2023-06-13 13:22:29 +00:00
renovate[bot]
da6a7a1967 chore(deps): update dependency typescript to v5.1.3 2023-06-13 06:21:05 -07:00
renovate[bot]
372b607184 chore(deps): update eslint packages 2023-06-13 06:20:57 -07:00
renovate[bot]
b23715bb85 chore(deps): update dependency @types/jest to v29.5.2 2023-06-13 06:20:41 -07:00
renovate[bot]
b6ce8ea652 chore(deps): update dependency @types/node to v18.16.17 2023-06-13 06:20:28 -07:00
9192e62995 feat: update the coverage to exclude "normal" lines
This will now exclude lines that are not added or edited in the diff.
They are lines that are included in the diff context but will still
count towards the coverage percentage.

You now get a more accurate coverage percentage from what you have
edited in the diff.
2023-06-13 06:20:15 -07:00
github-actions[bot]
797f97e867 chore(release): v0.1.0 [skip ci] 2023-05-31 15:40:44 +00:00
8 changed files with 1123 additions and 925 deletions

View file

@ -5,13 +5,16 @@ on:
pull_request: { branches: ["0.x"] } pull_request: { branches: ["0.x"] }
jobs: jobs:
test: lint:
name: Test name: Lint
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Install yarn
run: npm i -g yarn
- name: Set up Node - name: Set up Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
@ -27,5 +30,28 @@ jobs:
- name: Type Check - name: Type Check
run: yarn build 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 - name: Test
run: yarn test --coverage run: yarn test --coverage

View file

@ -1,3 +1,20 @@
# [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) ## [v0.0.2](https://github.com/AdeAttwood/DiffCov/compare/v0.0.1...v0.0.2) (2022-10-24)
### Bug Fixes ### Bug Fixes

View file

@ -2,7 +2,7 @@
# Diff Cov # Diff Cov
Simple CLI to print diffs highlighted with test coverage status Simple CLI to print git and lcov diffs highlighted with test coverage status
![Example Output](assets/example-output.png) ![Example Output](assets/example-output.png)
@ -45,6 +45,8 @@ git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/0.x
## Usage ## Usage
### Git diff
Before you run `diff-cov` you must run your test suite with coverage and output 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 a `lcov` coverage file. You must also have all your changes committed to ensure
it's included in the output. it's included in the output.
@ -62,3 +64,25 @@ diff-cov --coverageFile coverage/lcov.info
A report is printed at the bottom and colored with a threshold of `90%` A report is printed at the bottom and colored with a threshold of `90%`
anything below this percentage coverage will be colored red. 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.

View file

@ -1,6 +1,6 @@
{ {
"name": "@adeattwood/diff-cov", "name": "@adeattwood/diff-cov",
"version": "0.0.2", "version": "0.2.0",
"description": "Simple CLI to get test coverage on a diff", "description": "Simple CLI to get test coverage on a diff",
"main": "./lib/index.js", "main": "./lib/index.js",
"types": "./lib/index.d.ts", "types": "./lib/index.d.ts",
@ -31,17 +31,17 @@
"yargs": "^17.6.2" "yargs": "^17.6.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.4.0", "@types/jest": "^29.5.4",
"@types/node": "^18.13.0", "@types/node": "^20.5.0",
"@typescript-eslint/eslint-plugin": "^5.51.0", "@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^5.51.0", "@typescript-eslint/parser": "^6.4.1",
"eslint": "^8.33.0", "eslint": "^8.56.0",
"eslint-config-prettier": "^8.6.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^5.1.3",
"jest": "^29.4.2", "jest": "^29.6.4",
"prettier": "^2.8.4", "prettier": "^3.0.2",
"ts-jest": "^29.0.5", "ts-jest": "^29.1.1",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"typescript": "^5.0.0" "typescript": "^5.1.6"
} }
} }

View file

@ -5,6 +5,7 @@ import { hideBin } from "yargs/helpers";
import exec from "./exec"; import exec from "./exec";
import report from "./report"; import report from "./report";
import lcovDiff from "./lcov-diff";
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
const parseDiff = require("./diff-parser"); const parseDiff = require("./diff-parser");
@ -21,11 +22,16 @@ const options: { [key: string]: Options } = {
description: "The path to the lcov report file", description: "The path to the lcov report file",
type: "string", type: "string",
}, },
compare: {
description: "The path to the lcov report you wish to compare to the `coverage-file`",
type: "string",
},
}; };
type Argv = Arguments< type Argv = Arguments<
Partial<{ Partial<{
coverageFile: string; coverageFile: string;
compare?: string;
}> }>
>; >;
@ -36,8 +42,46 @@ export const validate = async (argv: Argv) => {
`Please ensure you have run tests with coverage enabled.` `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) => { export const run = async (argv = process.argv) => {
const parsed: Argv = await yargs(hideBin(argv)).options(options).argv; const parsed: Argv = await yargs(hideBin(argv)).options(options).argv;
const validationError = await validate(parsed); const validationError = await validate(parsed);
@ -45,13 +89,20 @@ export const run = async (argv = process.argv) => {
return error(validationError.message); return error(validationError.message);
} }
const diffText = await exec(`git diff origin/HEAD...HEAD`); const baseCoverage = await parseLcov.default(parsed.coverageFile);
if (diffText.code > 0) {
return error("Error loading the diff\n\n" + diffText.stderr); if (parsed.compare) {
const compareCoverage = await parseLcov.default(parsed.compare);
return lcovDiff(baseCoverage, compareCoverage);
} }
const diff = parseDiff.default(diffText.stdout); const diffText = await getDiff();
const coverage = await parseLcov.default(parsed.coverageFile); if (!diffText) {
return;
}
report(diff, coverage); const diff = parseDiff.default(diffText);
const { percentage } = report(diff, baseCoverage);
process.exit(percentage > 90 ? 0 : 1);
}; };

40
src/lcov-diff.ts Normal file
View file

@ -0,0 +1,40 @@
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;

View file

@ -1,7 +1,7 @@
const getCoverageForFile = (file: any, coverage: any) => { const getCoverageForFile = (file: any, coverage: any) => {
for (const cov of coverage) { for (const cov of coverage) {
const report: { [k: number]: number } = {}; const report: { [k: number]: number } = {};
if (cov.file === file.to) { if (cov.file.replace("./", "") === file.to) {
for (const detail of cov.lines.details) { for (const detail of cov.lines.details) {
report[detail.line] = detail.hit; report[detail.line] = detail.hit;
} }
@ -35,7 +35,7 @@ interface Diff {
} }
export const printReport = (diff: Diff[], coverage: any) => { export const printReport = (diff: Diff[], coverage: any) => {
const report = { total: 0, covered: 0 }; const report = { total: 0, covered: 0, percentage: 0 };
for (const file of diff) { for (const file of diff) {
const fileCoverage = getCoverageForFile(file, coverage); const fileCoverage = getCoverageForFile(file, coverage);
@ -54,7 +54,14 @@ export const printReport = (diff: Diff[], coverage: any) => {
if (change.type === "del") { if (change.type === "del") {
continue; continue;
} }
const line = change.ln || change.ln2; const line = change.ln || change.ln2;
if (change.type === "normal") {
console.log(line.toString().padStart(4, " "), "\x1b[0m", change.content.substring(1), "\x1b[0m");
continue;
}
let color = "\x1b[0m"; let color = "\x1b[0m";
if (typeof fileCoverage[line] !== "undefined") { if (typeof fileCoverage[line] !== "undefined") {
color = fileCoverage[line] > 0 ? "\x1b[32m" : "\x1b[31m"; color = fileCoverage[line] > 0 ? "\x1b[32m" : "\x1b[31m";
@ -70,13 +77,13 @@ export const printReport = (diff: Diff[], coverage: any) => {
} }
} }
const percentage = (report.covered / report.total) * 100; report.percentage = (report.covered / report.total) * 100;
const color = percentage > 90 ? "\x1b[32m" : "\x1b[31m"; const color = report.percentage > 90 ? "\x1b[32m" : "\x1b[31m";
console.log(""); console.log("");
console.log("Total Lines: ", report.total.toString()); console.log("Total Lines: ", report.total.toString());
console.log("Lines Covered: ", report.covered.toString()); console.log("Lines Covered: ", report.covered.toString());
console.log("Coverage Percentage", color, percentage.toString() + "%", "\x1b[0m"); console.log("Coverage Percentage", color, report.percentage.toString() + "%", "\x1b[0m");
return report; return report;
}; };

1831
yarn.lock

File diff suppressed because it is too large Load diff