Files
openclaw/extensions/qa-lab/src/suite-summary.ts
Josh Avant d5b326523f qa-lab: make live lanes CI-ready for v1 E2E automation (#69122)
* qa-lab: harden CI defaults and failure semantics for live lanes

* qa-lab: add unit tests for suite progress logging defaults

* qa-lab: cover malformed multipass summary edge cases

* qa-lab: share suite summary failure counting helper

* qa-lab: test allow-failures parse wiring and sanitize progress ids

* fix: note qa CI live-lane defaults in changelog (#69122) (thanks @joshavant)
2026-04-19 21:13:27 -05:00

65 lines
1.6 KiB
TypeScript

import type { QaProviderMode } from "./model-selection.js";
export type QaSuiteSummaryScenario = {
name: string;
status: "pass" | "fail";
steps: unknown[];
details?: string;
};
export type QaSuiteSummaryJson = {
scenarios: QaSuiteSummaryScenario[];
counts: {
total: number;
passed: number;
failed: number;
};
run: {
startedAt: string;
finishedAt: string;
providerMode: QaProviderMode;
primaryModel: string;
primaryProvider: string | null;
primaryModelName: string | null;
alternateModel: string;
alternateProvider: string | null;
alternateModelName: string | null;
fastMode: boolean;
concurrency: number;
scenarioIds: string[] | null;
};
};
type QaSuiteScenarioStatus = Pick<QaSuiteSummaryScenario, "status">;
export function countQaSuiteFailedScenarios(
scenarios: ReadonlyArray<QaSuiteScenarioStatus>,
): number {
let failed = 0;
for (const scenario of scenarios) {
if (scenario.status === "fail") {
failed += 1;
}
}
return failed;
}
export function readQaSuiteFailedScenarioCountFromSummary(summary: unknown): number | null {
if (!summary || typeof summary !== "object") {
return null;
}
const payload = summary as {
counts?: {
failed?: unknown;
};
scenarios?: Array<QaSuiteScenarioStatus>;
};
if (typeof payload.counts?.failed === "number" && Number.isFinite(payload.counts.failed)) {
return Math.max(0, Math.floor(payload.counts.failed));
}
if (Array.isArray(payload.scenarios)) {
return countQaSuiteFailedScenarios(payload.scenarios);
}
return null;
}