


























@@ -89,6 +89,64 @@ async function makeTempRepo(prefix: string) {
8989return repoRoot;
9090}
919192+async function writeScriptProducerEvidence(params: {
93+outputDir: string;
94+scenarioId?: string;
95+status: "blocked" | "fail" | "pass";
96+failureReason?: string;
97+}) {
98+const scenarioArtifactBase = path.join(params.outputDir, params.scenarioId ?? "scenario-script");
99+const runRoot = path.join(scenarioArtifactBase, "run-1");
100+await fs.mkdir(runRoot, { recursive: true });
101+await fs.writeFile(
102+path.join(runRoot, "qa-evidence.json"),
103+`${JSON.stringify(
104+ {
105+ kind: "openclaw.qa.evidence-summary",
106+ schemaVersion: 2,
107+ generatedAt: "2026-06-14T00:00:00.000Z",
108+ evidenceMode: "full",
109+ entries: [
110+ {
111+ test: {
112+ kind: "script-producer-check",
113+ id: "script-producer.web-ui.smoke",
114+ title: "Script producer: web-ui smoke",
115+ source: { path: "scripts/evidence-producer.ts" },
116+ },
117+ coverage: [{ id: "ui.control", role: "primary" }],
118+ execution: {
119+ runner: "evidence-producer-script",
120+ environment: { ref: "scenario-ref", os: "darwin", nodeVersion: "v24.0.0" },
121+ provider: {
122+ id: "script-producer",
123+ live: false,
124+ model: { name: null, ref: null },
125+ fixture: "mocked-script-evidence",
126+ },
127+ packageSource: { kind: "source-checkout", sha: "abc123" },
128+ artifacts: [],
129+ },
130+ result: {
131+ status: params.status,
132+ ...(params.failureReason ? { failure: { reason: params.failureReason } } : {}),
133+ timing: { wallMs: 1 },
134+ },
135+ },
136+ ],
137+ },
138+ null,
139+ 2,
140+ )}\n`,
141+"utf8",
142+);
143+await fs.writeFile(
144+path.join(scenarioArtifactBase, "latest-run.json"),
145+`${JSON.stringify({ qaEvidence: path.join(runRoot, "qa-evidence.json") }, null, 2)}\n`,
146+"utf8",
147+);
148+}
149+92150describe("qa test file scenario runner", () => {
93151afterEach(async () => {
94152await Promise.all([
@@ -729,6 +787,97 @@ describe("qa test file scenario runner", () => {
729787});
730788});
731789790+it("fails script scenario results when imported producer evidence is blocked by default", async () => {
791+const repoRoot = await makeTempRepo("qa-script-producer-blocked-");
792+const outputDir = path.join(
793+repoRoot,
794+".artifacts",
795+"qa-e2e",
796+"scenario-script-producer-blocked",
797+);
798+const result = await runQaTestFileScenarios({
799+ repoRoot,
800+ outputDir,
801+providerMode: "mock-openai",
802+primaryModel: "mock-openai/gpt-5.5",
803+scenarios: [makeTestFileScenario("script", "scripts/evidence-producer.ts")],
804+runCommand: async () => {
805+await writeScriptProducerEvidence({
806+ outputDir,
807+status: "blocked",
808+failureReason: "Playwright browser is missing.",
809+});
810+return {
811+exitCode: 0,
812+stdout: "script blocked\n",
813+stderr: "",
814+};
815+},
816+env: {
817+OPENCLAW_QA_REF: "scenario-ref",
818+} as NodeJS.ProcessEnv,
819+});
820+821+expect(result.results[0]).toMatchObject({
822+status: "blocked",
823+failureMessage: "Playwright browser is missing.",
824+});
825+});
826+827+it("allows blocked imported producer evidence for opt-in script scenarios", async () => {
828+const repoRoot = await makeTempRepo("qa-script-producer-blocked-allowed-");
829+const outputDir = path.join(
830+repoRoot,
831+".artifacts",
832+"qa-e2e",
833+"scenario-script-producer-blocked-allowed",
834+);
835+const scenario = makeTestFileScenario("script", "scripts/evidence-producer.ts");
836+if (scenario.execution.kind !== "script") {
837+throw new Error("expected script scenario");
838+}
839+scenario.execution.allowBlockedEvidence = true;
840+841+const result = await runQaTestFileScenarios({
842+ repoRoot,
843+ outputDir,
844+providerMode: "mock-openai",
845+primaryModel: "mock-openai/gpt-5.5",
846+scenarios: [scenario],
847+runCommand: async () => {
848+await writeScriptProducerEvidence({
849+ outputDir,
850+status: "blocked",
851+failureReason: "Playwright browser is missing.",
852+});
853+return {
854+exitCode: 0,
855+stdout: "script blocked\n",
856+stderr: "",
857+};
858+},
859+env: {
860+OPENCLAW_QA_REF: "scenario-ref",
861+} as NodeJS.ProcessEnv,
862+});
863+864+expect(result.results[0]).toMatchObject({
865+status: "pass",
866+producerEvidence: {
867+entries: [
868+{
869+test: {
870+id: "script-producer.web-ui.smoke",
871+},
872+result: {
873+status: "blocked",
874+},
875+},
876+],
877+},
878+});
879+});
880+732881it("carries the suite profile into merged producer evidence", async () => {
733882const repoRoot = await makeTempRepo("qa-script-profile-");
734883const result = await runQaTestFileScenarios({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。