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,6 +42,16 @@ 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

integration:
name: Integration
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ dist-test/
build/
bin/
.wt/
coverage/
7 changes: 6 additions & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,16 @@ tasks:
- pnpm typecheck

test:
desc: The unit tests - Vitest, against the fake spin in test/fake-spin/, and hack/'s Go.
desc: The unit tests - Vitest, against the fake spin in test/fake-spin/, with coverage held to the floor in vitest.config.mts - and hack/'s Go.
cmds:
- pnpm test
- go test ./hack/...

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:cli:
desc: The extension's reader against the real spin CLI of the pinned release (test/cli/), pulled and checked by package:spin - minutes, so it is not in task test.
cmds:
Expand Down
29 changes: 29 additions & 0 deletions hack/coverage-summary.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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 @@ -210,7 +210,7 @@
"lint": "biome check .",
"lint:fix": "biome check --write .",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test": "vitest run --coverage",
"test:cli": "vitest run --config vitest.cli.config.mts",
"test:integration": "node esbuild.mjs --tests && node test/integration/run.mjs",
"package": "vsce package --no-dependencies --out spinbox.vsix"
Expand All @@ -219,6 +219,7 @@
"@biomejs/biome": "2.6.3",
"@types/node": "22.20.5",
"@types/vscode": "1.146.0",
"@vitest/coverage-v8": "5.0.5",
"@vscode/test-electron": "3.1.0",
"@vscode/vsce": "4.1.0",
"esbuild": "0.28.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.

12 changes: 12 additions & 0 deletions vitest.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,17 @@ import { defineConfig } from "vitest/config"
export default defineConfig({
test: {
include: ["test/unit/**/*.test.ts"],
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 87.1% 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: 85 },
},
},
})
Loading