mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-28 01:21:36 +00:00
test: dedupe plugin provider runtime suites
This commit is contained in:
@@ -24,20 +24,27 @@ describe("gateway request scope", () => {
|
||||
});
|
||||
}
|
||||
|
||||
function expectGatewayScope(
|
||||
runtimeScope: Awaited<ReturnType<typeof importGatewayRequestScopeModule>>,
|
||||
expected: PluginRuntimeGatewayRequestScope,
|
||||
) {
|
||||
expect(runtimeScope.getPluginRuntimeGatewayRequestScope()).toEqual(expected);
|
||||
}
|
||||
|
||||
it("reuses AsyncLocalStorage across reloaded module instances", async () => {
|
||||
const first = await importGatewayRequestScopeModule();
|
||||
|
||||
await first.withPluginRuntimeGatewayRequestScope(TEST_SCOPE, async () => {
|
||||
vi.resetModules();
|
||||
const second = await importGatewayRequestScopeModule();
|
||||
expect(second.getPluginRuntimeGatewayRequestScope()).toEqual(TEST_SCOPE);
|
||||
expectGatewayScope(second, TEST_SCOPE);
|
||||
});
|
||||
});
|
||||
|
||||
it("attaches plugin id to the active scope", async () => {
|
||||
await withTestGatewayScope(async (runtimeScope) => {
|
||||
await runtimeScope.withPluginRuntimePluginIdScope("voice-call", async () => {
|
||||
expect(runtimeScope.getPluginRuntimeGatewayRequestScope()).toEqual({
|
||||
expectGatewayScope(runtimeScope, {
|
||||
...TEST_SCOPE,
|
||||
pluginId: "voice-call",
|
||||
});
|
||||
|
||||
@@ -50,6 +50,12 @@ function expectGatewaySubagentRunFailure(
|
||||
);
|
||||
}
|
||||
|
||||
function expectFunctionKeys(value: Record<string, unknown>, keys: readonly string[]) {
|
||||
keys.forEach((key) => {
|
||||
expect(typeof value[key]).toBe("function");
|
||||
});
|
||||
}
|
||||
|
||||
describe("plugin runtime command execution", () => {
|
||||
beforeEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
@@ -96,10 +102,12 @@ describe("plugin runtime command execution", () => {
|
||||
{
|
||||
name: "exposes runtime.mediaUnderstanding helpers and keeps stt as an alias",
|
||||
assert: (runtime: ReturnType<typeof createPluginRuntime>) => {
|
||||
expect(typeof runtime.mediaUnderstanding.runFile).toBe("function");
|
||||
expect(typeof runtime.mediaUnderstanding.describeImageFile).toBe("function");
|
||||
expect(typeof runtime.mediaUnderstanding.describeImageFileWithModel).toBe("function");
|
||||
expect(typeof runtime.mediaUnderstanding.describeVideoFile).toBe("function");
|
||||
expectFunctionKeys(runtime.mediaUnderstanding as Record<string, unknown>, [
|
||||
"runFile",
|
||||
"describeImageFile",
|
||||
"describeImageFileWithModel",
|
||||
"describeVideoFile",
|
||||
]);
|
||||
expect(runtime.mediaUnderstanding.transcribeAudioFile).toBe(
|
||||
runtime.stt.transcribeAudioFile,
|
||||
);
|
||||
@@ -108,15 +116,19 @@ describe("plugin runtime command execution", () => {
|
||||
{
|
||||
name: "exposes runtime.imageGeneration helpers",
|
||||
assert: (runtime: ReturnType<typeof createPluginRuntime>) => {
|
||||
expect(typeof runtime.imageGeneration.generate).toBe("function");
|
||||
expect(typeof runtime.imageGeneration.listProviders).toBe("function");
|
||||
expectFunctionKeys(runtime.imageGeneration as Record<string, unknown>, [
|
||||
"generate",
|
||||
"listProviders",
|
||||
]);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "exposes runtime.webSearch helpers",
|
||||
assert: (runtime: ReturnType<typeof createPluginRuntime>) => {
|
||||
expect(typeof runtime.webSearch.listProviders).toBe("function");
|
||||
expect(typeof runtime.webSearch.search).toBe("function");
|
||||
expectFunctionKeys(runtime.webSearch as Record<string, unknown>, [
|
||||
"listProviders",
|
||||
"search",
|
||||
]);
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -126,17 +138,23 @@ describe("plugin runtime command execution", () => {
|
||||
model: DEFAULT_MODEL,
|
||||
provider: DEFAULT_PROVIDER,
|
||||
});
|
||||
expect(typeof runtime.agent.runEmbeddedPiAgent).toBe("function");
|
||||
expect(typeof runtime.agent.resolveAgentDir).toBe("function");
|
||||
expect(typeof runtime.agent.session.resolveSessionFilePath).toBe("function");
|
||||
expectFunctionKeys(runtime.agent as Record<string, unknown>, [
|
||||
"runEmbeddedPiAgent",
|
||||
"resolveAgentDir",
|
||||
]);
|
||||
expectFunctionKeys(runtime.agent.session as Record<string, unknown>, [
|
||||
"resolveSessionFilePath",
|
||||
]);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "exposes runtime.modelAuth with getApiKeyForModel and resolveApiKeyForProvider",
|
||||
assert: (runtime: ReturnType<typeof createPluginRuntime>) => {
|
||||
expect(runtime.modelAuth).toBeDefined();
|
||||
expect(typeof runtime.modelAuth.getApiKeyForModel).toBe("function");
|
||||
expect(typeof runtime.modelAuth.resolveApiKeyForProvider).toBe("function");
|
||||
expectFunctionKeys(runtime.modelAuth as Record<string, unknown>, [
|
||||
"getApiKeyForModel",
|
||||
"resolveApiKeyForProvider",
|
||||
]);
|
||||
},
|
||||
},
|
||||
] as const)("$name", ({ assert }) => {
|
||||
|
||||
@@ -23,6 +23,13 @@ function buildTelegramTypingParams(
|
||||
};
|
||||
}
|
||||
|
||||
function expectTelegramPulseCount(
|
||||
pulse: ReturnType<typeof vi.fn<() => Promise<unknown>>>,
|
||||
expected: number,
|
||||
) {
|
||||
expect(pulse).toHaveBeenCalledTimes(expected);
|
||||
}
|
||||
|
||||
describe("createTelegramTypingLease", () => {
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
@@ -65,11 +72,11 @@ describe("createTelegramTypingLease", () => {
|
||||
pulse,
|
||||
});
|
||||
|
||||
expect(pulse).toHaveBeenCalledTimes(1);
|
||||
expectTelegramPulseCount(pulse, 1);
|
||||
await vi.advanceTimersByTimeAsync(TELEGRAM_TYPING_DEFAULT_INTERVAL_MS - 1);
|
||||
expect(pulse).toHaveBeenCalledTimes(1);
|
||||
expectTelegramPulseCount(pulse, 1);
|
||||
await vi.advanceTimersByTimeAsync(1);
|
||||
expect(pulse).toHaveBeenCalledTimes(2);
|
||||
expectTelegramPulseCount(pulse, 2);
|
||||
|
||||
lease.stop();
|
||||
});
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { expect, vi } from "vitest";
|
||||
|
||||
function expectPulseCount(pulse: { mock: { calls: unknown[] } }, expected: number) {
|
||||
expect(pulse.mock.calls).toHaveLength(expected);
|
||||
}
|
||||
|
||||
export async function expectIndependentTypingLeases<
|
||||
TParams extends { intervalMs?: number; pulse: (...args: never[]) => Promise<unknown> },
|
||||
TLease extends { refresh: () => Promise<void>; stop: () => void },
|
||||
@@ -13,17 +17,17 @@ export async function expectIndependentTypingLeases<
|
||||
const leaseA = await params.createLease(params.buildParams(pulse));
|
||||
const leaseB = await params.createLease(params.buildParams(pulse));
|
||||
|
||||
expect(pulse).toHaveBeenCalledTimes(2);
|
||||
expectPulseCount(pulse as unknown as { mock: { calls: unknown[] } }, 2);
|
||||
|
||||
await vi.advanceTimersByTimeAsync(2_000);
|
||||
expect(pulse).toHaveBeenCalledTimes(4);
|
||||
expectPulseCount(pulse as unknown as { mock: { calls: unknown[] } }, 4);
|
||||
|
||||
leaseA.stop();
|
||||
await vi.advanceTimersByTimeAsync(2_000);
|
||||
expect(pulse).toHaveBeenCalledTimes(5);
|
||||
expectPulseCount(pulse as unknown as { mock: { calls: unknown[] } }, 5);
|
||||
|
||||
await leaseB.refresh();
|
||||
expect(pulse).toHaveBeenCalledTimes(6);
|
||||
expectPulseCount(pulse as unknown as { mock: { calls: unknown[] } }, 6);
|
||||
|
||||
leaseB.stop();
|
||||
}
|
||||
@@ -41,7 +45,7 @@ export async function expectBackgroundTypingPulseFailuresAreSwallowed<
|
||||
const lease = await params.createLease(params.buildParams(params.pulse));
|
||||
|
||||
await expect(vi.advanceTimersByTimeAsync(2_000)).resolves.toBe(vi);
|
||||
expect(params.pulse).toHaveBeenCalledTimes(2);
|
||||
expectPulseCount(params.pulse as unknown as { mock: { calls: unknown[] } }, 2);
|
||||
|
||||
lease.stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user