

























@@ -48,6 +48,34 @@ async function flushAsyncWork() {
4848await Promise.resolve();
4949}
505051+function requireRecord(value: unknown, label: string): Record<string, unknown> {
52+expect(value, label).toBeTypeOf("object");
53+expect(value, label).not.toBeNull();
54+return value as Record<string, unknown>;
55+}
56+57+function callArg(mock: unknown, callIndex: number, argIndex: number, label: string) {
58+const calls = (mock as { mock?: { calls?: Array<Array<unknown>> } }).mock?.calls ?? [];
59+const call = calls.at(callIndex);
60+expect(call, label).toBeDefined();
61+return call?.[argIndex];
62+}
63+64+function expectRestBodyField(mock: unknown, field: string, expected: unknown) {
65+expect(callArg(mock, 0, 0, "rest path")).toBeTypeOf("string");
66+const options = requireRecord(callArg(mock, 0, 1, "rest options"), "rest options");
67+const body = requireRecord(options.body, "rest body");
68+expect(body[field]).toBe(expected);
69+}
70+71+function expectGeneratedTitleField(field: string, expected: unknown) {
72+const params = requireRecord(
73+callArg(generateThreadTitleMock, 0, 0, "thread title params"),
74+"thread title params",
75+);
76+expect(params[field]).toBe(expected);
77+}
78+5179beforeAll(async () => {
5280({ maybeCreateDiscordAutoThread } = await import("./threading.js"));
5381});
@@ -108,10 +136,7 @@ describe("maybeCreateDiscordAutoThread autoArchiveDuration", () => {
108136channelConfig: { allowed: true, autoThread: true, autoArchiveDuration: "10080" },
109137}),
110138);
111-expect(postMock).toHaveBeenCalledWith(
112-expect.any(String),
113-expect.objectContaining({ body: expect.objectContaining({ auto_archive_duration: 10080 }) }),
114-);
139+expectRestBodyField(postMock, "auto_archive_duration", 10080);
115140});
116141117142it("accepts numeric autoArchiveDuration", async () => {
@@ -121,19 +146,13 @@ describe("maybeCreateDiscordAutoThread autoArchiveDuration", () => {
121146channelConfig: { allowed: true, autoThread: true, autoArchiveDuration: 4320 },
122147}),
123148);
124-expect(postMock).toHaveBeenCalledWith(
125-expect.any(String),
126-expect.objectContaining({ body: expect.objectContaining({ auto_archive_duration: 4320 }) }),
127-);
149+expectRestBodyField(postMock, "auto_archive_duration", 4320);
128150});
129151130152it("defaults to 60 when autoArchiveDuration not set", async () => {
131153postMock.mockResolvedValueOnce({ id: "thread1" });
132154await maybeCreateDiscordAutoThread(createBaseParams());
133-expect(postMock).toHaveBeenCalledWith(
134-expect.any(String),
135-expect.objectContaining({ body: expect.objectContaining({ auto_archive_duration: 60 }) }),
136-);
155+expectRestBodyField(postMock, "auto_archive_duration", 60);
137156});
138157});
139158@@ -156,27 +175,16 @@ describe("maybeCreateDiscordAutoThread autoThreadName", () => {
156175}),
157176);
158177expect(result).toBe("thread1");
159-expect(postMock).toHaveBeenCalledWith(
160-expect.any(String),
161-expect.objectContaining({
162-body: expect.objectContaining({ name: "Need help with deploy rollout" }),
163-}),
164-);
178+expectRestBodyField(postMock, "name", "Need help with deploy rollout");
165179await flushAsyncWork();
166-expect(generateThreadTitleMock).toHaveBeenCalledWith(
167-expect.objectContaining({
168-agentId: "main",
169-messageText: "Need help with deploy rollout",
170-channelName: "openclaw",
171-channelDescription: "OpenClaw development coordination and release planning",
172-}),
173-);
174-expect(patchMock).toHaveBeenCalledWith(
175-expect.any(String),
176-expect.objectContaining({
177-body: expect.objectContaining({ name: "Deploy rollout summary" }),
178-}),
180+expectGeneratedTitleField("agentId", "main");
181+expectGeneratedTitleField("messageText", "Need help with deploy rollout");
182+expectGeneratedTitleField("channelName", "openclaw");
183+expectGeneratedTitleField(
184+"channelDescription",
185+"OpenClaw development coordination and release planning",
179186);
187+expectRestBodyField(patchMock, "name", "Deploy rollout summary");
180188});
181189182190it("does not block thread creation while title summary is pending", async () => {
@@ -231,11 +239,7 @@ describe("maybeCreateDiscordAutoThread autoThreadName", () => {
231239);
232240233241await flushAsyncWork();
234-expect(generateThreadTitleMock).toHaveBeenCalledWith(
235-expect.objectContaining({
236-modelRef: "openai/gpt-4.1-mini",
237-}),
238-);
242+expectGeneratedTitleField("modelRef", "openai/gpt-4.1-mini");
239243});
240244241245it("falls back to parent channel override for generated title model", async () => {
@@ -264,11 +268,7 @@ describe("maybeCreateDiscordAutoThread autoThreadName", () => {
264268);
265269266270await flushAsyncWork();
267-expect(generateThreadTitleMock).toHaveBeenCalledWith(
268-expect.objectContaining({
269-modelRef: "openai/gpt-4.1-mini",
270-}),
271-);
271+expectGeneratedTitleField("modelRef", "openai/gpt-4.1-mini");
272272});
273273274274it("skips summarization when cfg or agentId is missing", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。