extract test output parsing
Parsing no longer depends on ui widget
This commit is contained in:
parent
093c79009d
commit
ed147f6470
@ -1,5 +1,5 @@
|
||||
import {type ExtensionAPI, isBashToolResult} from "@earendil-works/pi-coding-agent";
|
||||
import {isTestCommand} from "./parsing/typescript-command-output";
|
||||
import {isTestCommand, parseTestOutput} from "./parsing/typescript-command-output";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
export default function testStatusExtension(pi: ExtensionAPI) {
|
||||
@ -13,30 +13,15 @@ export default function testStatusExtension(pi: ExtensionAPI) {
|
||||
const output = textContent?.text ?? "";
|
||||
const theme = ctx.ui.theme;
|
||||
|
||||
// Detect pass/fail from vitest summary output
|
||||
const testsPassed =
|
||||
/Tests\s+.+passed/.test(output) && !/Tests\s+.+failed/.test(output);
|
||||
const testsFailed =
|
||||
/Tests\s+.+failed/.test(output) || event.isError;
|
||||
|
||||
if (testsPassed) {
|
||||
// Extract summary line for inline detail (e.g., "1 passed (242ms)")
|
||||
const summaryLine = output
|
||||
.split("\n")
|
||||
.find((line: string) => /Test Files\s+.+passed/.test(line));
|
||||
const summary = summaryLine?.trim() ?? "All tests passed";
|
||||
const testResult = parseTestOutput(output);
|
||||
|
||||
if (testResult.status === "Success") {
|
||||
ctx.ui.setWidget("test-status", [
|
||||
`${theme.fg("success", "●")} ${theme.fg("text", summary)}`,
|
||||
`${theme.fg("success", "●")} ${theme.fg("text", testResult.summary)}`,
|
||||
]);
|
||||
} else if (testsFailed) {
|
||||
const summaryLine = output
|
||||
.split("\n")
|
||||
.find((line: string) => /Tests\s+.+failed/.test(line));
|
||||
const summary = summaryLine?.trim() ?? "Tests failed";
|
||||
|
||||
} else if (testResult.status === "Error" || event.isError) {
|
||||
ctx.ui.setWidget("test-status", [
|
||||
`${theme.fg("error", "●")} ${theme.fg("text", summary)}`,
|
||||
`${theme.fg("error", "●")} ${theme.fg("text", testResult.summary)}`,
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { parseTestOutput } from "../typescript-command-output";
|
||||
|
||||
describe("parseTestOutput", () => {
|
||||
it("parses a passing vitest run", () => {
|
||||
const output = `
|
||||
RAN v3.2.6 /path
|
||||
|
||||
✓ src/greet.test.ts (1 test) 1ms
|
||||
|
||||
Test Files 1 passed (1)
|
||||
Tests 1 passed (1)
|
||||
Start at 11:12:54
|
||||
Duration 308ms
|
||||
`;
|
||||
|
||||
const result = parseTestOutput(output);
|
||||
|
||||
expect(result.status).toBe("Success");
|
||||
expect(result.summary).toContain("1 passed");
|
||||
});
|
||||
|
||||
it("parses a failing vitest run", () => {
|
||||
const output = `
|
||||
RAN v3.2.6 /path
|
||||
|
||||
✓ src/greet.test.ts (1 test) 1ms
|
||||
✗ src/foo.test.ts (1 test) 2ms
|
||||
|
||||
Test Files 1 failed (1)
|
||||
Tests 1 failed (1)
|
||||
Start at 11:15:00
|
||||
Duration 400ms
|
||||
`;
|
||||
|
||||
const result = parseTestOutput(output);
|
||||
|
||||
expect(result.status).toBe("Error");
|
||||
expect(result.summary).toContain("1 failed");
|
||||
});
|
||||
|
||||
it("returns Error and a fallback summary for unrecognised output", () => {
|
||||
const result = parseTestOutput("some random output");
|
||||
|
||||
expect(result.status).toBe("Error");
|
||||
expect(result.summary).toBe("Tests failed");
|
||||
});
|
||||
|
||||
it("returns Success with a fallback summary when passed but no detail line", () => {
|
||||
const output = `
|
||||
✓ src/greet.test.ts (1 test) 1ms
|
||||
Tests 1 passed (242ms)
|
||||
`;
|
||||
|
||||
const result = parseTestOutput(output);
|
||||
|
||||
expect(result.status).toBe("Success");
|
||||
expect(result.summary).toBe("All tests passed");
|
||||
});
|
||||
});
|
||||
@ -1,3 +1,25 @@
|
||||
export type TestResult =
|
||||
| { status: "Success"; summary: string }
|
||||
| { status: "Error"; summary: string };
|
||||
|
||||
export const isTestCommand = (command: string) => {
|
||||
return command.includes("npm test") || command.includes("vitest")
|
||||
}
|
||||
return command.includes("npm test") || command.includes("vitest");
|
||||
};
|
||||
|
||||
export function parseTestOutput(output: string): TestResult {
|
||||
const testsPassed =
|
||||
/Tests\s+.+passed/.test(output) && !/Tests\s+.+failed/.test(output);
|
||||
const testsFailed = /Tests\s+.+failed/.test(output);
|
||||
|
||||
if (testsPassed && !testsFailed) {
|
||||
const line = output
|
||||
.split("\n")
|
||||
.find((l) => /Test Files\s+.+passed/.test(l));
|
||||
return { status: "Success", summary: line?.trim() ?? "All tests passed" };
|
||||
}
|
||||
|
||||
const line = output
|
||||
.split("\n")
|
||||
.find((l) => /Tests\s+.+failed/.test(l));
|
||||
return { status: "Error", summary: line?.trim() ?? "Tests failed" };
|
||||
}
|
||||
|
||||
10
vitest.config.ts
Normal file
10
vitest.config.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
include: [
|
||||
"src/**/*.test.ts",
|
||||
"pi-test-status/extensions/**/*.test.ts",
|
||||
],
|
||||
},
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user