mirror of
https://github.com/openclaw/openclaw.git
synced 2026-11-01 04:58:23 +00:00
* test(discord): deslop z0658 tests * test(discord): deslop z0658 tests * test(github-connections): deslop z0655 tests * test(github-connections): deslop z0655 tests * test(telegram): deslop z0657 tests * test(telegram): deslop z0657 tests * test(infra): deslop z0656 tests * test(infra): deslop z0656 tests * test(infra): deslop z0656 tests * test(signal): deslop z0661 tests * test(browser): deslop z0654 tests * test(browser): deslop z0654 tests * test(browser): deslop z0654 tests * test(cli): deslop z0653 tests * test(cli): deslop z0653 tests * test(cron): deslop z0659 tests * test(cron): deslop z0659 tests * test(cron): deslop z0659 tests * test(plugins): deslop z0662 tests * test(plugins): deslop z0662 tests * test(plugins): deslop z0662 tests * test(scripts): deslop z0664 tests * test(scripts): deslop z0664 tests * test(slack): deslop z0666 tests * test(plugins): deslop z0663 tests * test(plugins): deslop z0663 tests * test(agents): deslop z0660 tests * test(agents): deslop z0660 tests * test(agents): deslop z0660 tests * test: preserve contracts in batch d360 fixtures * test: align d360 fixtures with lint ratchets
117 lines
4.1 KiB
TypeScript
117 lines
4.1 KiB
TypeScript
import type { SpawnOptions } from "node:child_process";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { afterEach, vi } from "vitest";
|
|
import type { createRunNodePathClassifier } from "../../scripts/run-node-watch-paths.mts";
|
|
import type { WatcherFactory } from "../../scripts/watch-node-observation.mts";
|
|
import { createDeferred } from "../helpers/promise.js";
|
|
import { createScriptTestHarness } from "./test-helpers.js";
|
|
|
|
type WatchExit = number | NodeJS.Signals;
|
|
export type WatchFixture = {
|
|
args?: string[];
|
|
cwd?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
process: NodeJS.Process;
|
|
spawn: (command: string, args: string[], options: SpawnOptions) => unknown;
|
|
createWatcher?: WatcherFactory;
|
|
loadWatcher?: () => Promise<WatcherFactory>;
|
|
pathClassifier?: Pick<
|
|
ReturnType<typeof createRunNodePathClassifier>,
|
|
"refreshGeneratedPluginAssetPaths" | "isRestartRelevantRunNodePath"
|
|
>;
|
|
fs?: Pick<typeof fs, "existsSync">;
|
|
now?: () => number;
|
|
sleep?: (milliseconds: number) => Promise<void>;
|
|
signalProcess?: (pid: number, signal: NodeJS.Signals | 0) => void;
|
|
};
|
|
|
|
const { createTempDir } = createScriptTestHarness();
|
|
let ready: Promise<void>;
|
|
export const watchReady = () => ready;
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
vi.doUnmock("node:process");
|
|
vi.doUnmock("node:child_process");
|
|
vi.doUnmock("../../scripts/watch-node-observation.mts");
|
|
vi.doUnmock("../../scripts/run-node-watch-paths.mts");
|
|
vi.doUnmock("../../scripts/lib/sleep.mjs");
|
|
});
|
|
|
|
export async function runWatch(params: WatchFixture): Promise<WatchExit> {
|
|
const admission = createDeferred();
|
|
ready = admission.promise;
|
|
try {
|
|
vi.resetModules();
|
|
const cwd = params.cwd ?? createTempDir("openclaw-watch-boundary-");
|
|
const fakeProcess = Object.assign(params.process, {
|
|
cwd: () => cwd,
|
|
argv: [process.execPath, "watch-fixture", ...(params.args ?? [])],
|
|
env: params.env ?? { ...process.env },
|
|
platform: params.process.platform ?? process.platform,
|
|
stdin: params.process.stdin ?? { isTTY: false },
|
|
stderr: params.process.stderr ?? { write: () => true },
|
|
kill:
|
|
params.signalProcess ??
|
|
(() => {
|
|
throw new Error("Unexpected process signal in watch fixture");
|
|
}),
|
|
});
|
|
vi.doMock("node:process", () => ({ default: fakeProcess }));
|
|
vi.doMock("node:child_process", async (importOriginal) => ({
|
|
...(await importOriginal<typeof import("node:child_process")>()),
|
|
spawn: params.spawn,
|
|
}));
|
|
vi.doMock("../../scripts/watch-node-observation.mts", async () => {
|
|
let factory = params.createWatcher;
|
|
if (params.loadWatcher) {
|
|
const loading = params.loadWatcher();
|
|
admission.resolve();
|
|
try {
|
|
factory = await loading;
|
|
} catch (error) {
|
|
return {
|
|
get createSourceObserver() {
|
|
throw error;
|
|
},
|
|
};
|
|
}
|
|
}
|
|
const createObserver = factory;
|
|
if (!createObserver) {
|
|
throw new Error("Watch fixture needs a source observer");
|
|
}
|
|
return {
|
|
createSourceObserver: (...args: Parameters<WatcherFactory>) => {
|
|
const watcher = createObserver(...args);
|
|
admission.resolve();
|
|
return watcher;
|
|
},
|
|
};
|
|
});
|
|
if (params.pathClassifier) {
|
|
vi.doMock("../../scripts/run-node-watch-paths.mts", async (importOriginal) => ({
|
|
...(await importOriginal<typeof import("../../scripts/run-node-watch-paths.mts")>()),
|
|
createRunNodePathClassifier: () => params.pathClassifier,
|
|
}));
|
|
}
|
|
if (params.fs) {
|
|
const exists = fs.existsSync;
|
|
const distEntry = path.join(cwd, "dist", "entry.js");
|
|
vi.spyOn(fs, "existsSync").mockImplementation((candidate) =>
|
|
candidate === distEntry ? params.fs!.existsSync(candidate) : exists(candidate),
|
|
);
|
|
}
|
|
if (params.now) {
|
|
vi.spyOn(Date, "now").mockImplementation(params.now);
|
|
}
|
|
if (params.sleep) {
|
|
vi.doMock("../../scripts/lib/sleep.mjs", () => ({ sleep: params.sleep }));
|
|
}
|
|
const { runWatchMain } = await import("../../scripts/watch-node.mts");
|
|
return await runWatchMain();
|
|
} finally {
|
|
admission.resolve();
|
|
}
|
|
}
|