






















1-// Maturity docs renderer tests cover evidence-backed generated-doc checks.
21import { spawnSync } from "node:child_process";
2+// Maturity docs renderer tests cover evidence-backed generated-doc checks.
3+import fs from "node:fs";
34import path from "node:path";
45import { afterEach, describe, expect, it } from "vitest";
56import { createTempDirTracker } from "../helpers/temp-dir.js";
@@ -22,6 +23,56 @@ function runCli(...args: string[]) {
2223);
2324}
242526+function writeQaEvidence(params: {
27+dir: string;
28+entries: Array<{ id: string; status: "pass" | "fail" | "blocked" | "skipped" }>;
29+}) {
30+fs.mkdirSync(params.dir, { recursive: true });
31+fs.writeFileSync(
32+path.join(params.dir, "qa-evidence.json"),
33+`${JSON.stringify(
34+ {
35+ kind: "openclaw.qa.evidence-summary",
36+ schemaVersion: 2,
37+ generatedAt: "2026-06-23T00:00:00.000Z",
38+ evidenceMode: "full",
39+ profile: "all",
40+ entries: params.entries.map((entry) => ({
41+ test: {
42+ kind: "qa-scenario",
43+ id: entry.id,
44+ title: entry.id,
45+ source: { path: `qa/scenarios/${entry.id}.yaml` },
46+ },
47+ coverage: [{ id: "tools.evidence", role: "primary" }],
48+ result: { status: entry.status },
49+ })),
50+ scorecard: {
51+ filters: { surface: null, category: null },
52+ run: { evidenceEntryCount: params.entries.length },
53+ categories: {
54+ total: 0,
55+ fulfilled: 0,
56+ partial: 0,
57+ missing: 0,
58+ fulfillmentPercent: 0,
59+ },
60+ features: {
61+ total: 0,
62+ fulfilled: 0,
63+ missing: 0,
64+ fulfillmentPercent: 0,
65+ },
66+ categoryReports: [],
67+ },
68+ },
69+ null,
70+ 2,
71+ )}\n`,
72+"utf8",
73+);
74+}
75+2576describe("maturity docs renderer CLI", () => {
2677it("checks maturity inputs without requiring QA evidence artifacts", () => {
2778const result = runCli("--check");
@@ -42,4 +93,45 @@ describe("maturity docs renderer CLI", () => {
4293"maturity scorecard rendering requires all or release profile qa-evidence.json",
4394);
4495});
96+97+it("rejects scorecard evidence with failed or blocked entries", () => {
98+const outputDir = tempDirs.make("openclaw-maturity-docs-output-");
99+const evidenceDir = tempDirs.make("openclaw-maturity-docs-evidence-");
100+writeQaEvidence({
101+dir: evidenceDir,
102+entries: [
103+{ id: "passing-scenario", status: "pass" },
104+{ id: "failing-scenario", status: "fail" },
105+{ id: "blocked-scenario", status: "blocked" },
106+],
107+});
108+109+const result = runCli("--output-dir", outputDir, "--evidence-dir", evidenceDir);
110+111+expect(result.status).toBe(1);
112+expect(result.stdout).toBe("");
113+expect(result.stderr).toContain("maturity docs require passing QA evidence");
114+expect(result.stderr).toContain("failing-scenario (fail)");
115+expect(result.stderr).toContain("blocked-scenario (blocked)");
116+});
117+118+it("renders passing evidence without impossible failed or blocked result counts", () => {
119+const outputDir = tempDirs.make("openclaw-maturity-docs-output-");
120+const evidenceDir = tempDirs.make("openclaw-maturity-docs-evidence-");
121+writeQaEvidence({
122+dir: evidenceDir,
123+entries: [
124+{ id: "passing-scenario", status: "pass" },
125+{ id: "skipped-scenario", status: "skipped" },
126+],
127+});
128+129+const result = runCli("--output-dir", outputDir, "--evidence-dir", evidenceDir);
130+131+expect(result.status).toBe(0);
132+const scorecard = fs.readFileSync(path.join(outputDir, "maturity", "scorecard.md"), "utf8");
133+expect(scorecard).toContain("1 passed, 1 skipped");
134+expect(scorecard).not.toContain("0 failed");
135+expect(scorecard).not.toContain("0 blocked");
136+});
45137});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。