test: tighten remaining plugin sdk assertions

This commit is contained in:
Peter Steinberger
2026-05-11 15:40:56 +01:00
parent 6943b5b4a6
commit 0693603e5f
12 changed files with 105 additions and 77 deletions

View File

@@ -154,12 +154,23 @@ describe("handleStopCommand target fallback", () => {
});
expect(replyRunAbortMock).toHaveBeenCalledWith("agent:target:telegram:direct:123");
expect(abortEmbeddedPiRunMock).not.toHaveBeenCalledWith("wrapper-session-id");
const persistAbortTargetParams = persistAbortTargetEntryMock.mock.calls[0]?.[0];
const [[persistAbortTargetParams]] = persistAbortTargetEntryMock.mock.calls as unknown as Array<
[
{
key?: string;
entry?: unknown;
sessionStore?: unknown;
storePath?: string;
},
]
>;
expect(persistAbortTargetParams?.key).toBe("agent:target:telegram:direct:123");
expect(persistAbortTargetParams?.entry).toBeUndefined();
expect(persistAbortTargetParams?.sessionStore).toBe(params.sessionStore);
expect(persistAbortTargetParams?.storePath).toBe("/tmp/sessions.json");
const stopSubagentsParams = stopSubagentsForRequesterMock.mock.calls[0]?.[0];
const [[stopSubagentsParams]] = stopSubagentsForRequesterMock.mock.calls as unknown as Array<
[{ cfg?: unknown; requesterSessionKey?: string }]
>;
expect(stopSubagentsParams?.cfg).toBe(params.cfg);
expect(stopSubagentsParams?.requesterSessionKey).toBe("agent:target:telegram:direct:123");
expect(createInternalHookEventMock).toHaveBeenCalledWith(

View File

@@ -118,7 +118,18 @@ describe("dispatchReplyFromConfig reply_dispatch hook", () => {
expect(hookMocks.runner.runReplyDispatch).toHaveBeenCalledOnce();
const [replyDispatchEvent, replyDispatchRuntime] =
hookMocks.runner.runReplyDispatch.mock.calls[0] ?? [];
(hookMocks.runner.runReplyDispatch.mock.calls[0] as
| [
{
sessionKey?: string;
sendPolicy?: string;
inboundAudio?: boolean;
},
{
cfg?: unknown;
},
]
| undefined) ?? [];
expect(replyDispatchEvent?.sessionKey).toBe("agent:test:session");
expect(replyDispatchEvent?.sendPolicy).toBe("allow");
expect(replyDispatchEvent?.inboundAudio).toBe(false);

View File

@@ -68,11 +68,15 @@ describe("createChannelRunQueue", () => {
await flushAsyncWork();
expect(setStatus).toHaveBeenCalledWith({ activeRuns: 0, busy: false });
expect(setStatus).toHaveBeenCalledWith(expect.objectContaining({ activeRuns: 1, busy: true }));
expect(setStatus).toHaveBeenLastCalledWith(
expect.objectContaining({ activeRuns: 0, busy: false }),
);
expect(setStatus).toHaveBeenCalledTimes(3);
const [initialStatus, busyStatus, finalStatus] = setStatus.mock.calls.map(([status]) => status);
expect(initialStatus).toEqual({ activeRuns: 0, busy: false });
expect(busyStatus?.activeRuns).toBe(1);
expect(busyStatus?.busy).toBe(true);
expect(typeof busyStatus?.lastRunActivityAt).toBe("number");
expect(finalStatus?.activeRuns).toBe(0);
expect(finalStatus?.busy).toBe(false);
expect(typeof finalStatus?.lastRunActivityAt).toBe("number");
expect(onError).toHaveBeenCalledWith(taskError);
});

View File

@@ -279,20 +279,21 @@ describe("channel-streaming", () => {
});
it("formats progress draft lines with shared tool display labels", () => {
expect(
buildChannelProgressDraftLine({
event: "tool",
name: "write",
args: { path: "/tmp/demo/index.html" },
}),
).toMatchObject({
kind: "tool",
icon: "✍️",
label: "Write",
detail: "to /tmp/demo/index.html",
text: "✍️ Write: to /tmp/demo/index.html",
toolName: "write",
const progressLine = buildChannelProgressDraftLine({
event: "tool",
name: "write",
args: { path: "/tmp/demo/index.html" },
});
expect(progressLine).toBeDefined();
if (!progressLine) {
throw new Error("expected tool progress draft line");
}
expect(progressLine.kind).toBe("tool");
expect(progressLine.icon).toBe("✍️");
expect(progressLine.label).toBe("Write");
expect(progressLine.detail).toBe("to /tmp/demo/index.html");
expect(progressLine.text).toBe("✍️ Write: to /tmp/demo/index.html");
expect(progressLine.toolName).toBe("write");
expect(
formatChannelProgressDraftLine({
event: "tool",

View File

@@ -46,11 +46,10 @@ describe("plugin-sdk delivery queue drainPendingDeliveries", () => {
selectEntry: () => ({ match: false }),
});
expect(mocks.coreDrainPendingDeliveries).toHaveBeenCalledWith(
expect.objectContaining({
deliver: mocks.deliverOutboundPayloads,
}),
);
expect(mocks.coreDrainPendingDeliveries).toHaveBeenCalledTimes(1);
const [[{ deliver: lazyDeliver }]] = mocks.coreDrainPendingDeliveries.mock
.calls as unknown as Array<[{ deliver?: unknown }]>;
expect(lazyDeliver).toBe(mocks.deliverOutboundPayloads);
});
it("preserves an explicit deliver fn without loading the lazy runtime", async () => {
@@ -65,11 +64,10 @@ describe("plugin-sdk delivery queue drainPendingDeliveries", () => {
selectEntry: () => ({ match: false }),
});
expect(mocks.coreDrainPendingDeliveries).toHaveBeenCalledWith(
expect.objectContaining({
deliver,
}),
);
expect(mocks.coreDrainPendingDeliveries).toHaveBeenCalledTimes(1);
const [[{ deliver: explicitDeliver }]] = mocks.coreDrainPendingDeliveries.mock
.calls as unknown as Array<[{ deliver?: unknown }]>;
expect(explicitDeliver).toBe(deliver);
expect(mocks.deliverOutboundPayloads).not.toHaveBeenCalled();
});
});

View File

@@ -160,19 +160,17 @@ describe("discord plugin-sdk facade", () => {
childSessionKey: "child",
});
expect(mocks.runtimeModule.autoBindSpawnedDiscordSubagent).toHaveBeenCalledWith(
expect.objectContaining({
agentId: "agent",
cfg: mocks.runtimeConfig,
childSessionKey: "child",
}),
);
expect(binding).toEqual(
expect.objectContaining({
cfg: mocks.runtimeConfig,
targetKind: "subagent",
targetSessionKey: "child",
}),
);
expect(mocks.runtimeModule.autoBindSpawnedDiscordSubagent).toHaveBeenCalledTimes(1);
const callParams = mocks.runtimeModule.autoBindSpawnedDiscordSubagent.mock.calls[0]?.[0];
expect(callParams.agentId).toBe("agent");
expect(callParams.cfg).toBe(mocks.runtimeConfig);
expect(callParams.childSessionKey).toBe("child");
expect(binding).not.toBeNull();
if (!binding) {
throw new Error("expected Discord subagent binding");
}
expect(binding.cfg).toBe(mocks.runtimeConfig);
expect(binding.targetKind).toBe("subagent");
expect(binding.targetSessionKey).toBe("child");
});
});

View File

@@ -44,10 +44,9 @@ describe("acquireFileLock", () => {
);
await expect(acquireFileLock(filePath, options)).rejects.toSatisfy((error) => {
expect(error).toMatchObject({
code: FILE_LOCK_TIMEOUT_ERROR_CODE,
});
expect((error as { lockPath?: string }).lockPath).toMatch(/oauth-refresh\.lock$/);
const lockError = error as { code?: string; lockPath?: string };
expect(lockError.code).toBe(FILE_LOCK_TIMEOUT_ERROR_CODE);
expect(lockError.lockPath).toMatch(/oauth-refresh\.lock$/);
return true;
});
}, 5_000);

View File

@@ -196,12 +196,12 @@ describe("buildProviderToolCompatFamilyHooks", () => {
});
expect(normalized[0]?.parameters).toEqual(permissiveParameters);
expect(findOpenAIStrictSchemaViolations(permissiveParameters, "cron.parameters")).toEqual(
expect.arrayContaining([
"cron.parameters.required.schedule",
"cron.parameters.additionalProperties",
]),
const strictSchemaViolations = findOpenAIStrictSchemaViolations(
permissiveParameters,
"cron.parameters",
);
expect(strictSchemaViolations).toContain("cron.parameters.required.schedule");
expect(strictSchemaViolations).toContain("cron.parameters.additionalProperties");
expect(
hooks.inspectToolSchemas({
provider: "openai",

View File

@@ -518,14 +518,21 @@ describe("sendMediaWithLeadingCaption", () => {
}),
).resolves.toBe(true);
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
mediaUrl: "https://example.com/a.png",
caption: "hello",
index: 0,
isFirst: true,
}),
);
expect(onError).toHaveBeenCalledTimes(1);
const [[errorPayload]] = onError.mock.calls as unknown as Array<
[
{
mediaUrl?: string;
caption?: string;
index?: number;
isFirst?: boolean;
},
]
>;
expect(errorPayload.mediaUrl).toBe("https://example.com/a.png");
expect(errorPayload.caption).toBe("hello");
expect(errorPayload.index).toBe(0);
expect(errorPayload.isFirst).toBe(true);
expect(send).toHaveBeenNthCalledWith(2, {
mediaUrl: "https://example.com/b.png",
caption: undefined,

View File

@@ -36,11 +36,7 @@ describe("telegram account plugin-sdk compatibility facade", () => {
cfg,
accountId: "default",
});
expect(account).toEqual(
expect.objectContaining({
accountId: "default",
token: "token",
}),
);
expect(account.accountId).toBe("default");
expect(account.token).toBe("token");
});
});

