mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-13 17:07:40 +00:00
refactor(agents): remove catalog browse timer test hooks
This commit is contained in:
@@ -6,13 +6,11 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { MAX_TIMER_TIMEOUT_MS } from "../shared/number-coercion.js";
|
||||
import {
|
||||
DEFAULT_MODEL_CATALOG_BROWSE_TIMEOUT_MS,
|
||||
loadModelCatalogForBrowse,
|
||||
restoreModelCatalogBrowseTestDeps,
|
||||
setModelCatalogBrowseTestDeps,
|
||||
} from "./model-catalog-browse.js";
|
||||
import type { ModelCatalogEntry } from "./model-catalog.types.js";
|
||||
|
||||
const DEFAULT_MODEL_CATALOG_BROWSE_TIMEOUT_MS = 750;
|
||||
const readOnlyCatalog: ModelCatalogEntry[] = [
|
||||
{ id: "gpt-readonly", name: "GPT Readonly", provider: "openai" },
|
||||
];
|
||||
@@ -41,7 +39,6 @@ describe("loadModelCatalogForBrowse", () => {
|
||||
vi.clearAllTimers();
|
||||
vi.restoreAllMocks();
|
||||
vi.useRealTimers();
|
||||
restoreModelCatalogBrowseTestDeps();
|
||||
});
|
||||
|
||||
it("uses the read-only catalog for default browse views", async () => {
|
||||
@@ -97,16 +94,8 @@ describe("loadModelCatalogForBrowse", () => {
|
||||
});
|
||||
|
||||
it("returns an empty catalog when read-only catalog loading times out with provider wildcards", async () => {
|
||||
vi.useFakeTimers();
|
||||
const onTimeout = vi.fn();
|
||||
const timeoutHandle = { unref: vi.fn() } as unknown as NodeJS.Timeout;
|
||||
const clearTimeout = vi.fn();
|
||||
setModelCatalogBrowseTestDeps({
|
||||
setTimeout: vi.fn((callback: () => void) => {
|
||||
queueMicrotask(callback);
|
||||
return timeoutHandle;
|
||||
}) as unknown as typeof globalThis.setTimeout,
|
||||
clearTimeout: clearTimeout as unknown as typeof globalThis.clearTimeout,
|
||||
});
|
||||
const loadCatalog = vi.fn(() => new Promise<ModelCatalogEntry[]>(() => {}));
|
||||
|
||||
const resultPromise = loadModelCatalogForBrowse({
|
||||
@@ -116,21 +105,15 @@ describe("loadModelCatalogForBrowse", () => {
|
||||
onTimeout,
|
||||
});
|
||||
|
||||
await vi.advanceTimersByTimeAsync(5);
|
||||
await expect(resultPromise).resolves.toEqual([]);
|
||||
expect(onTimeout).toHaveBeenCalledExactlyOnceWith(5);
|
||||
expect(timeoutHandle["unref"]).toHaveBeenCalledOnce();
|
||||
expect(clearTimeout).toHaveBeenCalledExactlyOnceWith(timeoutHandle);
|
||||
});
|
||||
|
||||
it("uses the default timeout when timeoutMs is non-finite", async () => {
|
||||
const onTimeout = vi.fn();
|
||||
const timeoutHandle = { unref: vi.fn() } as unknown as NodeJS.Timeout;
|
||||
const setTimeout = vi.fn(() => timeoutHandle);
|
||||
const clearTimeout = vi.fn();
|
||||
setModelCatalogBrowseTestDeps({
|
||||
setTimeout: setTimeout as unknown as typeof globalThis.setTimeout,
|
||||
clearTimeout: clearTimeout as unknown as typeof globalThis.clearTimeout,
|
||||
});
|
||||
const setTimeout = vi.spyOn(globalThis, "setTimeout");
|
||||
const clearTimeout = vi.spyOn(globalThis, "clearTimeout");
|
||||
const loadCatalog = vi.fn(async () => readOnlyCatalog);
|
||||
|
||||
const resultPromise = loadModelCatalogForBrowse({
|
||||
@@ -145,18 +128,13 @@ describe("loadModelCatalogForBrowse", () => {
|
||||
expect.any(Function),
|
||||
DEFAULT_MODEL_CATALOG_BROWSE_TIMEOUT_MS,
|
||||
);
|
||||
expect(clearTimeout).toHaveBeenCalledExactlyOnceWith(timeoutHandle);
|
||||
expect(clearTimeout).toHaveBeenCalledOnce();
|
||||
expect(onTimeout).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("caps oversized browse timeouts before scheduling the fallback timer", async () => {
|
||||
const timeoutHandle = { unref: vi.fn() } as unknown as NodeJS.Timeout;
|
||||
const setTimeout = vi.fn(() => timeoutHandle);
|
||||
const clearTimeout = vi.fn();
|
||||
setModelCatalogBrowseTestDeps({
|
||||
setTimeout: setTimeout as unknown as typeof globalThis.setTimeout,
|
||||
clearTimeout: clearTimeout as unknown as typeof globalThis.clearTimeout,
|
||||
});
|
||||
const setTimeout = vi.spyOn(globalThis, "setTimeout");
|
||||
const clearTimeout = vi.spyOn(globalThis, "clearTimeout");
|
||||
const loadCatalog = vi.fn(async () => readOnlyCatalog);
|
||||
|
||||
const resultPromise = loadModelCatalogForBrowse({
|
||||
@@ -167,6 +145,6 @@ describe("loadModelCatalogForBrowse", () => {
|
||||
|
||||
await expect(resultPromise).resolves.toBe(readOnlyCatalog);
|
||||
expect(setTimeout).toHaveBeenCalledExactlyOnceWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS);
|
||||
expect(clearTimeout).toHaveBeenCalledExactlyOnceWith(timeoutHandle);
|
||||
expect(clearTimeout).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,29 +13,11 @@ import { parseConfiguredModelVisibilityEntries } from "./model-selection-shared.
|
||||
* Loads the model catalog shape used by browse/list commands without letting optional
|
||||
* provider discovery stall the CLI path.
|
||||
*/
|
||||
export const DEFAULT_MODEL_CATALOG_BROWSE_TIMEOUT_MS = 750;
|
||||
const DEFAULT_MODEL_CATALOG_BROWSE_TIMEOUT_MS = 750;
|
||||
|
||||
/** Visible model subset requested by model browse callers. */
|
||||
export type ModelCatalogBrowseView = "default" | "configured" | "all";
|
||||
|
||||
const modelCatalogBrowseDeps = {
|
||||
setTimeout: globalThis.setTimeout,
|
||||
clearTimeout: globalThis.clearTimeout,
|
||||
};
|
||||
|
||||
/** Replaces timer hooks for deterministic timeout tests. */
|
||||
export function setModelCatalogBrowseTestDeps(
|
||||
overrides: Partial<typeof modelCatalogBrowseDeps>,
|
||||
): void {
|
||||
Object.assign(modelCatalogBrowseDeps, overrides);
|
||||
}
|
||||
|
||||
/** Restores global timer hooks after catalog browse timeout tests. */
|
||||
export function restoreModelCatalogBrowseTestDeps(): void {
|
||||
modelCatalogBrowseDeps.setTimeout = globalThis.setTimeout;
|
||||
modelCatalogBrowseDeps.clearTimeout = globalThis.clearTimeout;
|
||||
}
|
||||
|
||||
/** True when a browse view cannot be answered from read-only cached catalog entries. */
|
||||
export function modelCatalogBrowseRequiresFullDiscovery(params: {
|
||||
cfg: OpenClawConfig;
|
||||
@@ -74,7 +56,7 @@ export async function loadModelCatalogForBrowse(params: {
|
||||
const timedOut = Symbol("model-catalog-browse-timeout");
|
||||
const catalogPromise = params.loadCatalog({ readOnly: true });
|
||||
const timeoutPromise = new Promise<typeof timedOut>((resolve) => {
|
||||
timeout = modelCatalogBrowseDeps.setTimeout(() => resolve(timedOut), timeoutMs);
|
||||
timeout = globalThis.setTimeout(() => resolve(timedOut), timeoutMs);
|
||||
timeout.unref?.();
|
||||
});
|
||||
|
||||
@@ -89,7 +71,7 @@ export async function loadModelCatalogForBrowse(params: {
|
||||
return result;
|
||||
} finally {
|
||||
if (timeout) {
|
||||
modelCatalogBrowseDeps.clearTimeout(timeout);
|
||||
globalThis.clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user