chore: Fix types in tests 30/N.

This commit is contained in:
cpojer
2026-02-17 14:32:57 +09:00
parent ecf1c955a1
commit f2f17bafbc
9 changed files with 65 additions and 32 deletions

View File

@@ -1,12 +1,14 @@
import { Command } from "commander";
import { describe, expect, it, vi } from "vitest";
const callGatewayFromCli = vi.fn(async (method: string, _opts: unknown, params?: unknown) => {
if (method === "cron.status") {
return { enabled: true };
}
return { ok: true, params };
});
const callGatewayFromCli = vi.fn(
async (method: string, _opts: unknown, params?: unknown, _timeoutMs?: number) => {
if (method === "cron.status") {
return { enabled: true };
}
return { ok: true, params };
},
);
vi.mock("./gateway-rpc.js", async () => {
const actual = await vi.importActual<typeof import("./gateway-rpc.js")>("./gateway-rpc.js");

View File

@@ -1,8 +1,8 @@
import { Command } from "commander";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
const callGateway = vi.fn(async () => ({ ok: true }));
const resolveGatewayProgramArguments = vi.fn(async () => ({
const callGateway = vi.fn(async (..._args: unknown[]) => ({ ok: true }));
const resolveGatewayProgramArguments = vi.fn(async (_opts?: unknown) => ({
programArguments: ["/bin/node", "cli", "gateway", "--port", "18789"],
}));
const serviceInstall = vi.fn().mockResolvedValue(undefined);
@@ -12,7 +12,7 @@ const serviceRestart = vi.fn().mockResolvedValue(undefined);
const serviceIsLoaded = vi.fn().mockResolvedValue(false);
const serviceReadCommand = vi.fn().mockResolvedValue(null);
const serviceReadRuntime = vi.fn().mockResolvedValue({ status: "running" });
const findExtraGatewayServices = vi.fn(async () => []);
const findExtraGatewayServices = vi.fn(async (_env: unknown, _opts?: unknown) => []);
const inspectPortUsage = vi.fn(async (port: number) => ({
port,
status: "free",

View File

@@ -9,7 +9,7 @@ const consumeGatewaySigusr1RestartAuthorization = vi.fn(() => true);
const isGatewaySigusr1RestartExternallyAllowed = vi.fn(() => false);
const markGatewaySigusr1RestartHandled = vi.fn();
const getActiveTaskCount = vi.fn(() => 0);
const waitForActiveTasks = vi.fn(async () => ({ drained: true }));
const waitForActiveTasks = vi.fn(async (_timeoutMs: number) => ({ drained: true }));
const resetAllLanes = vi.fn();
const DRAIN_TIMEOUT_LOG = "drain timeout reached; proceeding with restart";
const gatewayLog = {
@@ -103,7 +103,7 @@ describe("runGatewayLoop", () => {
start,
runtime: {
exit: vi.fn(),
} as { exit: (code: number) => never },
} as unknown as { exit: (code: number) => never },
});
try {

View File

@@ -14,8 +14,10 @@ vi.mock("../../plugin-registry.js", () => ({
ensurePluginRegistryLoaded: vi.fn(),
}));
const hasHooksMock = vi.fn(() => false);
const runGatewayStopMock = vi.fn(async () => {});
const hasHooksMock = vi.fn((_hookName: string) => false);
const runGatewayStopMock = vi.fn(
async (_event: { reason?: string }, _ctx: Record<string, unknown>) => {},
);
const runGlobalGatewayStopSafelyMock = vi.fn(
async (params: {
event: { reason?: string };
@@ -201,7 +203,13 @@ describe("runMessageAction", () => {
expect.anything(),
);
// account key should be stripped in favor of accountId
const passedOpts = messageCommandMock.mock.calls[0][0] as Record<string, unknown>;
const passedOpts = (
messageCommandMock.mock.calls as unknown as Array<[Record<string, unknown>]>
)?.[0]?.[0];
expect(passedOpts).toBeTruthy();
if (!passedOpts) {
throw new Error("expected message command call");
}
expect(passedOpts).not.toHaveProperty("account");
});
});

View File

@@ -2,7 +2,7 @@ import { describe, expect, it, vi } from "vitest";
import { isYes, setVerbose, setYes } from "../globals.js";
vi.mock("node:readline/promises", () => {
const question = vi.fn<[], Promise<string>>();
const question = vi.fn(async () => "");
const close = vi.fn();
const createInterface = vi.fn(() => ({ question, close }));
return { default: { createInterface } };
@@ -11,14 +11,14 @@ vi.mock("node:readline/promises", () => {
type ReadlineMock = {
default: {
createInterface: () => {
question: ReturnType<typeof vi.fn<[], Promise<string>>>;
question: ReturnType<typeof vi.fn>;
close: ReturnType<typeof vi.fn>;
};
};
};
const { promptYesNo } = await import("./prompt.js");
const readline = (await import("node:readline/promises")) as ReadlineMock;
const readline = (await import("node:readline/promises")) as unknown as ReadlineMock;
describe("promptYesNo", () => {
it("returns true when global --yes is set", async () => {

View File

@@ -87,8 +87,9 @@ describe("DiscordMessageListener", () => {
expect(handler).toHaveBeenCalledOnce();
expect(handlerResolved).toBe(false);
if (resolveHandler) {
resolveHandler();
const release = resolveHandler;
if (typeof release === "function") {
(release as () => void)();
}
await handlerPromise;
});
@@ -134,8 +135,9 @@ describe("DiscordMessageListener", () => {
);
vi.setSystemTime(31_000);
if (resolveHandler) {
resolveHandler();
const release = resolveHandler;
if (typeof release === "function") {
(release as () => void)();
}
await handlerPromise;
await Promise.resolve();
@@ -143,7 +145,8 @@ describe("DiscordMessageListener", () => {
expect(logger.warn).toHaveBeenCalled();
const warnMock = logger.warn as unknown as { mock: { calls: unknown[][] } };
const [, meta] = warnMock.mock.calls[0] ?? [];
expect(meta?.durationMs).toBeGreaterThanOrEqual(30_000);
const durationMs = (meta as { durationMs?: number } | undefined)?.durationMs;
expect(durationMs).toBeGreaterThanOrEqual(30_000);
} finally {
vi.useRealTimers();
}
@@ -756,11 +759,12 @@ describe("discord media payload", () => {
const { enqueueSystemEventSpy, resolveAgentRouteMock } = vi.hoisted(() => ({
enqueueSystemEventSpy: vi.fn(),
resolveAgentRouteMock: vi.fn(() => ({
resolveAgentRouteMock: vi.fn((params: unknown) => ({
agentId: "default",
channel: "discord",
accountId: "acc-1",
sessionKey: "discord:acc-1:dm:user-1",
...(typeof params === "object" && params !== null ? { _params: params } : {}),
})),
}));
@@ -940,7 +944,9 @@ describe("discord DM reaction handling", () => {
await listener.handle(data, client);
expect(resolveAgentRouteMock).toHaveBeenCalledOnce();
const [routeArgs] = resolveAgentRouteMock.mock.calls[0] ?? [];
const routeArgs = (resolveAgentRouteMock.mock.calls[0]?.[0] ?? {}) as {
peer?: unknown;
};
if (!routeArgs) {
throw new Error("expected route arguments");
}
@@ -958,7 +964,9 @@ describe("discord DM reaction handling", () => {
await listener.handle(data, client);
expect(resolveAgentRouteMock).toHaveBeenCalledOnce();
const [routeArgs] = resolveAgentRouteMock.mock.calls[0] ?? [];
const routeArgs = (resolveAgentRouteMock.mock.calls[0]?.[0] ?? {}) as {
peer?: unknown;
};
if (!routeArgs) {
throw new Error("expected route arguments");
}

View File

@@ -132,7 +132,9 @@ describe("processDiscordMessage ack reactions", () => {
// oxlint-disable-next-line typescript/no-explicit-any
await processDiscordMessage(ctx as any);
const emojis = reactMessageDiscord.mock.calls.map((call) => call[2]);
const emojis = (
reactMessageDiscord.mock.calls as unknown as Array<[unknown, unknown, string]>
).map((call) => call[2]);
expect(emojis).toContain("👀");
expect(emojis).toContain("✅");
expect(emojis).not.toContain("🧠");
@@ -161,7 +163,9 @@ describe("processDiscordMessage ack reactions", () => {
}
await runPromise;
const emojis = reactMessageDiscord.mock.calls.map((call) => call[2]);
const emojis = (
reactMessageDiscord.mock.calls as unknown as Array<[unknown, unknown, string]>
).map((call) => call[2]);
expect(emojis).toContain("⏳");
expect(emojis).toContain("⚠️");
expect(emojis).toContain("✅");

View File

@@ -20,7 +20,7 @@ const { resolveDiscordMessageChannelId, resolveForwardedMediaList } =
await import("./message-utils.js");
function asMessage(payload: Record<string, unknown>): Message {
return payload as Message;
return payload as unknown as Message;
}
describe("resolveDiscordMessageChannelId", () => {

View File

@@ -5,9 +5,17 @@ function jsonResponse(body: unknown) {
return new Response(JSON.stringify(body), { status: 200 });
}
const urlToString = (url: Request | URL | string): string => {
if (typeof url === "string") {
return url;
}
return "url" in url ? url.url : String(url);
};
describe("resolveDiscordChannelAllowlist", () => {
it("resolves guild/channel by name", async () => {
const fetcher = async (url: string) => {
const fetcher = async (input: RequestInfo | URL) => {
const url = urlToString(input);
if (url.endsWith("/users/@me/guilds")) {
return jsonResponse([{ id: "g1", name: "My Guild" }]);
}
@@ -32,7 +40,8 @@ describe("resolveDiscordChannelAllowlist", () => {
});
it("resolves channel id to guild", async () => {
const fetcher = async (url: string) => {
const fetcher = async (input: RequestInfo | URL) => {
const url = urlToString(input);
if (url.endsWith("/users/@me/guilds")) {
return jsonResponse([{ id: "g1", name: "Guild One" }]);
}
@@ -54,7 +63,8 @@ describe("resolveDiscordChannelAllowlist", () => {
});
it("resolves guild: prefixed id as guild (not channel)", async () => {
const fetcher = async (url: string) => {
const fetcher = async (input: RequestInfo | URL) => {
const url = urlToString(input);
if (url.endsWith("/users/@me/guilds")) {
return jsonResponse([{ id: "111222333444555666", name: "Guild One" }]);
}
@@ -80,7 +90,8 @@ describe("resolveDiscordChannelAllowlist", () => {
// Demonstrates why provider.ts must prefix guild-only entries with "guild:"
// In reality, Discord returns 404 when a guild ID is sent to /channels/<guildId>,
// which causes fetchDiscord to throw and the entire resolver to crash.
const fetcher = async (url: string) => {
const fetcher = async (input: RequestInfo | URL) => {
const url = urlToString(input);
if (url.endsWith("/users/@me/guilds")) {
return jsonResponse([{ id: "999", name: "My Server" }]);
}