Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,13 @@ jobs:
with:
go-version-file: go.mod
- run: go tool task ci
# The coverage task test wrote, even when a test failed: the summary says so when there is none.
- if: always()
run: go tool task coverage:summary
- if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: coverage-web
path: coverage
retention-days: 7
if-no-files-found: ignore
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
/.vscode-test/
/*.vsix
/.wt/
/coverage/
7 changes: 6 additions & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ tasks:
- pnpm typecheck

test:
desc: The unit tests - Vitest, with vscode replaced by test/mocks/vscode.ts.
desc: The unit tests - Vitest, with vscode replaced by test/mocks/vscode.ts, and coverage held to the floor in vitest.config.ts.
cmds:
- pnpm test

coverage:summary:
desc: The coverage task test left in coverage/, as the job's summary (hack/coverage-summary.mjs); the HTML is coverage/index.html.
cmds:
- node hack/coverage-summary.mjs

test:e2e:
desc: >-
The Spinbox resolver against spin's e2e stack and the real spin CLI (test/e2e/). Bring the
Expand Down
24 changes: 24 additions & 0 deletions hack/coverage-summary.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// The unit tests' coverage, from what `vitest run --coverage` writes into coverage/, as the job's
// summary (stdout outside a workflow). The HTML beside it is the coverage-web artifact.
import { appendFileSync, existsSync, readFileSync } from 'node:fs';

const file = 'coverage/coverage-summary.json';
const write = (text) => {
const summary = process.env.GITHUB_STEP_SUMMARY;
if (summary) {
appendFileSync(summary, `${text}\n`);
} else {
console.log(text);
}
};

if (!existsSync(file)) {
write(`${file} was not produced; the tests may have failed before coverage ran.`);
} else {
const { total } = JSON.parse(readFileSync(file, 'utf8'));
const rows = ['statements', 'branches', 'functions', 'lines'].map((key) => {
const { covered, total: all, pct } = total[key];
return `| ${key} | ${covered} | ${all} | ${pct}% |`;
});
write(['## Unit test coverage', '', '| Metric | Covered | Total | % |', '|---|---:|---:|---:|', ...rows].join('\n'));
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
"lint": "biome check --error-on-warnings .",
"lint:fix": "biome check --write --error-on-warnings .",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test": "vitest run --coverage",
"test:e2e": "vitest run --config vitest.e2e.config.mts",
"package": "vsce package --no-dependencies --out spinbox-remote.vsix"
},
"devDependencies": {
"@biomejs/biome": "2.6.3",
"@types/node": "22.20.5",
"@types/vscode": "1.146.0",
"@vitest/coverage-v8": "5.0.5",
"@vscode/vsce": "4.1.0",
"esbuild": "0.28.2",
"typescript": "7.0.2",
Expand Down
108 changes: 106 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ export default defineConfig({
// test:e2e's, which need spin's e2e stack.
exclude: ['test/e2e/**'],
environment: 'node',
coverage: {
provider: 'v8',
// Every file under src/, so one no unit test imports counts as uncovered rather than
// absent.
include: ['src/**'],
// json-summary is what CI's job summary reads (hack/coverage-summary.mjs);
// reportOnFailure keeps a red suite from leaving it nothing to read.
reporter: ['text', 'json-summary', 'html'],
reportOnFailure: true,
// A floor below the 92.0% of statements measured on 2026-11-14. Raise it when the
// number has moved up and stayed; never lower it to let a change through.
thresholds: { statements: 90 },
},
},
resolve: {
alias: {
Expand Down
Loading