Compare commits

...

15 commits
v0.2.0 ... 0.x

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
7 changed files with 1099 additions and 925 deletions

View file

@ -5,13 +5,16 @@ on:
pull_request: { branches: ["0.x"] }
jobs:
test:
name: Test
lint:
name: Lint
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:
@ -27,5 +30,28 @@ 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

View file

@ -2,7 +2,7 @@
# 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)
@ -45,6 +45,8 @@ 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.
@ -62,3 +64,25 @@ 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.

View file

@ -31,17 +31,17 @@
"yargs": "^17.6.2"
},
"devDependencies": {
"@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",
"@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",
"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 report from "./report";
import lcovDiff from "./lcov-diff";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const parseDiff = require("./diff-parser");
@ -21,11 +22,16 @@ 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;
}>
>;
@ -36,8 +42,46 @@ 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);
@ -45,13 +89,20 @@ export const run = async (argv = process.argv) => {
return error(validationError.message);
}
const diffText = await exec(`git diff origin/HEAD...HEAD`);
if (diffText.code > 0) {
return error("Error loading the diff\n\n" + diffText.stderr);
const baseCoverage = await parseLcov.default(parsed.coverageFile);
if (parsed.compare) {
const compareCoverage = await parseLcov.default(parsed.compare);
return lcovDiff(baseCoverage, compareCoverage);
}
const diff = parseDiff.default(diffText.stdout);
const coverage = await parseLcov.default(parsed.coverageFile);
const diffText = await getDiff();
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) => {
for (const cov of coverage) {
const report: { [k: number]: number } = {};
if (cov.file === file.to) {
if (cov.file.replace("./", "") === 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 };
const report = { total: 0, covered: 0, percentage: 0 };
for (const file of diff) {
const fileCoverage = getCoverageForFile(file, coverage);
@ -77,13 +77,13 @@ export const printReport = (diff: Diff[], coverage: any) => {
}
}
const percentage = (report.covered / report.total) * 100;
const color = percentage > 90 ? "\x1b[32m" : "\x1b[31m";
report.percentage = (report.covered / report.total) * 100;
const color = report.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, percentage.toString() + "%", "\x1b[0m");
console.log("Coverage Percentage", color, report.percentage.toString() + "%", "\x1b[0m");
return report;
};

1831
yarn.lock

File diff suppressed because it is too large Load diff