Files
adolf/test/scripts/test-env-mutation-report.test.ts
alvis bedb527145
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Vendor OpenClaw source as Adolf fork baseline
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11),
free to diverge. Tree copied sans upstream .git; upstream remote added for
future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19.
Preserves docs/ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
2026-07-05 09:36:54 +00:00

213 lines
6.4 KiB
TypeScript

// Test Env Mutation Report tests cover test env mutation report script behavior.
import { spawnSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
import {
collectTestEnvMutationReport,
renderTestEnvMutationReport,
type TestEnvMutationReport,
} from "../../scripts/test-env-mutation-report.js";
import { createScriptTestHarness } from "./test-helpers.js";
const { createTempDir } = createScriptTestHarness();
function writeRepoFile(repoRoot: string, relativePath: string, value: string): void {
const filePath = path.join(repoRoot, relativePath);
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, value, "utf8");
}
function makeEnvMutationFixture(): string {
const repoRoot = createTempDir("openclaw-test-env-mutations-");
writeRepoFile(
repoRoot,
"src/runtime.ts",
`
process.env.OPENCLAW_STATE_DIR = "ignored because this is not a test file";
`,
);
writeRepoFile(
repoRoot,
"src/example.test.ts",
`
process.env.OPENCLAW_STATE_DIR = "state";
delete process.env["OPENCLAW_CONFIG_PATH"];
vi.stubEnv("HOME", "home");
vi.stubEnv("OPENCLAW_WORKSPACE_DIR", "workspace");
process.env = { ...process.env, OPENCLAW_HOME: "home", OTHER_KEY: "ignored" };
const dynamicEnvKey = "OPENCLAW_STATE_DIR";
process.env[dynamicEnvKey] = "dynamic";
delete process.env[dynamicEnvKey];
const fixture = 'process.env.OPENCLAW_HOME = "not code"';
process.env.NOT_OPENCLAW = "ignored";
`,
);
writeRepoFile(
repoRoot,
"scripts/mcp-code-mode-gateway-e2e.ts",
`
process.env.OPENCLAW_CONFIG_PATH = "script-harness";
`,
);
writeRepoFile(
repoRoot,
"src/agents/auth-profiles/oauth-test-utils.ts",
`
process.env.OPENCLAW_AGENT_DIR = "agent";
`,
);
writeRepoFile(
repoRoot,
"src/test-utils/openclaw-test-state.ts",
`
process.env.HOME = "allowed";
delete process.env.OPENCLAW_STATE_DIR;
`,
);
return repoRoot;
}
describe("collectTestEnvMutationReport", () => {
it("reports active OpenClaw env mutations while ignoring strings and non-test files", () => {
const report = collectTestEnvMutationReport({ repoRoot: makeEnvMutationFixture() });
expect(
report.activeFindings.map((finding) => ({
file: finding.file,
key: finding.key,
operation: finding.operation,
})),
).toEqual([
{
file: "scripts/mcp-code-mode-gateway-e2e.ts",
key: "OPENCLAW_CONFIG_PATH",
operation: "assign",
},
{
file: "src/agents/auth-profiles/oauth-test-utils.ts",
key: "OPENCLAW_AGENT_DIR",
operation: "assign",
},
{ file: "src/example.test.ts", key: "OPENCLAW_STATE_DIR", operation: "assign" },
{ file: "src/example.test.ts", key: "OPENCLAW_CONFIG_PATH", operation: "delete" },
{ file: "src/example.test.ts", key: "HOME", operation: "stubEnv" },
{ file: "src/example.test.ts", key: "OPENCLAW_WORKSPACE_DIR", operation: "stubEnv" },
{ file: "src/example.test.ts", key: "OPENCLAW_HOME", operation: "replace" },
{ file: "src/example.test.ts", key: "<dynamic>", operation: "assign" },
{ file: "src/example.test.ts", key: "<dynamic>", operation: "delete" },
]);
expect(report.allowedFindings).toHaveLength(2);
expect(report.summary).toMatchObject({
activeFileCount: 3,
activeFindingCount: 9,
allowedFileCount: 1,
allowedFindingCount: 2,
});
});
it("renders a non-blocking text report for active findings", () => {
const report = collectTestEnvMutationReport({ repoRoot: makeEnvMutationFixture() });
const rendered = renderTestEnvMutationReport(report, { includeAllowed: true });
expect(rendered).toContain("OpenClaw test env mutation report");
expect(rendered).toContain("Findings: 9 active in 3 file(s), 2 allowed in 1 file(s)");
expect(rendered).toContain("- src/example.test.ts (7)");
expect(rendered).toContain("L2 OPENCLAW_STATE_DIR assign process.env");
expect(rendered).toContain("Allowed harness findings:");
});
it("prints JSON from the CLI and exits successfully", () => {
const repoRoot = makeEnvMutationFixture();
const result = spawnSync(
process.execPath,
[
"--import",
"tsx",
path.join(process.cwd(), "scripts/test-env-mutation-report.ts"),
"--",
"--repo-root",
repoRoot,
"--json",
],
{
encoding: "utf8",
},
);
expect(result.status).toBe(0);
const report = JSON.parse(result.stdout) as TestEnvMutationReport;
expect(report.summary.activeFindingCount).toBe(9);
expect(report.summary.allowedFindingCount).toBe(2);
});
it("prints CLI help without scanning the repository", () => {
const result = spawnSync(
process.execPath,
[
"--import",
"tsx",
path.join(process.cwd(), "scripts/test-env-mutation-report.ts"),
"--help",
],
{
encoding: "utf8",
},
);
expect(result.status).toBe(0);
expect(result.stdout).toContain("Usage:");
expect(result.stdout).toContain("pnpm test:env-mutations:report");
expect(result.stdout).not.toContain("Scanned files:");
expect(result.stderr).toBe("");
});
it("rejects missing or flag-shaped CLI repo roots instead of scanning zero files", () => {
for (const value of ["--json", "-h"]) {
const result = spawnSync(
process.execPath,
[
"--import",
"tsx",
path.join(process.cwd(), "scripts/test-env-mutation-report.ts"),
"--",
"--repo-root",
value,
],
{
encoding: "utf8",
},
);
expect(result.status).toBe(1);
expect(result.stderr).toContain("--repo-root expects a path");
}
});
it("rejects loose CLI limits before scanning the repository", () => {
for (const limit of ["1e3", ""]) {
const result = spawnSync(
process.execPath,
[
"--import",
"tsx",
path.join(process.cwd(), "scripts/test-env-mutation-report.ts"),
"--",
"--limit",
limit,
"--repo-root",
createTempDir("openclaw-env-limit-"),
],
{
encoding: "utf8",
},
);
expect(result.status).toBe(1);
expect(result.stderr).toContain("--limit expects a non-negative integer");
expect(result.stdout).not.toContain("Scanned files:");
}
});
});