Skip to content

Commit 9e58cc8

Browse files
committed
test: fix strict CI gates
1 parent 79e3142 commit 9e58cc8

53 files changed

Lines changed: 318 additions & 222 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

extensions/deepseek/deepseek.live.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ describeLive("deepseek plugin live", () => {
142142
};
143143
let capturedPayload: Record<string, unknown> | undefined;
144144
const streamFn = createDeepSeekV4ThinkingWrapper(streamSimple, "high");
145+
if (!streamFn) {
146+
throw new Error("expected DeepSeek V4 thinking stream wrapper");
147+
}
145148

146149
const stream = streamFn(resolveDeepSeekV4LiveModel(), context, {
147150
apiKey: DEEPSEEK_KEY,
@@ -202,6 +205,9 @@ describeLive("deepseek plugin live", () => {
202205
};
203206
let capturedPayload: Record<string, unknown> | undefined;
204207
const streamFn = createDeepSeekV4ThinkingWrapper(streamSimple, "high");
208+
if (!streamFn) {
209+
throw new Error("expected DeepSeek V4 thinking stream wrapper");
210+
}
205211

206212
const stream = streamFn(resolveDeepSeekV4LiveModel(), context, {
207213
apiKey: DEEPSEEK_KEY,

extensions/discord/src/channel.message-adapter.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe("discord channel message adapter", () => {
3232

3333
const proveText = async () => {
3434
resetDiscordOutboundMocks(hoisted);
35-
const result = await adapter!.send!.text!({
35+
const result = await adapter.send!.text!({
3636
cfg: {},
3737
to: "channel:123456",
3838
text: "hello",
@@ -49,7 +49,7 @@ describe("discord channel message adapter", () => {
4949

5050
const proveMedia = async () => {
5151
resetDiscordOutboundMocks(hoisted);
52-
const result = await adapter!.send!.media!({
52+
const result = await adapter.send!.media!({
5353
cfg: {},
5454
to: "channel:123456",
5555
text: "caption",
@@ -69,7 +69,7 @@ describe("discord channel message adapter", () => {
6969

7070
const provePayload = async () => {
7171
resetDiscordOutboundMocks(hoisted);
72-
const result = await adapter!.send!.payload!({
72+
const result = await adapter.send!.payload!({
7373
cfg: {},
7474
to: "channel:123456",
7575
text: "payload",
@@ -86,7 +86,7 @@ describe("discord channel message adapter", () => {
8686

8787
const proveReplyThreadSilent = async () => {
8888
resetDiscordOutboundMocks(hoisted);
89-
const result = await adapter!.send!.text!({
89+
const result = await adapter.send!.text!({
9090
cfg: {},
9191
to: "channel:parent-1",
9292
text: "threaded",
@@ -110,7 +110,7 @@ describe("discord channel message adapter", () => {
110110

111111
await verifyChannelMessageAdapterCapabilityProofs({
112112
adapterName: "discordMessageAdapter",
113-
adapter: adapter!,
113+
adapter: adapter,
114114
proofs: {
115115
text: proveText,
116116
media: proveMedia,
@@ -119,7 +119,7 @@ describe("discord channel message adapter", () => {
119119
replyTo: proveReplyThreadSilent,
120120
thread: proveReplyThreadSilent,
121121
messageSendingHooks: () => {
122-
expect(adapter!.send!.text).toBeTypeOf("function");
122+
expect(adapter.send!.text).toBeTypeOf("function");
123123
},
124124
},
125125
});

extensions/discord/src/voice/manager.e2e.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ describe("DiscordVoiceManager", () => {
276276

277277
const getLastAudioPlayer = () => {
278278
const player = createAudioPlayerMock.mock.results.at(-1)?.value as
279-
| { state: { status: string } }
279+
| { state: { status: string }; stop: ReturnType<typeof vi.fn> }
280280
| undefined;
281281
if (!player) {
282282
throw new Error("expected Discord voice audio player to be created");

extensions/line/src/webhook-node.test.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import crypto from "node:crypto";
22
import type { IncomingMessage, ServerResponse } from "node:http";
3+
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
34
import { createMockIncomingRequest } from "openclaw/plugin-sdk/test-env";
45
import { describe, expect, it, vi } from "vitest";
56
import { createLineNodeWebhookHandler, readLineWebhookRequestBody } from "./webhook-node.js";
@@ -29,6 +30,20 @@ function createRes() {
2930

3031
const SECRET = "secret";
3132

33+
type RuntimeEnvMock = RuntimeEnv & {
34+
error: ReturnType<typeof vi.fn<(...args: unknown[]) => void>>;
35+
exit: ReturnType<typeof vi.fn<(code: number) => void>>;
36+
log: ReturnType<typeof vi.fn<(...args: unknown[]) => void>>;
37+
};
38+
39+
function createRuntimeMock(): RuntimeEnvMock {
40+
return {
41+
error: vi.fn<(...args: unknown[]) => void>(),
42+
exit: vi.fn<(code: number) => void>(),
43+
log: vi.fn<(...args: unknown[]) => void>(),
44+
};
45+
}
46+
3247
function createMiddlewareRes() {
3348
const res = {
3449
status: vi.fn(),
@@ -42,7 +57,7 @@ function createMiddlewareRes() {
4257

4358
function createPostWebhookTestHarness(rawBody: string, secret = "secret") {
4459
const bot = { handleWebhook: vi.fn(async () => {}) };
45-
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
60+
const runtime = createRuntimeMock();
4661
const handler = createLineNodeWebhookHandler({
4762
channelSecret: secret,
4863
bot,
@@ -71,11 +86,7 @@ async function invokeWebhook(params: {
7186
headers?: Record<string, string>;
7287
onEvents?: ReturnType<typeof vi.fn>;
7388
autoSign?: boolean;
74-
runtime?: {
75-
log: ReturnType<typeof vi.fn>;
76-
error: ReturnType<typeof vi.fn>;
77-
exit: ReturnType<typeof vi.fn>;
78-
};
89+
runtime?: RuntimeEnv;
7990
}) {
8091
const onEventsMock = params.onEvents ?? vi.fn(async () => {});
8192
const middleware = createLineWebhookMiddleware({
@@ -138,7 +149,7 @@ async function invokeNodePostContract(params: {
138149
throw params.failWith;
139150
}
140151
});
141-
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
152+
const runtime = createRuntimeMock();
142153
const handler = createLineNodeWebhookHandler({
143154
channelSecret: SECRET,
144155
bot: { handleWebhook: dispatched },
@@ -167,7 +178,7 @@ async function invokeMiddlewarePostContract(params: {
167178
rawBody: string;
168179
signed: boolean;
169180
}) {
170-
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
181+
const runtime = createRuntimeMock();
171182
const onEvents = vi.fn(async () => {
172183
if (params.failWith) {
173184
throw params.failWith;
@@ -182,6 +193,7 @@ async function invokeMiddlewarePostContract(params: {
182193
});
183194
return {
184195
body: res.json.mock.calls.at(-1)?.[0],
196+
contentType: undefined,
185197
dispatched,
186198
runtimeError: runtime.error,
187199
status: res.status.mock.calls.at(-1)?.[0],
@@ -288,7 +300,7 @@ describe("LINE webhook shared POST contract", () => {
288300
describe("createLineNodeWebhookHandler", () => {
289301
it("returns 200 for GET", async () => {
290302
const bot = { handleWebhook: vi.fn(async () => {}) };
291-
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
303+
const runtime = createRuntimeMock();
292304
const handler = createLineNodeWebhookHandler({
293305
channelSecret: "secret",
294306
bot,
@@ -305,7 +317,7 @@ describe("createLineNodeWebhookHandler", () => {
305317

306318
it("returns 204 for HEAD", async () => {
307319
const bot = { handleWebhook: vi.fn(async () => {}) };
308-
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
320+
const runtime = createRuntimeMock();
309321
const handler = createLineNodeWebhookHandler({
310322
channelSecret: "secret",
311323
bot,
@@ -333,7 +345,7 @@ describe("createLineNodeWebhookHandler", () => {
333345

334346
it("rejects unsigned POST requests before reading the body", async () => {
335347
const bot = { handleWebhook: vi.fn(async () => {}) };
336-
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
348+
const runtime = createRuntimeMock();
337349
const readBody = vi.fn(async () => JSON.stringify({ events: [{ type: "message" }] }));
338350
const handler = createLineNodeWebhookHandler({
339351
channelSecret: "secret",
@@ -353,7 +365,7 @@ describe("createLineNodeWebhookHandler", () => {
353365
it("uses strict pre-auth limits for signed POST requests", async () => {
354366
const rawBody = JSON.stringify({ events: [{ type: "message" }] });
355367
const bot = { handleWebhook: vi.fn(async () => {}) };
356-
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
368+
const runtime = createRuntimeMock();
357369
const readBody = vi.fn(async (_req: IncomingMessage, maxBytes: number, timeoutMs?: number) => {
358370
expect(maxBytes).toBe(64 * 1024);
359371
expect(timeoutMs).toBe(5_000);
@@ -414,7 +426,7 @@ describe("createLineNodeWebhookHandler", () => {
414426
),
415427
};
416428
const onRequestAuthenticated = vi.fn();
417-
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
429+
const runtime = createRuntimeMock();
418430
const handler = createLineNodeWebhookHandler({
419431
channelSecret: SECRET,
420432
bot,

extensions/lmstudio/src/models.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ describe("lmstudio-models", () => {
378378
context_length: 32768,
379379
}),
380380
});
381-
const loadInit = loadCall![1] as RequestInit;
381+
const loadInit = loadCall[1] as RequestInit;
382382
const loadBody = parseJsonRequestBody(loadInit) as { context_length: number };
383383
expect(loadBody.context_length).not.toBe(LMSTUDIO_DEFAULT_LOAD_CONTEXT_LENGTH);
384384
});

extensions/matrix/src/channel.message-adapter.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ describe("matrix channel message adapter", () => {
4747
if (adapter?.send?.text === undefined || adapter.send.media === undefined) {
4848
throw new Error("expected matrix text and media message adapter");
4949
}
50+
const sendText = adapter.send.text;
51+
const sendMedia = adapter.send.media;
5052

5153
const proveText = async () => {
5254
mocks.sendMessageMatrix.mockClear();
53-
const result = await adapter.send.text({
55+
const result = await sendText({
5456
cfg,
5557
to: "room:!room:example",
5658
text: "hello",
@@ -67,7 +69,7 @@ describe("matrix channel message adapter", () => {
6769

6870
const proveMedia = async () => {
6971
mocks.sendMessageMatrix.mockClear();
70-
const result = await adapter.send.media({
72+
const result = await sendMedia({
7173
cfg,
7274
to: "room:!room:example",
7375
text: "caption",
@@ -91,7 +93,7 @@ describe("matrix channel message adapter", () => {
9193

9294
const proveReplyThread = async () => {
9395
mocks.sendMessageMatrix.mockClear();
94-
const result = await adapter!.send!.text!({
96+
const result = await adapter.send!.text!({
9597
cfg,
9698
to: "room:!room:example",
9799
text: "threaded",
@@ -114,14 +116,14 @@ describe("matrix channel message adapter", () => {
114116

115117
await verifyChannelMessageAdapterCapabilityProofs({
116118
adapterName: "matrixMessageAdapter",
117-
adapter: adapter!,
119+
adapter: adapter,
118120
proofs: {
119121
text: proveText,
120122
media: proveMedia,
121123
replyTo: proveReplyThread,
122124
thread: proveReplyThread,
123125
messageSendingHooks: () => {
124-
expect(adapter!.send!.text).toBeTypeOf("function");
126+
expect(adapter.send!.text).toBeTypeOf("function");
125127
},
126128
},
127129
});

extensions/mattermost/src/channel.message-adapter.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ describe("mattermost channel message adapter", () => {
3030

3131
const proveText = async () => {
3232
sendMessageMattermostMock.mockClear();
33-
const result = await adapter!.send!.text!({
33+
const result = await adapter.send!.text!({
3434
cfg: {},
3535
to: "channel:team-1",
3636
text: "hello",
@@ -47,7 +47,7 @@ describe("mattermost channel message adapter", () => {
4747

4848
const proveMedia = async () => {
4949
sendMessageMattermostMock.mockClear();
50-
const result = await adapter!.send!.media!({
50+
const result = await adapter.send!.media!({
5151
cfg: {},
5252
to: "channel:team-1",
5353
text: "caption",
@@ -67,7 +67,7 @@ describe("mattermost channel message adapter", () => {
6767

6868
const proveReplyThread = async () => {
6969
sendMessageMattermostMock.mockClear();
70-
const result = await adapter!.send!.text!({
70+
const result = await adapter.send!.text!({
7171
cfg: {},
7272
to: "channel:parent-1",
7373
text: "threaded",
@@ -84,7 +84,7 @@ describe("mattermost channel message adapter", () => {
8484

8585
const proveExplicitReply = async () => {
8686
sendMessageMattermostMock.mockClear();
87-
const result = await adapter!.send!.text!({
87+
const result = await adapter.send!.text!({
8888
cfg: {},
8989
to: "channel:parent-1",
9090
text: "reply",
@@ -102,14 +102,14 @@ describe("mattermost channel message adapter", () => {
102102

103103
await verifyChannelMessageAdapterCapabilityProofs({
104104
adapterName: "mattermostMessageAdapter",
105-
adapter: adapter!,
105+
adapter: adapter,
106106
proofs: {
107107
text: proveText,
108108
media: proveMedia,
109109
replyTo: proveExplicitReply,
110110
thread: proveReplyThread,
111111
messageSendingHooks: () => {
112-
expect(adapter!.send!.text).toBeTypeOf("function");
112+
expect(adapter.send!.text).toBeTypeOf("function");
113113
},
114114
},
115115
});

extensions/memory-core/src/dreaming-phases.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,8 +2427,8 @@ describe("memory-core dreaming phases", () => {
24272427
const phaseSignalStore = JSON.parse(await fs.readFile(phaseSignalPath, "utf-8")) as {
24282428
entries: Record<string, { remHits: number }>;
24292429
};
2430-
expect(phaseSignalStore.entries[liveKey!]).toMatchObject({ remHits: 1 });
2431-
expect(phaseSignalStore.entries[staleKey!]).toBeUndefined();
2430+
expect(phaseSignalStore.entries[liveKey]).toMatchObject({ remHits: 1 });
2431+
expect(phaseSignalStore.entries[staleKey]).toBeUndefined();
24322432

24332433
const remOutput = await fs.readFile(
24342434
path.join(workspaceDir, "memory", `${DREAMING_TEST_DAY}.md`),

extensions/msteams/src/channel.message-adapter.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ describe("msteams channel message adapter", () => {
5454
if (!adapter?.send?.text || !adapter.send.media) {
5555
throw new Error("expected msteams channel message adapter with text and media senders");
5656
}
57+
const sendText = adapter.send.text;
58+
const sendMedia = adapter.send.media;
5759
expect(adapter.durableFinal?.capabilities?.replyTo).toBeUndefined();
5860
expect(adapter.durableFinal?.capabilities?.thread).toBeUndefined();
5961

6062
const proveText = async () => {
6163
mocks.sendText.mockClear();
62-
const result = await adapter.send.text({
64+
const result = await sendText({
6365
cfg,
6466
to: "conversation:abc",
6567
text: "hello",
@@ -79,7 +81,7 @@ describe("msteams channel message adapter", () => {
7981

8082
const proveMedia = async () => {
8183
mocks.sendMedia.mockClear();
82-
const result = await adapter.send.media({
84+
const result = await sendMedia({
8385
cfg,
8486
to: "conversation:abc",
8587
text: "photo",
@@ -107,7 +109,7 @@ describe("msteams channel message adapter", () => {
107109
text: proveText,
108110
media: proveMedia,
109111
messageSendingHooks: () => {
110-
expect(adapter.send.text).toBeTypeOf("function");
112+
expect(sendText).toBeTypeOf("function");
111113
},
112114
},
113115
});

extensions/msteams/src/sdk.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ describe("createMSTeamsApp – federated certificate credentials", () => {
472472
clientId: "fed-app-id",
473473
tenantId: "fed-tenant",
474474
});
475-
const tokenProvider = appInstances[0].token;
475+
const tokenProvider = appInstances[0].token as ((scope: string) => Promise<string>) | undefined;
476476
if (!tokenProvider) {
477477
throw new Error("expected federated app to expose token provider");
478478
}
@@ -521,7 +521,7 @@ describe("createMSTeamsApp – federated managed identity", () => {
521521
};
522522
await createMSTeamsApp(creds, sdk);
523523
expect(appInstances[0]).toMatchObject({ clientId: "mi-app-id", tenantId: "mi-tenant" });
524-
const tokenProvider = appInstances[0].token;
524+
const tokenProvider = appInstances[0].token as ((scope: string) => Promise<string>) | undefined;
525525
if (!tokenProvider) {
526526
throw new Error("expected managed-identity app to expose token provider");
527527
}
@@ -538,7 +538,7 @@ describe("createMSTeamsApp – federated managed identity", () => {
538538
useManagedIdentity: true,
539539
};
540540
await createMSTeamsApp(creds, sdk);
541-
const tokenProvider = appInstances[0].token;
541+
const tokenProvider = appInstances[0].token as ((scope: string) => Promise<string>) | undefined;
542542
if (!tokenProvider) {
543543
throw new Error("expected managed-identity app to expose token provider");
544544
}

0 commit comments

Comments
 (0)