mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-28 19:11:03 +08:00
76 lines
3.4 KiB
TypeScript
76 lines
3.4 KiB
TypeScript
/**
|
|
* Source contract test for selectSession's connection handling.
|
|
*
|
|
* Static analysis — reads session.tsx and verifies that selectSession updates
|
|
* the current session id BEFORE (and independently of) the backend connection
|
|
* check, and only defers the message fetch when offline.
|
|
*
|
|
* Regression guard: previously selectSession bailed out entirely when
|
|
* `server.isConnected()` was false. In Agent Manager the side diff is resolved
|
|
* from the worktree selection independently of currentSessionID, so a switch
|
|
* during a transient disconnect moved the diff but left the chat frozen on the
|
|
* previous session ("switching only changes the sidebar diff"). The chat must
|
|
* always follow the selection; only the network fetch may wait for reconnect.
|
|
*/
|
|
|
|
import { describe, it, expect } from "bun:test"
|
|
import fs from "node:fs"
|
|
import path from "node:path"
|
|
|
|
const ROOT = path.resolve(import.meta.dir, "../..")
|
|
const SESSION_FILE = path.join(ROOT, "webview-ui/src/context/session.tsx")
|
|
|
|
const source = fs.readFileSync(SESSION_FILE, "utf-8")
|
|
|
|
describe("selectSession keeps the chat in sync with the selection while offline", () => {
|
|
const start = source.indexOf("function selectSession(")
|
|
const cloudGuard = source.indexOf('id.startsWith("cloud:")', start)
|
|
const setCurrent = source.indexOf("setCurrentSessionID(id)", start)
|
|
const offlineDefer = source.indexOf("if (!server.isConnected()) {", start)
|
|
|
|
it("selectSession exists", () => {
|
|
expect(start).toBeGreaterThan(-1)
|
|
})
|
|
|
|
it("returns early for cloud preview ids before touching the current session", () => {
|
|
expect(cloudGuard).toBeGreaterThan(start)
|
|
expect(cloudGuard).toBeLessThan(setCurrent)
|
|
})
|
|
|
|
it("sets currentSessionID before checking the connection (chat follows selection offline)", () => {
|
|
expect(setCurrent).toBeGreaterThan(-1)
|
|
expect(offlineDefer).toBeGreaterThan(-1)
|
|
// The whole point of the fix: the local selection update must precede the
|
|
// connection guard, so a disconnected switch no longer freezes the chat.
|
|
expect(setCurrent).toBeLessThan(offlineDefer)
|
|
})
|
|
|
|
it("defers the fetch for any session while offline, including cached ones", () => {
|
|
const body = source.slice(start, source.indexOf("\n function loadFocusedMessages("))
|
|
// Queue a replay unconditionally. The earlier `deferredFetch = ready ? undefined : id`
|
|
// form skipped cached sessions, so a reconnect never re-sent the focus load that
|
|
// re-focuses the backend (focusSession/contextSessionID/SSE tracking/reconcile).
|
|
expect(body).toContain("deferredFetch = { id, focus }")
|
|
expect(body).not.toMatch(/deferredFetch\s*=\s*ready\s*\?/)
|
|
})
|
|
})
|
|
|
|
describe("a deferred fetch is replayed on reconnect", () => {
|
|
it("watches the connection and replays the deferred session load", () => {
|
|
expect(source).toContain("on(server.isConnected")
|
|
const effect = source.slice(source.indexOf("on(server.isConnected"))
|
|
expect(effect).toContain("deferredFetch")
|
|
// Replays with the focus/replace choice so cached sessions still re-focus the backend.
|
|
expect(effect).toMatch(
|
|
/loadFocusedMessages\(\s*pending\.id,\s*loaded\(\)\.has\(pending\.id\),\s*pending\.focus\s*\)/,
|
|
)
|
|
})
|
|
|
|
it("the focused load helper sends focus for cached sessions and replace otherwise", () => {
|
|
const helper = source.slice(source.indexOf("function loadFocusedMessages("))
|
|
expect(helper).toMatch(/mode: "focus"/)
|
|
expect(helper).toMatch(/mode: "replace"/)
|
|
expect(helper).toContain("focus: false")
|
|
})
|
|
})
|