Skip to content

Commit 9d9a614

Browse files
committed
refactor: share sessions list changed test helpers
1 parent 674bd6f commit 9d9a614

1 file changed

Lines changed: 94 additions & 128 deletions

File tree

src/gateway/server.sessions.list-changed.test.ts

Lines changed: 94 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const { createSessionStoreDir, openClient } = setupGatewaySessionsTestHarness();
1515
type MockCalls = {
1616
mock: { calls: unknown[][] };
1717
};
18+
type SessionStoreEntryOptions = Parameters<typeof sessionStoreEntry>[1];
19+
type MutationMethod = "sessions.patch" | "sessions.compact";
1820

1921
function isRecord(value: unknown): value is Record<string, unknown> {
2022
return typeof value === "object" && value !== null;
@@ -116,20 +118,31 @@ async function invokeSessionsList({
116118
return { request, respond };
117119
}
118120

119-
async function invokeSessionsPatch(params: Record<string, unknown>) {
121+
async function invokeSessionMutation({
122+
method,
123+
params,
124+
context = {},
125+
subscribedConnIds = new Set(["conn-1"]),
126+
}: {
127+
method: MutationMethod;
128+
params: Record<string, unknown>;
129+
context?: Record<string, unknown>;
130+
subscribedConnIds?: Set<string>;
131+
}) {
120132
const broadcastToConnIds = vi.fn();
121133
const respond = vi.fn();
122134
const sessionsHandlers = await getSessionsHandlers();
123135
const { getRuntimeConfig } = await getGatewayConfigModule();
124-
await sessionsHandlers["sessions.patch"]({
136+
await sessionsHandlers[method]({
125137
req: {} as never,
126138
params,
127139
respond,
128140
context: {
129141
broadcastToConnIds,
130-
getSessionEventSubscriberConnIds: () => new Set(["conn-1"]),
142+
getSessionEventSubscriberConnIds: () => subscribedConnIds,
131143
loadGatewayModelCatalog: async () => ({ providers: [] }),
132144
getRuntimeConfig,
145+
...context,
133146
} as never,
134147
client: null,
135148
isWebchatConnect: () => false,
@@ -140,6 +153,31 @@ async function invokeSessionsPatch(params: Record<string, unknown>) {
140153
};
141154
}
142155

156+
async function invokeSessionsPatch(params: Record<string, unknown>) {
157+
return invokeSessionMutation({ method: "sessions.patch", params });
158+
}
159+
160+
async function writeMainSessionStore(options?: SessionStoreEntryOptions) {
161+
await createSessionStoreDir();
162+
await writeSessionStore({
163+
entries: {
164+
main: sessionStoreEntry("sess-main", options),
165+
},
166+
});
167+
}
168+
169+
function expectMainPatchBroadcast(
170+
result: Awaited<ReturnType<typeof invokeSessionsPatch>>,
171+
expected: Record<string, unknown>,
172+
) {
173+
expectFields(result.responsePayload, { ok: true, key: "agent:main:main" });
174+
expectChangedBroadcast(result.broadcastToConnIds, {
175+
sessionKey: "agent:main:main",
176+
reason: "patch",
177+
...expected,
178+
});
179+
}
180+
143181
async function setupGlobalAgentSessionStores({
144182
writePrimeStore = false,
145183
withTranscripts = false,
@@ -257,25 +295,33 @@ async function invokeSessionsCompact({
257295
params: Record<string, unknown>;
258296
subscribedConnIds?: Set<string>;
259297
}) {
260-
const broadcastToConnIds = vi.fn();
261-
const respond = vi.fn();
262-
const sessionsHandlers = await getSessionsHandlers();
263-
await sessionsHandlers["sessions.compact"]({
264-
req: {} as never,
298+
return invokeSessionMutation({
299+
method: "sessions.compact",
265300
params,
266-
respond,
267301
context: {
268-
broadcastToConnIds,
269-
getSessionEventSubscriberConnIds: () => subscribedConnIds,
270302
getRuntimeConfig,
271-
} as never,
272-
client: null,
273-
isWebchatConnect: () => false,
303+
},
304+
subscribedConnIds,
274305
});
275-
return {
276-
broadcastToConnIds,
277-
responsePayload: expectRespondPayload(respond),
278-
};
306+
}
307+
308+
async function expectListedSessionActiveRun(
309+
requestId: string,
310+
run: Record<string, unknown>,
311+
expected: boolean,
312+
) {
313+
await writeMainSessionStore();
314+
315+
const { respond } = await invokeSessionsList({
316+
requestId,
317+
context: {
318+
chatAbortControllers: new Map([["run-1", { sessionKey: "agent:main:main", ...run }]]),
319+
},
320+
});
321+
322+
const payload = expectRespondPayload(respond);
323+
const session = findSession(payload, "agent:main:main");
324+
expect(session.hasActiveRun).toBe(expected);
279325
}
280326

281327
test("sessions.list keeps bulk rows lightweight and uses persisted model fields", async () => {
@@ -369,17 +415,12 @@ test("sessions.list keeps bulk rows lightweight and uses persisted model fields"
369415
});
370416

371417
test("sessions.list uses the gateway model catalog for effective thinking defaults", async () => {
372-
await createSessionStoreDir();
373418
testState.agentConfig = {
374419
model: { primary: "test-provider/reasoner" },
375420
};
376-
await writeSessionStore({
377-
entries: {
378-
main: sessionStoreEntry("sess-main", {
379-
modelProvider: "test-provider",
380-
model: "reasoner",
381-
}),
382-
},
421+
await writeMainSessionStore({
422+
modelProvider: "test-provider",
423+
model: "reasoner",
383424
});
384425

385426
const { respond } = await invokeSessionsList({
@@ -407,67 +448,23 @@ test("sessions.list uses the gateway model catalog for effective thinking defaul
407448
});
408449

409450
test("sessions.list marks sessions with active abortable runs", async () => {
410-
await createSessionStoreDir();
411-
await writeSessionStore({
412-
entries: {
413-
main: sessionStoreEntry("sess-main"),
414-
},
415-
});
416-
417-
const { respond } = await invokeSessionsList({
418-
requestId: "req-sessions-list-active-run",
419-
context: {
420-
chatAbortControllers: new Map([["run-1", { sessionKey: "agent:main:main" }]]),
421-
},
422-
});
423-
424-
const payload = expectRespondPayload(respond);
425-
const session = findSession(payload, "agent:main:main");
426-
expect(session.hasActiveRun).toBe(true);
451+
await expectListedSessionActiveRun("req-sessions-list-active-run", {}, true);
427452
});
428453

429454
test("sessions.list ignores terminal abortable runs kept for retry guards", async () => {
430-
await createSessionStoreDir();
431-
await writeSessionStore({
432-
entries: {
433-
main: sessionStoreEntry("sess-main"),
434-
},
435-
});
436-
437-
const { respond } = await invokeSessionsList({
438-
requestId: "req-sessions-list-terminal-run",
439-
context: {
440-
chatAbortControllers: new Map([
441-
["run-1", { sessionKey: "agent:main:main", projectSessionActive: false }],
442-
]),
443-
},
444-
});
445-
446-
const payload = expectRespondPayload(respond);
447-
const session = findSession(payload, "agent:main:main");
448-
expect(session.hasActiveRun).toBe(false);
455+
await expectListedSessionActiveRun(
456+
"req-sessions-list-terminal-run",
457+
{ projectSessionActive: false },
458+
false,
459+
);
449460
});
450461

451462
test("sessions.list ignores hidden internal abortable runs", async () => {
452-
await createSessionStoreDir();
453-
await writeSessionStore({
454-
entries: {
455-
main: sessionStoreEntry("sess-main"),
456-
},
457-
});
458-
459-
const { respond } = await invokeSessionsList({
460-
requestId: "req-sessions-list-hidden-run",
461-
context: {
462-
chatAbortControllers: new Map([
463-
["run-1", { sessionKey: "agent:main:main", controlUiVisible: false }],
464-
]),
465-
},
466-
});
467-
468-
const payload = expectRespondPayload(respond);
469-
const session = findSession(payload, "agent:main:main");
470-
expect(session.hasActiveRun).toBe(false);
463+
await expectListedSessionActiveRun(
464+
"req-sessions-list-hidden-run",
465+
{ controlUiVisible: false },
466+
false,
467+
);
471468
});
472469

473470
test("sessions.list yields before responding during bulk transcript hydration", async () => {
@@ -518,12 +515,7 @@ test("sessions.list yields before responding during bulk transcript hydration",
518515
});
519516

520517
test("sessions.list does not block on slow model catalog discovery", async () => {
521-
await createSessionStoreDir();
522-
await writeSessionStore({
523-
entries: {
524-
main: sessionStoreEntry("sess-main"),
525-
},
526-
});
518+
await writeMainSessionStore();
527519

528520
vi.useFakeTimers();
529521
try {
@@ -586,15 +578,12 @@ test("sessions.changed mutation events include live usage metadata", async () =>
586578
},
587579
});
588580

589-
const { broadcastToConnIds, responsePayload } = await invokeSessionsPatch({
581+
const result = await invokeSessionsPatch({
590582
key: "main",
591583
label: "Renamed",
592584
});
593585

594-
expectFields(responsePayload, { ok: true, key: "agent:main:main" });
595-
expectChangedBroadcast(broadcastToConnIds, {
596-
sessionKey: "agent:main:main",
597-
reason: "patch",
586+
expectMainPatchBroadcast(result, {
598587
totalTokens: 6_643,
599588
totalTokensFresh: true,
600589
contextTokens: 123_456,
@@ -605,59 +594,36 @@ test("sessions.changed mutation events include live usage metadata", async () =>
605594
});
606595

607596
test("sessions.changed mutation events include live session setting metadata", async () => {
608-
await createSessionStoreDir();
609-
await writeSessionStore({
610-
entries: {
611-
main: sessionStoreEntry("sess-main", {
612-
verboseLevel: "on",
613-
responseUsage: "full",
614-
fastMode: true,
615-
lastChannel: "telegram",
616-
lastTo: "-100123",
617-
lastAccountId: "acct-1",
618-
lastThreadId: 42,
619-
}),
620-
},
621-
});
622-
623-
const { broadcastToConnIds, responsePayload } = await invokeSessionsPatch({
624-
key: "main",
625-
verboseLevel: "on",
626-
});
627-
628-
expectFields(responsePayload, { ok: true, key: "agent:main:main" });
629-
expectChangedBroadcast(broadcastToConnIds, {
630-
sessionKey: "agent:main:main",
631-
reason: "patch",
597+
const sessionSettings = {
632598
verboseLevel: "on",
633599
responseUsage: "full",
634600
fastMode: true,
635601
lastChannel: "telegram",
636602
lastTo: "-100123",
637603
lastAccountId: "acct-1",
638604
lastThreadId: 42,
605+
} satisfies SessionStoreEntryOptions;
606+
await writeMainSessionStore(sessionSettings);
607+
608+
const result = await invokeSessionsPatch({
609+
key: "main",
610+
verboseLevel: "on",
639611
});
612+
613+
expectMainPatchBroadcast(result, sessionSettings);
640614
});
641615

642616
test("sessions.changed mutation events include sendPolicy metadata", async () => {
643-
await createSessionStoreDir();
644-
await writeSessionStore({
645-
entries: {
646-
main: sessionStoreEntry("sess-main", {
647-
sendPolicy: "deny",
648-
}),
649-
},
617+
await writeMainSessionStore({
618+
sendPolicy: "deny",
650619
});
651620

652-
const { broadcastToConnIds, responsePayload } = await invokeSessionsPatch({
621+
const result = await invokeSessionsPatch({
653622
key: "main",
654623
sendPolicy: "deny",
655624
});
656625

657-
expectFields(responsePayload, { ok: true, key: "agent:main:main" });
658-
expectChangedBroadcast(broadcastToConnIds, {
659-
sessionKey: "agent:main:main",
660-
reason: "patch",
626+
expectMainPatchBroadcast(result, {
661627
sendPolicy: "deny",
662628
});
663629
});

0 commit comments

Comments
 (0)