openclaw/test/scripts/dev-tool.test.ts
Peter Steinberger 700d5ce702
test(agents,plugins,ui): remove low-value tests (batch d352) (#178930)
* test(doctor): deslop z0552 tests

* test(auth-profiles): deslop z0553 tests

* test(auth-profiles): preserve migration table provider type

* test(auth-profiles): deslop z0553 tests

* test(plugins): deslop z0551 tests

* test(plugins): deslop z0551 tests

* test(plugins): deslop z0551 tests

* test(agents): deslop z0556 tests

* test(agents): deslop z0556 tests

* test(ui): deslop z0554 tests

* test(ui): deslop z0554 tests

* test(ui): deslop z0554 tests

* test(xai): deslop z0558 tests

* test(xai): deslop z0558 tests

* test(channels): deslop z0560 tests

* test(plugins): deslop z0557 tests

* test(plugins): deslop z0557 tests

* test(plugins): deslop z0557 tests

* test(discord): deslop z0555 tests

* test(discord): deslop z0555 tests

* test(plugins): deslop z0559 tests

* test(plugins): deslop z0559 tests

* test(doctor): deslop z0552 tests

* test(scripts): deslop z0561 tests

* test(scripts): further deslop z0561 tests

* test(doctor): deslop z0562 tests

* test(doctor): deslop z0562 tests

* test(doctor): deslop z0562 tests

* test(agents): deslop z0563 tests

* test(discord): preserve shared model-picker fixture after replay

* test: retain boundary assertions and fix cleanup fixture types

* test: repair cleanup fixture types and mock isolation contracts

* test(scripts): allow omitted availability in dev-tool cases

* test: prune obsolete cleanup mock baseline entries
2026-10-21 03:20:15 +00:00

92 lines
3.9 KiB
TypeScript

import { spawnSync } from "node:child_process";
import { symlinkSync, writeFileSync } from "node:fs";
import path from "node:path";
import { expect, it, vi } from "vitest";
import { resolveDevTool } from "../../scripts/lib/dev-tool.mts";
import { compareFormatResults } from "../../scripts/run-format.mts";
import { resolveTestNodeExecPath } from "../../src/test-utils/node-process.js";
import { createScriptTestHarness } from "./test-helpers.js";
const { createTempDir } = createScriptTestHarness();
const pinnedBun = { command: "/pinned/bin/bun" };
const unavailable = { reason: "unavailable" };
it.each([
["format", {}, true],
["format", { CI: "true" }, false],
["format", { CI: "false" }, true],
["format", { OPENCLAW_FORMAT_TOOL: "oxfmt" }, false],
["format", { OPENCLAW_FORMAT_TOOL: "bun" }, true],
["format", { CI: "true", OPENCLAW_FORMAT_TOOL: "bun" }, true],
["lint", {}, false],
["lint", { CI: "true" }, false],
["lint", { OPENCLAW_LINT_TOOL: "bun", PATH: "/usr/bin" }, true],
["format", { OPENCLAW_FORMAT_TOOL: "bun" }, "error", false],
["format", {}, false, false],
] as const)("selects %s for %j", (kind, env, bun, availability?: boolean) => {
const available = availability ?? true;
const resolvePinnedBun = vi.fn(() => (available ? pinnedBun : unavailable));
const notice = vi.fn();
const run = () => resolveDevTool(kind, env, { resolvePinnedBun, notice });
if (bun === "error") {
expect(run).toThrow("OPENCLAW_FORMAT_TOOL=bun: unavailable");
expect(notice).not.toHaveBeenCalled();
return;
}
const tool = run();
expect(tool.command === "/pinned/bin/bun").toBe(bun);
expect(resolvePinnedBun).toHaveBeenCalledTimes(bun || !available ? 1 : 0);
if (available) {
expect(notice).not.toHaveBeenCalled();
} else {
const args = [path.resolve("node_modules/oxfmt/bin/oxfmt")];
expect(tool).toMatchObject({ command: process.execPath, args });
expect(notice).toHaveBeenCalledExactlyOnceWith("[openclaw] unavailable; using oxfmt.");
}
if (kind === "lint" && bun) {
expect(tool.args).toEqual(["lint"]);
expect(tool.env.PATH?.split(/[:;]/u)[0]).toBe("/pinned/bin");
expect(tool.env.npm_lifecycle_event).toBe("lint");
}
});
it("rejects an invalid override", () => {
const invalid = () => resolveDevTool("format", { OPENCLAW_FORMAT_TOOL: "typo" });
expect(invalid).toThrow("OPENCLAW_FORMAT_TOOL must be bun or oxfmt");
});
it.each([
["bun", "export const value=1;", "process.exit(0);"],
["oxfmt", "export const value = 1;\n", 'console.log("file.ts"); process.exit(1);'],
])("CI enforces both tools despite the %s override", (override, source, bunOutput) => {
const root = createTempDir("format-parity-");
symlinkSync(path.resolve("node_modules"), path.join(root, "node_modules"), "junction");
writeFileSync(path.join(root, ".oxfmtrc.jsonc"), "{}");
writeFileSync(path.join(root, "file.ts"), source);
// Node stands in for Bun and executes this fixed report as its `fmt` command.
writeFileSync(path.join(root, "fmt"), bunOutput);
const node = resolveTestNodeExecPath();
const result = spawnSync(node, [path.resolve("scripts/run-format.mts"), "--check", "file.ts"], {
cwd: root,
encoding: "utf8",
env: {
...process.env,
CI: "true",
OPENCLAW_FORMAT_TOOL: override,
OPENCLAW_BUN_PATH: node,
},
});
expect(result.status).toBe(1);
expect(result.stderr).toContain("[format] parity failed");
});
const output = (status: number, stdout = "") => ({ status, stdout });
const timing = (ms: number) => `Finished in ${ms}ms on 0 files using 4 threads.\n`;
it.each([
[output(0, timing(1)), output(0, timing(0)), true],
[output(0), output(0), true],
[output(0), output(1, "a.ts\n"), false],
[output(1, "a.ts"), output(0), false],
[output(1, "a.ts"), output(1, "b.ts\n"), false],
[output(1, "b.ts\na.ts"), output(1, "a.ts\nb.ts\n"), true],
])("compares each tool's changed-file set", (oxfmt, bun, matches) => {
expect(compareFormatResults(oxfmt, bun)).toBe(matches);
});