Files
openclaw/test/scripts/tsdown-build.test.ts
2026-04-14 15:19:31 +01:00

106 lines
3.8 KiB
TypeScript

import fs from "node:fs";
import fsPromises from "node:fs/promises";
import path from "node:path";
import { describe, expect, it, vi } from "vitest";
import {
pruneSourceCheckoutBundledPluginNodeModules,
pruneStaleRootChunkFiles,
resolveTsdownBuildInvocation,
} from "../../scripts/tsdown-build.mjs";
import { createScriptTestHarness } from "./test-helpers.js";
const { createTempDir } = createScriptTestHarness();
describe("resolveTsdownBuildInvocation", () => {
it("routes Windows tsdown builds through the pnpm runner instead of shell=true", () => {
const result = resolveTsdownBuildInvocation({
platform: "win32",
nodeExecPath: "C:\\Program Files\\nodejs\\node.exe",
npmExecPath: "C:/Users/test/AppData/Local/pnpm/10.32.1/bin/pnpm.cjs",
env: {},
});
expect(result).toEqual({
command: "C:\\Program Files\\nodejs\\node.exe",
args: [
"C:/Users/test/AppData/Local/pnpm/10.32.1/bin/pnpm.cjs",
"exec",
"tsdown",
"--config-loader",
"unrun",
"--logLevel",
"warn",
],
options: {
encoding: "utf8",
stdio: "pipe",
shell: false,
windowsVerbatimArguments: undefined,
env: {},
},
});
});
it("keeps source-checkout prune best-effort", () => {
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
const rmSync = vi.spyOn(fs, "rmSync");
rmSync.mockImplementation(() => {
throw new Error("locked");
});
expect(() =>
pruneSourceCheckoutBundledPluginNodeModules({
cwd: process.cwd(),
}),
).not.toThrow();
expect(warn).toHaveBeenCalledWith(
"tsdown: could not prune bundled plugin source node_modules: Error: locked",
);
warn.mockRestore();
rmSync.mockRestore();
});
it("prunes stale hashed root chunk files but keeps stable aliases and nested assets", async () => {
const rootDir = createTempDir("openclaw-tsdown-build-");
const distDir = path.join(rootDir, "dist");
const distRuntimeDir = path.join(rootDir, "dist-runtime");
await fsPromises.mkdir(path.join(distDir, "control-ui"), { recursive: true });
await fsPromises.mkdir(distRuntimeDir, { recursive: true });
await fsPromises.writeFile(path.join(distDir, "delegate-BPjCe4gC.js"), "old delegate\n");
await fsPromises.writeFile(path.join(distDir, "compact.runtime-2DiEmVcA.js"), "old runtime\n");
await fsPromises.writeFile(path.join(distDir, "compact.runtime.js"), "stable alias\n");
await fsPromises.writeFile(path.join(distDir, "entry.js"), "entry\n");
await fsPromises.writeFile(path.join(distDir, "control-ui", "index.html"), "asset\n");
await fsPromises.writeFile(
path.join(distRuntimeDir, "heartbeat-runner.runtime-fspOEj_1.js"),
"old runtime\n",
);
await fsPromises.writeFile(path.join(distRuntimeDir, "heartbeat-runner.runtime.js"), "alias\n");
pruneStaleRootChunkFiles({ cwd: rootDir });
await expect(
fsPromises.readFile(path.join(distDir, "compact.runtime.js"), "utf8"),
).resolves.toBe("stable alias\n");
await expect(fsPromises.readFile(path.join(distDir, "entry.js"), "utf8")).resolves.toBe(
"entry\n",
);
await expect(
fsPromises.readFile(path.join(distDir, "control-ui", "index.html"), "utf8"),
).resolves.toBe("asset\n");
await expect(
fsPromises.readFile(path.join(distRuntimeDir, "heartbeat-runner.runtime.js"), "utf8"),
).resolves.toBe("alias\n");
await expect(fsPromises.stat(path.join(distDir, "delegate-BPjCe4gC.js"))).rejects.toThrow();
await expect(
fsPromises.stat(path.join(distDir, "compact.runtime-2DiEmVcA.js")),
).rejects.toThrow();
await expect(
fsPromises.stat(path.join(distRuntimeDir, "heartbeat-runner.runtime-fspOEj_1.js")),
).rejects.toThrow();
});
});