View File

@@ -86,7 +86,10 @@ describe("withTempDownloadPath", () => {
expect(capturedPath).toContain(path.join(resolvePreferredOpenClawTmpDir(), "line-media-"));
}
if (expectCleanup) {
await expect(fs.stat(capturedPath)).rejects.toMatchObject({ code: "ENOENT" });
await expect(fs.stat(capturedPath)).rejects.toSatisfy((error) => {
expect((error as NodeJS.ErrnoException).code).toBe("ENOENT");
return true;
});
}
});
});

View File

@@ -85,7 +85,7 @@ describe("registerWebhookTarget", () => {
expect(onFirstPathTarget).toHaveBeenCalledTimes(1);
expect(onFirstPathTarget).toHaveBeenCalledWith({
path: "/hook",
target: expect.objectContaining({ id: "A", path: "/hook" }),
target: registeredA.target,
});
registeredB.unregister();
@@ -147,13 +147,13 @@ describe("registerWebhookTargetWithPluginRoute", () => {
});
expect(registry.httpRoutes).toHaveLength(1);
expect(registry.httpRoutes[0]).toEqual(
expect.objectContaining({
pluginId: "demo",
path: "/hook",
source: "demo-webhook",
}),
);
const route = registry.httpRoutes[0];
if (!route) {
throw new Error("expected plugin route to be registered");
}
expect(route.pluginId).toBe("demo");
expect(route.path).toBe("/hook");
expect(route.source).toBe("demo-webhook");
registeredA.unregister();
expect(registry.httpRoutes).toHaveLength(1);