mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
fix(discord): keep the thread of a discarded rebuild, close one made for a closed tab, unique tmp names, wider prune keep set
This commit is contained in:
1 parent
b68792f988
commit
a698729fb6
6 files changed
+94
-10
No files matched your search
@@ -50,7 +50,7 @@ function bareServer(live: string[] = [], persisted: string[] = []): CleanupServe
|
||||
persistDeb: { cancelKey: () => {} },
|
||||
sse: { cleanupSessionBatches: () => {} },
|
||||
// A real delete also tells the Discord bridge, which frees its per-tab state and may archive the thread.
|
||||
discordBridge: { sessionDeleted: async () => {} },
|
||||
discordBridge: { sessionDeleted: async () => {}, forgetTab: () => {} },
|
||||
broadcast: () => {},
|
||||
});
|
||||
return server;
|
||||
|
||||
@@ -663,6 +663,41 @@ describe('DiscordBridge', () => {
|
||||
b.stop();
|
||||
});
|
||||
|
||||
it('forgetTab drops the per-tab state but keeps the thread and its map entry', async () => {
|
||||
await writeDiscordConfig(dir, { ...CFG, onSessionDelete: 'delete' });
|
||||
const b = bridge();
|
||||
await b.notify(MSG);
|
||||
posts.length = 0;
|
||||
b.forgetTab('s1');
|
||||
await b.sessionRenamed('s1', 'other'); // first sight again: recorded, no PATCH
|
||||
expect(posts).toHaveLength(0);
|
||||
expect(await readThreadMap(dir)).toEqual({ s1: THREAD });
|
||||
b.stop();
|
||||
});
|
||||
|
||||
it('a tab closed while its thread is being created has that thread closed and no entry kept', async () => {
|
||||
await writeDiscordConfig(dir, { ...CFG, onSessionDelete: 'archive' });
|
||||
let release!: () => void;
|
||||
const gate = new Promise<void>((r) => (release = r));
|
||||
const b = bridge({}, async (url, init) => {
|
||||
const path = new URL(String(url)).pathname.replace('/api/v10', '');
|
||||
posts.push({ path, method: String(init.method), body: init.body ? JSON.parse(String(init.body)) : undefined });
|
||||
if (path.endsWith('/threads')) {
|
||||
await gate;
|
||||
return jsonRes({ id: THREAD });
|
||||
}
|
||||
return jsonRes({ id: 'msg' });
|
||||
});
|
||||
const first = b.notify(MSG);
|
||||
await vi.waitFor(() => expect(posts.some((p) => p.path.endsWith('/threads'))).toBe(true));
|
||||
await b.sessionDeleted('s1');
|
||||
release();
|
||||
await first;
|
||||
expect(posts).toContainEqual({ path: `/channels/${THREAD}`, method: 'PATCH', body: { archived: true } });
|
||||
expect(await readThreadMap(dir)).toEqual({});
|
||||
b.stop();
|
||||
});
|
||||
|
||||
it('renames the thread only when the name really changed', async () => {
|
||||
const b = bridge();
|
||||
await b.notify(MSG);
|
||||
|
||||
@@ -25,6 +25,7 @@ type Internals = {
|
||||
sendPushNotifications: (event: string, data: Record<string, unknown>) => Promise<void>;
|
||||
broadcast: (event: string, data: unknown) => void;
|
||||
cleanupSession: (id: string, killMux?: boolean, reason?: string) => Promise<void>;
|
||||
discardPartiallyBuiltSession: (id: string) => Promise<void>;
|
||||
};
|
||||
|
||||
function server(): Internals {
|
||||
@@ -35,6 +36,7 @@ function server(): Internals {
|
||||
sessionCreated: vi.fn(async () => undefined),
|
||||
sessionRenamed: vi.fn(async () => undefined),
|
||||
sessionDeleted: vi.fn(async () => undefined),
|
||||
forgetTab: vi.fn(),
|
||||
sessionIdle: vi.fn(async () => undefined),
|
||||
stop: vi.fn(),
|
||||
};
|
||||
@@ -125,6 +127,19 @@ describe('broadcast -> Discord tab lifecycle', () => {
|
||||
expect(s.discordBridge.sessionDeleted).toHaveBeenCalledWith('gone');
|
||||
});
|
||||
|
||||
it('a discarded half-built session clears the per-tab state but keeps its thread', async () => {
|
||||
const s = server();
|
||||
s.sessions.set('rebuild', {
|
||||
owner: 'u',
|
||||
ralphTracker: { stopWatchingFixPlan: () => undefined, fullReset: () => undefined },
|
||||
removeAllListeners: () => undefined,
|
||||
stop: async () => undefined,
|
||||
});
|
||||
await s.discardPartiallyBuiltSession('rebuild');
|
||||
expect(s.discordBridge.forgetTab).toHaveBeenCalledWith('rebuild');
|
||||
expect(s.discordBridge.sessionDeleted).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('ignores an event with no session id', () => {
|
||||
const s = server();
|
||||
s.broadcast(SseEvent.SessionUpdated, {});
|
||||
|
||||
Reference in new issue
Block a user