Skip to content

Instantly share code, notes, and snippets.

@davidgilbertson
Created June 18, 2026 00:12
Show Gist options
  • Select an option

  • Save davidgilbertson/0e16b3e9571ed2b7d34feb4e14106f80 to your computer and use it in GitHub Desktop.

Select an option

Save davidgilbertson/0e16b3e9571ed2b7d34feb4e14106f80 to your computer and use it in GitHub Desktop.
import { writeFile } from "node:fs/promises";
import type { TestModule } from "vitest/node";
import type { Reporter } from "vitest/reporters";
const outputPath = "APP_BEHAVIOR.md";
export default class AppBehaviorReporter implements Reporter {
async onTestRunEnd(testModules: readonly TestModule[]) {
// The doc is committed from local runs, so there's no reason for a build server to regenerate it.
if (process.env.CI) return;
const rootGroup: SummaryGroup = { children: new Map(), tests: [] };
for (const testModule of testModules) {
for (const testCase of testModule.children.allTests()) {
const parts = testCase.fullName.split(" > ");
// Skip top-level tests that aren't inside a describe block.
if (parts.length === 1) continue;
addTest(rootGroup, parts);
}
}
const lines = ["<!-- Autogenerated by appBehaviorReporter.ts -->", "# App Behavior", ""];
appendGroupLines(lines, rootGroup, 0);
await writeFile(outputPath, `${lines.join("\n").trimEnd()}\n`);
}
}
type SummaryGroup = {
children: Map<string, SummaryGroup>;
tests: string[];
};
function addTest(group: SummaryGroup, parts: string[]) {
if (parts.length === 1) {
group.tests.push(parts[0]);
return;
}
const [describeName, ...remainingParts] = parts;
const childGroup = group.children.get(describeName) ?? { children: new Map(), tests: [] };
group.children.set(describeName, childGroup);
addTest(childGroup, remainingParts);
}
function appendGroupLines(lines: string[], group: SummaryGroup, depth: number) {
const indent = " ".repeat(depth);
for (const test of group.tests) {
lines.push(`${indent}- ${test}`);
}
for (const [name, childGroup] of group.children) {
lines.push(`${indent}- ${name}`);
appendGroupLines(lines, childGroup, depth + 1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment