test: stabilize vitest helper export types

This commit is contained in:
Val Alexander 2026-03-13 16:16:47 -05:00
parent 9505224316
commit 734d0bd647
No known key found for this signature in database
5 changed files with 60 additions and 18 deletions

View File

@ -46,6 +46,7 @@ describe("runServiceRestart token drift", () => {
});
resetLifecycleServiceMocks();
service.readCommand.mockResolvedValue({
programArguments: [],
environment: { OPENCLAW_GATEWAY_TOKEN: "service-token" },
});
stubEmptyGatewayEnv();
@ -77,6 +78,7 @@ describe("runServiceRestart token drift", () => {
},
});
service.readCommand.mockResolvedValue({
programArguments: [],
environment: { OPENCLAW_GATEWAY_TOKEN: "env-token" },
});
vi.stubEnv("OPENCLAW_GATEWAY_TOKEN", "env-token");

View File

@ -1,16 +1,36 @@
import { vi } from "vitest";
import type { GatewayService } from "../../../daemon/service.js";
import type { RuntimeEnv } from "../../../runtime.js";
import type { MockFn } from "../../../test-utils/vitest-mock-fn.js";
export const runtimeLogs: string[] = [];
export const defaultRuntime = {
log: (message: string) => runtimeLogs.push(message),
error: vi.fn(),
exit: (code: number) => {
throw new Error(`__exit__:${code}`);
},
type LifecycleRuntimeHarness = RuntimeEnv & {
error: MockFn<RuntimeEnv["error"]>;
exit: MockFn<RuntimeEnv["exit"]>;
};
export const service = {
type LifecycleServiceHarness = GatewayService & {
install: MockFn<GatewayService["install"]>;
uninstall: MockFn<GatewayService["uninstall"]>;
stop: MockFn<GatewayService["stop"]>;
isLoaded: MockFn<GatewayService["isLoaded"]>;
readCommand: MockFn<GatewayService["readCommand"]>;
readRuntime: MockFn<GatewayService["readRuntime"]>;
restart: MockFn<GatewayService["restart"]>;
};
export const defaultRuntime: LifecycleRuntimeHarness = {
log: (...args: unknown[]) => {
runtimeLogs.push(args.map((arg) => String(arg)).join(" "));
},
error: vi.fn(),
exit: vi.fn((code: number) => {
throw new Error(`__exit__:${code}`);
}),
};
export const service: LifecycleServiceHarness = {
label: "TestService",
loadedText: "loaded",
notLoadedText: "not loaded",
@ -32,7 +52,7 @@ export function resetLifecycleServiceMocks() {
service.readCommand.mockClear();
service.restart.mockClear();
service.isLoaded.mockResolvedValue(true);
service.readCommand.mockResolvedValue({ environment: {} });
service.readCommand.mockResolvedValue({ programArguments: [], environment: {} });
service.restart.mockResolvedValue({ outcome: "completed" });
}

View File

@ -14,9 +14,9 @@ vi.mock("../schtasks-exec.js", () => ({
}));
vi.mock("../../infra/ports.js", () => ({
inspectPortUsage: (...args: unknown[]) => inspectPortUsage(...args),
inspectPortUsage: (port: number) => inspectPortUsage(port),
}));
vi.mock("../../process/kill-tree.js", () => ({
killProcessTree: (...args: unknown[]) => killProcessTree(...args),
killProcessTree: (pid: number, opts?: { graceMs?: number }) => killProcessTree(pid, opts),
}));

View File

@ -2,11 +2,15 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { vi } from "vitest";
import type { PortUsage } from "../../infra/ports-types.js";
import type { killProcessTree as killProcessTreeImpl } from "../../process/kill-tree.js";
import type { MockFn } from "../../test-utils/vitest-mock-fn.js";
export const schtasksResponses: Array<{ code: number; stdout: string; stderr: string }> = [];
export const schtasksCalls: string[][] = [];
export const inspectPortUsage = vi.fn();
export const killProcessTree = vi.fn();
export const inspectPortUsage: MockFn<(port: number) => Promise<PortUsage>> = vi.fn();
export const killProcessTree: MockFn<typeof killProcessTreeImpl> = vi.fn();
export async function withWindowsEnv(
prefix: string,

View File

@ -3,12 +3,28 @@ import type { OpenClawConfig } from "../config/config.js";
import type { ChannelGroupPolicy } from "../config/group-policy.js";
import type { TelegramAccountConfig } from "../config/types.js";
import type { RuntimeEnv } from "../runtime.js";
import type { MockFn } from "../test-utils/vitest-mock-fn.js";
import { registerTelegramNativeCommands } from "./bot-native-commands.js";
type RegisterTelegramNativeCommandsParams = Parameters<typeof registerTelegramNativeCommands>[0];
type GetPluginCommandSpecsFn = typeof import("../plugins/commands.js").getPluginCommandSpecs;
type MatchPluginCommandFn = typeof import("../plugins/commands.js").matchPluginCommand;
type ExecutePluginCommandFn = typeof import("../plugins/commands.js").executePluginCommand;
type AnyMock = MockFn<(...args: unknown[]) => unknown>;
type AnyAsyncMock = MockFn<(...args: unknown[]) => Promise<unknown>>;
type NativeCommandHarness = {
handlers: Record<string, (ctx: unknown) => Promise<void>>;
sendMessage: AnyAsyncMock;
setMyCommands: AnyAsyncMock;
log: AnyMock;
bot: {
api: {
setMyCommands: AnyAsyncMock;
sendMessage: AnyAsyncMock;
};
command: (name: string, handler: (ctx: unknown) => Promise<void>) => void;
};
};
const pluginCommandMocks = vi.hoisted(() => ({
getPluginCommandSpecs: vi.fn<GetPluginCommandSpecsFn>(() => []),
@ -86,12 +102,12 @@ export function createNativeCommandsHarness(params?: {
nativeEnabled?: boolean;
groupConfig?: Record<string, unknown>;
resolveGroupPolicy?: () => ChannelGroupPolicy;
}) {
}): NativeCommandHarness {
const handlers: Record<string, (ctx: unknown) => Promise<void>> = {};
const sendMessage = vi.fn().mockResolvedValue(undefined);
const setMyCommands = vi.fn().mockResolvedValue(undefined);
const log = vi.fn();
const bot = {
const sendMessage: AnyAsyncMock = vi.fn(async () => undefined);
const setMyCommands: AnyAsyncMock = vi.fn(async () => undefined);
const log: AnyMock = vi.fn();
const bot: NativeCommandHarness["bot"] = {
api: {
setMyCommands,
sendMessage,
@ -153,7 +169,7 @@ export function createTelegramGroupCommandContext(params?: {
};
}
export function findNotAuthorizedCalls(sendMessage: ReturnType<typeof vi.fn>) {
export function findNotAuthorizedCalls(sendMessage: AnyAsyncMock) {
return sendMessage.mock.calls.filter(
(call) => typeof call[1] === "string" && call[1].includes("not authorized"),
);