mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 20:05:46 -06:00
test: clear discord lifecycle broad matchers
This commit is contained in:
@@ -184,6 +184,35 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
expect(params.gatewaySupervisor.detachLifecycle).toHaveBeenCalledTimes(params.detachCalls ?? 1);
|
||||
}
|
||||
|
||||
function mockMessages(mock: ReturnType<typeof vi.fn>): string[] {
|
||||
return mock.mock.calls.map((call) => String(call[0] ?? ""));
|
||||
}
|
||||
|
||||
function expectMockMessageContains(mock: ReturnType<typeof vi.fn>, expected: string): void {
|
||||
expect(mockMessages(mock).some((message) => message.includes(expected))).toBe(true);
|
||||
}
|
||||
|
||||
function expectMockMessageNotContains(mock: ReturnType<typeof vi.fn>, expected: string): void {
|
||||
expect(mockMessages(mock).every((message) => !message.includes(expected))).toBe(true);
|
||||
}
|
||||
|
||||
type StatusPatch = {
|
||||
connected?: boolean;
|
||||
lastDisconnect?: null | Record<string, unknown>;
|
||||
lastError?: string | null;
|
||||
};
|
||||
|
||||
function statusPatches(statusSink: ReturnType<typeof vi.fn>): StatusPatch[] {
|
||||
return statusSink.mock.calls.map((call) => call[0] as StatusPatch);
|
||||
}
|
||||
|
||||
function expectStatusPatch(
|
||||
statusSink: ReturnType<typeof vi.fn>,
|
||||
predicate: (patch: StatusPatch) => boolean,
|
||||
): void {
|
||||
expect(statusPatches(statusSink).some(predicate)).toBe(true);
|
||||
}
|
||||
|
||||
it("resolves gateway READY timeouts from config, env, then defaults", () => {
|
||||
expect(resolveDiscordGatewayReadyTimeoutMs({ configuredTimeoutMs: 45_000 })).toBe(45_000);
|
||||
expect(
|
||||
@@ -240,11 +269,9 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
const { lifecycleParams, statusSink } = createLifecycleHarness({ gateway });
|
||||
await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
|
||||
|
||||
expect(statusSink).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
connected: true,
|
||||
lastDisconnect: null,
|
||||
}),
|
||||
expectStatusPatch(
|
||||
statusSink,
|
||||
(patch) => patch.connected === true && patch.lastDisconnect === null,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -266,11 +293,7 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
await expect(lifecyclePromise).rejects.toThrow(
|
||||
"discord gateway did not reach READY within 5000ms",
|
||||
);
|
||||
expect(statusSink).not.toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
connected: true,
|
||||
}),
|
||||
);
|
||||
expect(statusPatches(statusSink).every((patch) => patch.connected !== true)).toBe(true);
|
||||
expectLifecycleCleanup({
|
||||
threadStop,
|
||||
waitCalls: 0,
|
||||
@@ -352,21 +375,18 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
await vi.advanceTimersByTimeAsync(18_500);
|
||||
await expect(lifecyclePromise).resolves.toBeUndefined();
|
||||
|
||||
expect(runtimeError).toHaveBeenCalledWith(
|
||||
expect.stringContaining("gateway READY wait timed out after 15000ms"),
|
||||
);
|
||||
expect(runtimeError).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining("gateway was not ready after 15000ms; restarting gateway"),
|
||||
expectMockMessageContains(runtimeError, "gateway READY wait timed out after 15000ms");
|
||||
expectMockMessageNotContains(
|
||||
runtimeError,
|
||||
"gateway was not ready after 15000ms; restarting gateway",
|
||||
);
|
||||
expect(gateway.disconnect).toHaveBeenCalledTimes(1);
|
||||
expect(gateway.connect).toHaveBeenCalledTimes(1);
|
||||
expect(gateway.connect).toHaveBeenCalledWith(false);
|
||||
expect(statusSink).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
connected: true,
|
||||
lastDisconnect: null,
|
||||
lastError: null,
|
||||
}),
|
||||
expectStatusPatch(
|
||||
statusSink,
|
||||
(patch) =>
|
||||
patch.connected === true && patch.lastDisconnect === null && patch.lastError === null,
|
||||
);
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
@@ -447,9 +467,7 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
|
||||
await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
|
||||
|
||||
expect(runtimeError).toHaveBeenCalledWith(
|
||||
expect.stringContaining("discord: gateway closed with code 4014"),
|
||||
);
|
||||
expectMockMessageContains(runtimeError, "discord: gateway closed with code 4014");
|
||||
expectLifecycleCleanup({
|
||||
threadStop,
|
||||
waitCalls: 0,
|
||||
@@ -466,8 +484,9 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
|
||||
await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
|
||||
|
||||
expect(runtimeError).toHaveBeenCalledWith(
|
||||
expect.stringContaining("discord gateway error: Error: transient startup error"),
|
||||
expectMockMessageContains(
|
||||
runtimeError,
|
||||
"discord gateway error: Error: transient startup error",
|
||||
);
|
||||
expectLifecycleCleanup({
|
||||
threadStop,
|
||||
@@ -550,15 +569,15 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
|
||||
|
||||
expect(gatewaySupervisor.attachLifecycle).toHaveBeenCalledTimes(1);
|
||||
expect(runtimeLog).toHaveBeenCalledWith(
|
||||
expect.stringContaining("treating reconnect-exhausted during expected shutdown as clean"),
|
||||
expectMockMessageContains(
|
||||
runtimeLog,
|
||||
"treating reconnect-exhausted during expected shutdown as clean",
|
||||
);
|
||||
expect(runtimeLog).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Max reconnect attempts (50) reached after close code 1005"),
|
||||
);
|
||||
expect(runtimeError).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining("discord gateway reconnect-exhausted"),
|
||||
expectMockMessageContains(
|
||||
runtimeLog,
|
||||
"Max reconnect attempts (50) reached after close code 1005",
|
||||
);
|
||||
expectMockMessageNotContains(runtimeError, "discord gateway reconnect-exhausted");
|
||||
expectLifecycleCleanup({
|
||||
threadStop,
|
||||
waitCalls: 1,
|
||||
@@ -590,8 +609,9 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
await expect(lifecyclePromise).rejects.toThrow(
|
||||
"discord gateway fatal: Error: Fatal Gateway error: 4001",
|
||||
);
|
||||
expect(runtimeError).toHaveBeenCalledWith(
|
||||
expect.stringContaining("discord gateway fatal: Error: Fatal Gateway error: 4001"),
|
||||
expectMockMessageContains(
|
||||
runtimeError,
|
||||
"discord gateway fatal: Error: Fatal Gateway error: 4001",
|
||||
);
|
||||
expect(gateway.disconnect).not.toHaveBeenCalled();
|
||||
expect(gateway.connect).not.toHaveBeenCalled();
|
||||
@@ -617,11 +637,12 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
|
||||
await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
|
||||
|
||||
expect(statusSink).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
connected: false,
|
||||
lastDisconnect: expect.objectContaining({ status: 1006 }),
|
||||
}),
|
||||
expectStatusPatch(
|
||||
statusSink,
|
||||
(patch) =>
|
||||
patch.connected === false &&
|
||||
patch.lastDisconnect !== null &&
|
||||
patch.lastDisconnect?.status === 1006,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -637,11 +658,11 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
|
||||
await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
|
||||
|
||||
expect(statusSink).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
connected: false,
|
||||
lastError: "Gateway reconnect scheduled in 1000ms (zombie, resume=true)",
|
||||
}),
|
||||
expectStatusPatch(
|
||||
statusSink,
|
||||
(patch) =>
|
||||
patch.connected === false &&
|
||||
patch.lastError === "Gateway reconnect scheduled in 1000ms (zombie, resume=true)",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -664,12 +685,10 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
|
||||
await expect(runDiscordGatewayLifecycle(lifecycleParams)).resolves.toBeUndefined();
|
||||
|
||||
expect(statusSink).toHaveBeenCalledWith(expect.objectContaining({ connected: false }));
|
||||
expect(statusSink).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
connected: true,
|
||||
lastDisconnect: null,
|
||||
}),
|
||||
expectStatusPatch(statusSink, (patch) => patch.connected === false);
|
||||
expectStatusPatch(
|
||||
statusSink,
|
||||
(patch) => patch.connected === true && patch.lastDisconnect === null,
|
||||
);
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
@@ -700,14 +719,13 @@ describe("runDiscordGatewayLifecycle", () => {
|
||||
await expect(lifecyclePromise).rejects.toThrow(
|
||||
"discord gateway opened but did not reach READY within 5000ms",
|
||||
);
|
||||
expect(runtimeError).toHaveBeenCalledWith(
|
||||
expect.stringContaining("did not reach READY within 5000ms"),
|
||||
);
|
||||
expect(statusSink).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
connected: false,
|
||||
lastDisconnect: expect.objectContaining({ error: "runtime-not-ready" }),
|
||||
}),
|
||||
expectMockMessageContains(runtimeError, "did not reach READY within 5000ms");
|
||||
expectStatusPatch(
|
||||
statusSink,
|
||||
(patch) =>
|
||||
patch.connected === false &&
|
||||
patch.lastDisconnect !== null &&
|
||||
patch.lastDisconnect?.error === "runtime-not-ready",
|
||||
);
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
|
||||
Reference in New Issue
Block a user