From 2d55e0a00be7b6d5137335ac1afdf8e6bdea3a4a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 20 Apr 2026 20:47:35 +0100 Subject: [PATCH] perf(test): avoid app chat slash reload --- ui/src/ui/app-chat.test.ts | 51 ++++++++++++++---------- ui/src/ui/chat/slash-command-executor.ts | 8 +++- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/ui/src/ui/app-chat.test.ts b/ui/src/ui/app-chat.test.ts index 3c2eea19684..edd3e6186bf 100644 --- a/ui/src/ui/app-chat.test.ts +++ b/ui/src/ui/app-chat.test.ts @@ -2,6 +2,7 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import type { ChatHost } from "./app-chat.ts"; +import type { GatewaySessionRow, SessionsListResult } from "./types.ts"; const { setLastActiveSessionKeyMock } = vi.hoisted(() => ({ setLastActiveSessionKeyMock: vi.fn(), @@ -15,10 +16,7 @@ let handleSendChat: typeof import("./app-chat.ts").handleSendChat; let refreshChatAvatar: typeof import("./app-chat.ts").refreshChatAvatar; let clearPendingQueueItemsForRun: typeof import("./app-chat.ts").clearPendingQueueItemsForRun; -async function loadChatHelpers(params?: { reload?: boolean }): Promise { - if (params?.reload) { - vi.resetModules(); - } +async function loadChatHelpers(): Promise { ({ handleSendChat, refreshChatAvatar, clearPendingQueueItemsForRun } = await import("./app-chat.ts")); } @@ -60,6 +58,25 @@ function makeHost(overrides?: Partial): ChatHost { }; } +function createSessionsResult(sessions: GatewaySessionRow[]): SessionsListResult { + return { + ts: 0, + path: "", + count: sessions.length, + defaults: { modelProvider: null, model: null, contextTokens: null }, + sessions, + }; +} + +function row(key: string, overrides?: Partial): GatewaySessionRow { + return { + key, + kind: "direct", + updatedAt: null, + ...overrides, + }; +} + function createDeferred() { let resolve!: (value: T) => void; let reject!: (reason?: unknown) => void; @@ -172,7 +189,6 @@ describe("handleSendChat", () => { afterEach(() => { vi.unstubAllGlobals(); - vi.doUnmock("./chat/slash-command-executor.ts"); }); it("keeps slash-command model changes in sync with the chat header cache", async () => { @@ -354,24 +370,19 @@ describe("handleSendChat", () => { }); it("shows a visible pending item for /steer on the active run", async () => { - vi.doMock("./chat/slash-command-executor.ts", async () => { - const actual = await vi.importActual( - "./chat/slash-command-executor.ts", - ); - return { - ...actual, - executeSlashCommand: vi.fn(async () => ({ - content: "Steered.", - pendingCurrentRun: true, - })), - }; - }); - await loadChatHelpers({ reload: true }); - const host = makeHost({ - client: { request: vi.fn() } as unknown as ChatHost["client"], + client: { + request: vi.fn(async (method: string) => { + if (method === "chat.send") { + return { status: "started", runId: "run-1", messageSeq: 2 }; + } + throw new Error(`Unexpected request: ${method}`); + }), + } as unknown as ChatHost["client"], chatRunId: "run-1", chatMessage: "/steer tighten the plan", + sessionKey: "agent:main:main", + sessionsResult: createSessionsResult([row("agent:main:main", { status: "running" })]), }); await handleSendChat(host); diff --git a/ui/src/ui/chat/slash-command-executor.ts b/ui/src/ui/chat/slash-command-executor.ts index 9f3f2e271d7..9fb4b14a58e 100644 --- a/ui/src/ui/chat/slash-command-executor.ts +++ b/ui/src/ui/chat/slash-command-executor.ts @@ -743,6 +743,7 @@ async function resolveSteerTarget( return { error: "empty" }; } const spaceIdx = trimmed.indexOf(" "); + let resolvedSessions: SessionsListResult | undefined; if (spaceIdx > 0) { const maybeTarget = trimmed.slice(0, spaceIdx); const rest = trimmed.slice(spaceIdx + 1).trim(); @@ -751,6 +752,7 @@ async function resolveSteerTarget( if (rest && normalizeLowercaseStringOrEmpty(maybeTarget) !== "all") { const sessions = context.sessionsResult ?? (await client.request("sessions.list", {})); + resolvedSessions = sessions; const matched = resolveSteerSubagent(sessions?.sessions ?? [], sessionKey, maybeTarget); if (matched.length === 1) { return { key: matched[0], message: rest, label: maybeTarget, sessions }; @@ -760,7 +762,11 @@ async function resolveSteerTarget( } } } - return { key: sessionKey, message: trimmed }; + return { + key: sessionKey, + message: trimmed, + sessions: resolvedSessions ?? context.sessionsResult ?? undefined, + }; } function isActiveSteerSession(session: GatewaySessionRow | undefined): boolean {