From 772e320a8df45ffed904a72bc5ef3161bd28053f Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Fri, 24 Jul 2026 15:02:44 +0800 Subject: [PATCH] refactor(qa): remove duplicate report renderer (#113258) --- extensions/qa-lab/src/report.test.ts | 31 ++++++++ src/plugin-sdk/qa-runtime.test.ts | 29 -------- src/plugin-sdk/qa-runtime.ts | 104 --------------------------- 3 files changed, 31 insertions(+), 133 deletions(-) create mode 100644 extensions/qa-lab/src/report.test.ts diff --git a/extensions/qa-lab/src/report.test.ts b/extensions/qa-lab/src/report.test.ts new file mode 100644 index 000000000000..44986fc1e534 --- /dev/null +++ b/extensions/qa-lab/src/report.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, it } from "vitest"; +import { renderQaMarkdownReport } from "./report.js"; + +describe("renderQaMarkdownReport", () => { + it("renders checks, scenarios, timeline, and multiline details", () => { + const report = renderQaMarkdownReport({ + title: "QA Report", + startedAt: new Date("2026-01-01T00:00:00.000Z"), + finishedAt: new Date("2026-01-01T00:00:02.000Z"), + checks: [{ name: "preflight", status: "pass" }], + scenarios: [ + { + name: "transport reply", + status: "fail", + details: "line one\nline two", + steps: [{ name: "send", status: "pass", details: "ok" }], + }, + ], + timeline: ["sent request"], + notes: ["kept artifacts"], + }); + + expect(report).toContain("# QA Report"); + expect(report).toContain("- Duration ms: 2000"); + expect(report).toContain("- Passed: 1"); + expect(report).toContain("- Failed: 1"); + expect(report).toContain("```text\nline one\nline two\n```"); + expect(report).toContain("- [x] send"); + expect(report).toContain("## Timeline"); + }); +}); diff --git a/src/plugin-sdk/qa-runtime.test.ts b/src/plugin-sdk/qa-runtime.test.ts index f6af24ae3100..dcf8bccdd9c9 100644 --- a/src/plugin-sdk/qa-runtime.test.ts +++ b/src/plugin-sdk/qa-runtime.test.ts @@ -118,35 +118,6 @@ describe("plugin-sdk qa-runtime", () => { expect(module.isQaRuntimeAvailable()).toBe(false); }); - it("renders shared QA markdown reports with multiline details", async () => { - const module = await import("./qa-runtime.js"); - - const report = module.renderQaMarkdownReport({ - title: "QA Report", - startedAt: new Date("2026-01-01T00:00:00.000Z"), - finishedAt: new Date("2026-01-01T00:00:02.000Z"), - checks: [{ name: "preflight", status: "pass" }], - scenarios: [ - { - name: "transport reply", - status: "fail", - details: "line one\nline two", - steps: [{ name: "send", status: "pass", details: "ok" }], - }, - ], - timeline: ["sent request"], - notes: ["kept artifacts"], - }); - - expect(report).toContain("# QA Report"); - expect(report).toContain("- Duration ms: 2000"); - expect(report).toContain("- Passed: 1"); - expect(report).toContain("- Failed: 1"); - expect(report).toContain("```text\nline one\nline two\n```"); - expect(report).toContain("- [x] send"); - expect(report).toContain("## Timeline"); - }); - it("registers shared live transport QA CLI options", async () => { const module = await import("./qa-runtime.js"); const run = vi.fn(async () => {}); diff --git a/src/plugin-sdk/qa-runtime.ts b/src/plugin-sdk/qa-runtime.ts index fb2efd55eeba..91852e4fdf04 100644 --- a/src/plugin-sdk/qa-runtime.ts +++ b/src/plugin-sdk/qa-runtime.ts @@ -219,21 +219,6 @@ export function createLiveTransportQaCliRegistration( }; } -/** One top-level check row in a rendered QA markdown report. */ -export type QaReportCheck = { - name: string; - status: "pass" | "fail" | "skip"; - details?: string; -}; - -/** One scenario section in a rendered QA markdown report. */ -export type QaReportScenario = { - name: string; - status: "pass" | "fail" | "skip"; - details?: string; - steps?: QaReportCheck[]; -}; - /** Docker command runner abstraction used by QA Docker helpers and tests. */ export type QaDockerRunCommand = ( command: string, @@ -254,95 +239,6 @@ export type QaDockerFetchLike = ( const DEFAULT_QA_DOCKER_COMMAND_TIMEOUT_MS = 120_000; const DEFAULT_QA_DOCKER_HEALTH_REQUEST_TIMEOUT_MS = 2_000; -function pushQaReportDetailsBlock(lines: string[], label: string, details: string, indent = "") { - if (!details.includes("\n")) { - lines.push(`${indent}- ${label}: ${details}`); - return; - } - lines.push(`${indent}- ${label}:`); - lines.push("", "```text", details, "```"); -} - -/** Render checks, scenarios, timeline, and notes into the standard QA markdown report format. */ -export function renderQaMarkdownReport(params: { - title: string; - startedAt: Date; - finishedAt: Date; - checks?: QaReportCheck[]; - scenarios?: QaReportScenario[]; - timeline?: string[]; - notes?: string[]; -}) { - const checks = params.checks ?? []; - const scenarios = params.scenarios ?? []; - const passCount = - checks.filter((check) => check.status === "pass").length + - scenarios.filter((scenario) => scenario.status === "pass").length; - const failCount = - checks.filter((check) => check.status === "fail").length + - scenarios.filter((scenario) => scenario.status === "fail").length; - - const lines = [ - `# ${params.title}`, - "", - `- Started: ${params.startedAt.toISOString()}`, - `- Finished: ${params.finishedAt.toISOString()}`, - `- Duration ms: ${params.finishedAt.getTime() - params.startedAt.getTime()}`, - `- Passed: ${passCount}`, - `- Failed: ${failCount}`, - "", - ]; - - if (checks.length > 0) { - lines.push("## Checks", ""); - for (const check of checks) { - lines.push(`- [${check.status === "pass" ? "x" : " "}] ${check.name}`); - if (check.details) { - pushQaReportDetailsBlock(lines, "Details", check.details, " "); - } - } - } - - if (scenarios.length > 0) { - lines.push("", "## Scenarios", ""); - for (const scenario of scenarios) { - lines.push(`### ${scenario.name}`); - lines.push(""); - lines.push(`- Status: ${scenario.status}`); - if (scenario.details) { - pushQaReportDetailsBlock(lines, "Details", scenario.details); - } - if (scenario.steps?.length) { - lines.push("- Steps:"); - for (const step of scenario.steps) { - lines.push(` - [${step.status === "pass" ? "x" : " "}] ${step.name}`); - if (step.details) { - pushQaReportDetailsBlock(lines, "Details", step.details, " "); - } - } - } - lines.push(""); - } - } - - if (params.timeline && params.timeline.length > 0) { - lines.push("## Timeline", ""); - for (const item of params.timeline) { - lines.push(`- ${item}`); - } - } - - if (params.notes && params.notes.length > 0) { - lines.push("", "## Notes", ""); - for (const note of params.notes) { - lines.push(`- ${note}`); - } - } - - lines.push(""); - return lines.join("\n"); -} - /** Append a formatted live-lane issue while preserving the caller-owned issue list. */ export function appendQaLiveLaneIssue(issues: string[], label: string, error: unknown) { issues.push(`${label}: ${formatErrorMessage(error)}`);