mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-14 21:03:23 +02:00
test: clear discord provider broad matchers
This commit is contained in:
@@ -102,6 +102,26 @@ function createConfigWithDiscordAccount(overrides: Record<string, unknown> = {})
|
||||
} as OpenClawConfig;
|
||||
}
|
||||
|
||||
type MockCallReader = { mock: { calls: unknown[][] } };
|
||||
|
||||
function mockMessages(mock: unknown): string[] {
|
||||
return (mock as MockCallReader).mock.calls.map((call) => String(call[0] ?? ""));
|
||||
}
|
||||
|
||||
function expectMockLogContains(mock: unknown, expected: string): void {
|
||||
expect(mockMessages(mock).some((message) => message.includes(expected))).toBe(true);
|
||||
}
|
||||
|
||||
function expectMockLogNotContains(mock: unknown, expected: string): void {
|
||||
expect(mockMessages(mock).every((message) => !message.includes(expected))).toBe(true);
|
||||
}
|
||||
|
||||
function expectMessagesContainAll(messages: string[], expected: string[]): void {
|
||||
for (const entry of expected) {
|
||||
expect(messages.some((message) => message.includes(entry))).toBe(true);
|
||||
}
|
||||
}
|
||||
|
||||
vi.mock("../voice/manager.runtime.js", () => {
|
||||
voiceRuntimeModuleLoadedMock();
|
||||
return {
|
||||
@@ -163,6 +183,21 @@ describe("monitorDiscordProvider", () => {
|
||||
return reconcileParams.healthProbe;
|
||||
};
|
||||
|
||||
const getMonitorLifecycleParams = (): {
|
||||
gatewayReadyTimeoutMs?: number;
|
||||
gatewayRuntimeReadyTimeoutMs?: number;
|
||||
} => {
|
||||
expect(monitorLifecycleMock).toHaveBeenCalledTimes(1);
|
||||
const firstCall = monitorLifecycleMock.mock.calls.at(0);
|
||||
const params = firstCall?.[0] as
|
||||
| { gatewayReadyTimeoutMs?: number; gatewayRuntimeReadyTimeoutMs?: number }
|
||||
| undefined;
|
||||
if (!params) {
|
||||
throw new Error("expected lifecycle monitor params");
|
||||
}
|
||||
return params;
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
vi.doMock("openclaw/plugin-sdk/plugin-runtime", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/plugin-runtime")>(
|
||||
@@ -330,8 +365,9 @@ describe("monitorDiscordProvider", () => {
|
||||
expect(
|
||||
emitter.emit("error", new Error("Max reconnect attempts (0) reached after code 1005")),
|
||||
).toBe(true);
|
||||
expect(runtime.error).toHaveBeenCalledWith(
|
||||
expect.stringContaining("suppressed late gateway reconnect-exhausted error after dispose"),
|
||||
expectMockLogContains(
|
||||
runtime.error,
|
||||
"suppressed late gateway reconnect-exhausted error after dispose",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -350,7 +386,7 @@ describe("monitorDiscordProvider", () => {
|
||||
expect(monitorLifecycleMock).not.toHaveBeenCalled();
|
||||
expect(createdBindingManagers).toHaveLength(1);
|
||||
expect(createdBindingManagers[0]?.stop).toHaveBeenCalledTimes(1);
|
||||
expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("identity offline"));
|
||||
expectMockLogContains(runtime.error, "identity offline");
|
||||
});
|
||||
|
||||
it("fails closed before lifecycle when Discord bot identity has no usable id", async () => {
|
||||
@@ -368,7 +404,7 @@ describe("monitorDiscordProvider", () => {
|
||||
expect(monitorLifecycleMock).not.toHaveBeenCalled();
|
||||
expect(createdBindingManagers).toHaveLength(1);
|
||||
expect(createdBindingManagers[0]?.stop).toHaveBeenCalledTimes(1);
|
||||
expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("no usable id"));
|
||||
expectMockLogContains(runtime.error, "no usable id");
|
||||
});
|
||||
|
||||
it("does not double-stop thread bindings when lifecycle performs cleanup", async () => {
|
||||
@@ -402,12 +438,9 @@ describe("monitorDiscordProvider", () => {
|
||||
runtime: baseRuntime(),
|
||||
});
|
||||
|
||||
expect(monitorLifecycleMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
gatewayReadyTimeoutMs: 90_000,
|
||||
gatewayRuntimeReadyTimeoutMs: 120_000,
|
||||
}),
|
||||
);
|
||||
const lifecycleParams = getMonitorLifecycleParams();
|
||||
expect(lifecycleParams.gatewayReadyTimeoutMs).toBe(90_000);
|
||||
expect(lifecycleParams.gatewayRuntimeReadyTimeoutMs).toBe(120_000);
|
||||
});
|
||||
|
||||
it("does not load the Discord voice runtime when voice is disabled", async () => {
|
||||
@@ -852,9 +885,7 @@ describe("monitorDiscordProvider", () => {
|
||||
|
||||
await vi.waitFor(() => expect(clientDeployCommandsMock).toHaveBeenCalledTimes(1));
|
||||
expect(monitorLifecycleMock).toHaveBeenCalledTimes(1);
|
||||
expect(runtime.error).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining("failed to deploy native commands"),
|
||||
);
|
||||
expectMockLogNotContains(runtime.error, "failed to deploy native commands");
|
||||
expect(
|
||||
vi
|
||||
.mocked(runtime.log)
|
||||
@@ -908,9 +939,7 @@ describe("monitorDiscordProvider", () => {
|
||||
expect(warningMessages[0]).toContain("retry after 0s");
|
||||
expect(warningMessages[0]).toContain("Message send/receive is unaffected.");
|
||||
expect(warningMessages[0]).not.toContain("body=");
|
||||
expect(runtime.error).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining("native-slash-command-deploy-rest"),
|
||||
);
|
||||
expectMockLogNotContains(runtime.error, "native-slash-command-deploy-rest");
|
||||
});
|
||||
|
||||
it("formats Discord deploy rate limits without raw response bodies", () => {
|
||||
@@ -985,11 +1014,10 @@ describe("monitorDiscordProvider", () => {
|
||||
|
||||
await vi.waitFor(() => expect(clientDeployCommandsMock).toHaveBeenCalledTimes(1));
|
||||
expect(clientDeployCommandsMock).toHaveBeenCalledWith({ mode: "reconcile" });
|
||||
expect(getConstructedClientOptions().requestOptions).toMatchObject({
|
||||
timeout: 15_000,
|
||||
runtimeProfile: "persistent",
|
||||
maxQueueSize: 1000,
|
||||
});
|
||||
const requestOptions = getConstructedClientOptions().requestOptions;
|
||||
expect(requestOptions?.timeout).toBe(15_000);
|
||||
expect(requestOptions?.runtimeProfile).toBe("persistent");
|
||||
expect(requestOptions?.maxQueueSize).toBe(1000);
|
||||
expect(getConstructedClientOptions().eventQueue?.listenerTimeout).toBe(120_000);
|
||||
});
|
||||
|
||||
@@ -1017,9 +1045,7 @@ describe("monitorDiscordProvider", () => {
|
||||
expect(listNativeCommandSpecsForConfigMock).not.toHaveBeenCalled();
|
||||
expect(getPluginCommandSpecsMock).not.toHaveBeenCalled();
|
||||
expect(clientDeployCommandsMock).not.toHaveBeenCalled();
|
||||
expect(runtime.log).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining("cleared native commands"),
|
||||
);
|
||||
expectMockLogNotContains(runtime.log, "cleared native commands");
|
||||
});
|
||||
|
||||
it("derives application id from token before probing Discord over REST", async () => {
|
||||
@@ -1082,8 +1108,9 @@ describe("monitorDiscordProvider", () => {
|
||||
setStatus,
|
||||
});
|
||||
|
||||
expect(setStatus.mock.calls).toContainEqual([expect.objectContaining({ connected: true })]);
|
||||
expect(setStatus.mock.calls).toContainEqual([expect.objectContaining({ connected: false })]);
|
||||
const statuses = setStatus.mock.calls.map((call) => call[0] as { connected?: boolean });
|
||||
expect(statuses.some((status) => status.connected === true)).toBe(true);
|
||||
expect(statuses.some((status) => status.connected === false)).toBe(true);
|
||||
});
|
||||
|
||||
it("logs Discord startup phases and early gateway debug events", async () => {
|
||||
@@ -1104,27 +1131,21 @@ describe("monitorDiscordProvider", () => {
|
||||
runtime,
|
||||
});
|
||||
|
||||
await vi.waitFor(() =>
|
||||
expect(vi.mocked(runtime.log).mock.calls.map((call) => String(call[0]))).toEqual(
|
||||
expect.arrayContaining([expect.stringContaining("deploy-commands:done")]),
|
||||
),
|
||||
);
|
||||
await vi.waitFor(() => expectMockLogContains(runtime.log, "deploy-commands:done"));
|
||||
|
||||
const messages = vi.mocked(runtime.log).mock.calls.map((call) => String(call[0]));
|
||||
expect(messages).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.stringContaining("fetch-application-id:start"),
|
||||
expect.stringContaining("fetch-application-id:done"),
|
||||
expect.stringContaining("deploy-commands:schedule"),
|
||||
expect.stringContaining("deploy-commands:scheduled"),
|
||||
expect.stringContaining("deploy-commands:done"),
|
||||
expect.stringContaining("fetch-bot-identity:start"),
|
||||
expect.stringContaining("fetch-bot-identity:done"),
|
||||
]),
|
||||
);
|
||||
expect(messages).toEqual(
|
||||
expect.arrayContaining([expect.stringMatching(/gateway-debug.*Gateway websocket opened/)]),
|
||||
);
|
||||
expectMessagesContainAll(messages, [
|
||||
"fetch-application-id:start",
|
||||
"fetch-application-id:done",
|
||||
"deploy-commands:schedule",
|
||||
"deploy-commands:scheduled",
|
||||
"deploy-commands:done",
|
||||
"fetch-bot-identity:start",
|
||||
"fetch-bot-identity:done",
|
||||
]);
|
||||
expect(
|
||||
messages.some((message) => /gateway-debug.*Gateway websocket opened/.test(message)),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps Discord startup chatter quiet by default", async () => {
|
||||
@@ -1136,8 +1157,6 @@ describe("monitorDiscordProvider", () => {
|
||||
});
|
||||
|
||||
const messages = vi.mocked(runtime.log).mock.calls.map((call) => String(call[0]));
|
||||
expect(messages).not.toEqual(
|
||||
expect.arrayContaining([expect.stringContaining("discord startup [")]),
|
||||
);
|
||||
expect(messages.every((message) => !message.includes("discord startup ["))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user