From 4f4288e3b5be2e55abfce5213f0bcf182a252f5e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 24 Apr 2026 16:07:53 +0100 Subject: [PATCH] test: speed zalo polling waits --- .../zalo/src/monitor.image.polling.test.ts | 9 +++-- extensions/zalo/src/monitor.lifecycle.test.ts | 37 ++++++++++++++++--- .../src/monitor.polling.media-reply.test.ts | 13 +++++-- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/extensions/zalo/src/monitor.image.polling.test.ts b/extensions/zalo/src/monitor.image.polling.test.ts index 72878c72a72..a9fa7f4ec8d 100644 --- a/extensions/zalo/src/monitor.image.polling.test.ts +++ b/extensions/zalo/src/monitor.image.polling.test.ts @@ -1,10 +1,11 @@ -import { afterAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterAll, beforeEach, describe, expect, it } from "vitest"; import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import { createImageLifecycleCore, createImageUpdate, createLifecycleMonitorSetup, expectImageLifecycleDelivery, + settleAsyncWork, } from "../test-support/lifecycle-test-support.js"; import { getUpdatesMock, @@ -55,7 +56,8 @@ describe("Zalo polling image handling", () => { abortSignal: abort.signal, }); - await vi.waitFor(() => expect(fetchRemoteMediaMock).toHaveBeenCalledTimes(1)); + await settleAsyncWork(); + expect(fetchRemoteMediaMock).toHaveBeenCalledTimes(1); expectImageLifecycleDelivery({ fetchRemoteMediaMock, saveMediaBufferMock, @@ -95,7 +97,8 @@ describe("Zalo polling image handling", () => { abortSignal: abort.signal, }); - await vi.waitFor(() => expect(sendMessageMock).toHaveBeenCalledTimes(1)); + await settleAsyncWork(); + expect(sendMessageMock).toHaveBeenCalledTimes(1); expect(fetchRemoteMediaMock).not.toHaveBeenCalled(); expect(saveMediaBufferMock).not.toHaveBeenCalled(); expect(finalizeInboundContextMock).not.toHaveBeenCalled(); diff --git a/extensions/zalo/src/monitor.lifecycle.test.ts b/extensions/zalo/src/monitor.lifecycle.test.ts index f526e5e81fd..688a67b0d15 100644 --- a/extensions/zalo/src/monitor.lifecycle.test.ts +++ b/extensions/zalo/src/monitor.lifecycle.test.ts @@ -36,6 +36,13 @@ const TEST_ACCOUNT = { const TEST_CONFIG = {} as OpenClawConfig; +async function settleLifecycleWork(): Promise { + for (let i = 0; i < 6; i += 1) { + await Promise.resolve(); + await new Promise((resolve) => setImmediate(resolve)); + } +} + async function startLifecycleMonitor( options: { useWebhook?: boolean; @@ -70,7 +77,8 @@ describe("monitorZaloProvider lifecycle", () => { settled = true; }); - await vi.waitFor(() => expect(getUpdatesMock).toHaveBeenCalledTimes(1)); + await settleLifecycleWork(); + expect(getUpdatesMock).toHaveBeenCalledTimes(1); expect(getWebhookInfoMock).toHaveBeenCalledTimes(1); expect(deleteWebhookMock).not.toHaveBeenCalled(); @@ -94,7 +102,8 @@ describe("monitorZaloProvider lifecycle", () => { const { abort, runtime, run } = await startLifecycleMonitor(); - await vi.waitFor(() => expect(getUpdatesMock).toHaveBeenCalledTimes(1)); + await settleLifecycleWork(); + expect(getUpdatesMock).toHaveBeenCalledTimes(1); expect(getWebhookInfoMock).toHaveBeenCalledTimes(1); expect(deleteWebhookMock).toHaveBeenCalledTimes(1); @@ -112,7 +121,8 @@ describe("monitorZaloProvider lifecycle", () => { const { abort, runtime, run } = await startLifecycleMonitor(); - await vi.waitFor(() => expect(getUpdatesMock).toHaveBeenCalledTimes(1)); + await settleLifecycleWork(); + expect(getUpdatesMock).toHaveBeenCalledTimes(1); expect(getWebhookInfoMock).toHaveBeenCalledTimes(1); expect(deleteWebhookMock).not.toHaveBeenCalled(); @@ -129,10 +139,24 @@ describe("monitorZaloProvider lifecycle", () => { const registry = createEmptyPluginRegistry(); setActivePluginRegistry(registry); + let resolveSetWebhookCalled: (() => void) | undefined; + const setWebhookCalled = new Promise((resolve) => { + resolveSetWebhookCalled = resolve; + }); + setWebhookMock.mockImplementationOnce(async () => { + resolveSetWebhookCalled?.(); + return { ok: true, result: { url: "" } }; + }); + + let resolveDeleteWebhookCalled: (() => void) | undefined; + const deleteWebhookCalled = new Promise((resolve) => { + resolveDeleteWebhookCalled = resolve; + }); let resolveDeleteWebhook: (() => void) | undefined; deleteWebhookMock.mockImplementationOnce( () => new Promise((resolve) => { + resolveDeleteWebhookCalled?.(); resolveDeleteWebhook = () => resolve({ ok: true, result: { url: "" } }); }), ); @@ -147,12 +171,15 @@ describe("monitorZaloProvider lifecycle", () => { settled = true; }); - await vi.waitFor(() => expect(setWebhookMock).toHaveBeenCalledTimes(1), { timeout: 5_000 }); + await setWebhookCalled; + await settleLifecycleWork(); + expect(setWebhookMock).toHaveBeenCalledTimes(1); expect(registry.httpRoutes).toHaveLength(2); abort.abort(); - await vi.waitFor(() => expect(deleteWebhookMock).toHaveBeenCalledTimes(1), { timeout: 5000 }); + await deleteWebhookCalled; + expect(deleteWebhookMock).toHaveBeenCalledTimes(1); expect(deleteWebhookMock).toHaveBeenCalledWith("test-token", undefined, 5000); expect(settled).toBe(false); expect(registry.httpRoutes).toHaveLength(2); diff --git a/extensions/zalo/src/monitor.polling.media-reply.test.ts b/extensions/zalo/src/monitor.polling.media-reply.test.ts index 7344ba52373..5cbec6781a3 100644 --- a/extensions/zalo/src/monitor.polling.media-reply.test.ts +++ b/extensions/zalo/src/monitor.polling.media-reply.test.ts @@ -6,6 +6,7 @@ import type { PluginRuntime } from "../runtime-api.js"; import { createLifecycleMonitorSetup, createTextUpdate, + settleAsyncWork, } from "../test-support/lifecycle-test-support.js"; import { getUpdatesMock, @@ -114,7 +115,8 @@ describe("Zalo polling media replies", () => { }); try { - await vi.waitFor(() => expect(sendPhotoMock).toHaveBeenCalledTimes(1)); + await settleAsyncWork(); + expect(sendPhotoMock).toHaveBeenCalledTimes(1); expect(registry.httpRoutes).toHaveLength(1); expect(prepareHostedZaloMediaUrlMock).toHaveBeenCalledWith({ @@ -176,7 +178,8 @@ describe("Zalo polling media replies", () => { }); try { - await vi.waitFor(() => expect(sendPhotoMock).toHaveBeenCalledTimes(1)); + await settleAsyncWork(); + expect(sendPhotoMock).toHaveBeenCalledTimes(1); expect(prepareHostedZaloMediaUrlMock).not.toHaveBeenCalled(); expect(sendPhotoMock).toHaveBeenCalledWith( @@ -223,7 +226,8 @@ describe("Zalo polling media replies", () => { let secondRun: Promise | undefined; try { - await vi.waitFor(() => expect(firstRegistry.httpRoutes).toHaveLength(1)); + await settleAsyncWork(); + expect(firstRegistry.httpRoutes).toHaveLength(1); setActivePluginRegistry(secondRegistry); secondRun = monitorZaloProvider({ @@ -234,7 +238,8 @@ describe("Zalo polling media replies", () => { abortSignal: secondAbort.signal, }); - await vi.waitFor(() => expect(secondRegistry.httpRoutes).toHaveLength(1)); + await settleAsyncWork(); + expect(secondRegistry.httpRoutes).toHaveLength(1); } finally { firstAbort.abort(); secondAbort.abort();