// Flow's test reports in VS Code's Testing view (spec §9.2): the newest // report on each repository's current bookmark, its suites and cases with // their results, messages and output. Nothing runs here: running a test // loads the hub's latest results. import * as vscode from "vscode"; import { HubAuth } from "./auth"; import { caseId, caseOutcome, casesBySuite, duration } from "./flowview"; import type { HubRepo } from "./proposals"; export class HubTests implements vscode.Disposable { private readonly controller: vscode.TestController; constructor( private readonly auth: HubAuth, private readonly repos: () => Promise, ) { this.controller = vscode.tests.createTestController("oxygenhub", "OxygenFlow test reports"); this.controller.refreshHandler = () => this.load(); this.controller.createRunProfile("Load the hub's latest results", vscode.TestRunProfileKind.Run, () => this.load(), true); } dispose(): void { this.controller.dispose(); } /** Fetch each repository's newest test report and show its results. */ async load(): Promise { const repos = await this.repos().catch(() => [] as HubRepo[]); const roots: vscode.TestItem[] = []; const results: [vscode.TestItem, string, string, string, number][] = []; for (const repo of repos) { const client = this.auth.clientFor(repo.base); const bookmark = repo.handle.currentBookmark ?? undefined; const [newest] = await client.testReports(repo.owner, repo.name, bookmark, 1).catch(() => []); if (!newest) { continue; } const detail = await client.testReport(repo.owner, repo.name, newest.id).catch(() => undefined); if (!detail) { continue; } const key = `${repo.base}/${repo.owner}/${repo.name}`; const r = detail.report; const root = this.controller.createTestItem(key, `${repo.owner}/${repo.name}`); root.description = `${r.passed}/${r.tests} passed${r.failed ? ` · ${r.failed} failed` : ""} · run #${r.run} ${r.job} on ${r.bookmark}`; for (const [suite, cases] of casesBySuite(detail.cases)) { const s = this.controller.createTestItem(`${key}::${suite}`, suite); for (const c of cases) { const item = this.controller.createTestItem(caseId(key, c), c.name); item.description = c.classname && c.classname !== suite ? c.classname : undefined; s.children.add(item); results.push([item, c.status, c.message, c.output, c.time_ms]); } root.children.add(s); } roots.push(root); } this.controller.items.replace(roots); const run = this.controller.createTestRun(new vscode.TestRunRequest(), "OxygenFlow", false); for (const [item, status, message, output, ms] of results) { const outcome = caseOutcome(status); if (outcome === "passed") { run.passed(item, ms); } else if (outcome === "skipped") { run.skipped(item); } else { const m = new vscode.TestMessage(message || `${status} after ${duration(ms)}`); if (output) { m.actualOutput = output; } (outcome === "failed" ? run.failed : run.errored).call(run, item, m, ms); } } run.end(); } }