test: stabilize channel mode and discussion coverage

This commit is contained in:
zhi
2026-04-02 06:18:16 +00:00
parent 4e0a24333e
commit b11c15d8c8
6 changed files with 113 additions and 26 deletions

View File

@@ -5,7 +5,7 @@ import os from 'node:os';
import path from 'node:path';
import { createDiscussionService } from '../plugin/core/discussion-service.ts';
import { buildDiscussionClosedMessage, buildDiscussionOriginCallbackMessage } from '../plugin/core/discussion-messages.ts';
import { buildDiscussionClosedMessage, buildDiscussionIdleReminderMessage, buildDiscussionOriginCallbackMessage } from '../plugin/core/discussion-messages.ts';
function makeLogger() {
return {
@@ -246,6 +246,44 @@ test('handleCallback rejects an absolute path outside the initiator workspace',
);
});
test('maybeSendIdleReminder sends exactly one idle reminder for an active discussion', async () => {
const workspace = makeWorkspace();
const fetchCalls: Array<{ url: string; body: any }> = [];
const originalFetch = globalThis.fetch;
globalThis.fetch = (async (url: string | URL | Request, init?: RequestInit) => {
const body = init?.body ? JSON.parse(String(init.body)) : undefined;
fetchCalls.push({ url: String(url), body });
return new Response(JSON.stringify({ id: `msg-${fetchCalls.length}` }), { status: 200 });
}) as typeof fetch;
try {
const service = createDiscussionService({
api: makeApi() as any,
workspaceRoot: workspace,
moderatorBotToken: 'bot-token',
forceNoReplyForSession: () => {},
});
await service.initDiscussion({
discussionChannelId: 'discussion-idle-1',
originChannelId: 'origin-idle-1',
initiatorAgentId: 'agent-idle',
initiatorSessionId: 'session-idle',
discussGuide: 'Only send one reminder.',
});
await service.maybeSendIdleReminder('discussion-idle-1');
await service.maybeSendIdleReminder('discussion-idle-1');
assert.equal(fetchCalls.length, 2);
assert.equal(fetchCalls[1]?.url, 'https://discord.com/api/v10/channels/discussion-idle-1/messages');
assert.equal(fetchCalls[1]?.body?.content, buildDiscussionIdleReminderMessage());
} finally {
globalThis.fetch = originalFetch;
}
});
test('handleCallback notifies the origin channel with the resolved summary path', async () => {
const workspace = makeWorkspace();
const summaryRelPath = path.join('plans', 'discussion-summary.md');