Explorar o código

feat(app): support current review data (#38460)

Brendan Allan hai 1 mes
pai
achega
3819848cf2

+ 4 - 1
packages/app/e2e/regression/review-terminal-stacked.spec.ts

@@ -20,6 +20,7 @@ const branchDiffs = [
 test("keeps the review tree and terminal sized when both panels are open", async ({ page }) => {
 test("keeps the review tree and terminal sized when both panels are open", async ({ page }) => {
   test.setTimeout(120_000)
   test.setTimeout(120_000)
   const events: Array<{ directory: string; payload: Record<string, unknown> }> = []
   const events: Array<{ directory: string; payload: Record<string, unknown> }> = []
+  const sessionStatus = { [sessionID]: { type: "idle" as "busy" | "idle" } }
   let detailVersion = 1
   let detailVersion = 1
   let detailFailures = 1
   let detailFailures = 1
   await page.setViewportSize({ width: 1400, height: 900 })
   await page.setViewportSize({ width: 1400, height: 900 })
@@ -55,7 +56,7 @@ test("keeps the review tree and terminal sized when both panels are open", async
         time: { created: 1700000000000, updated: 1700000000000 },
         time: { created: 1700000000000, updated: 1700000000000 },
       },
       },
     ],
     ],
-    sessionStatus: { [sessionID]: { type: "idle" } },
+    sessionStatus: () => sessionStatus,
     pageMessages: () => ({ items: [] }),
     pageMessages: () => ({ items: [] }),
     events: () => events.splice(0, 1),
     events: () => events.splice(0, 1),
     eventRetry: 16,
     eventRetry: 16,
@@ -143,6 +144,7 @@ test("keeps the review tree and terminal sized when both panels are open", async
   const preview = page.locator('[data-slot="session-review-v2-diff-scroll"]')
   const preview = page.locator('[data-slot="session-review-v2-diff-scroll"]')
   await expect(preview).toContainText("after-1")
   await expect(preview).toContainText("after-1")
   detailVersion = 2
   detailVersion = 2
+  sessionStatus[sessionID] = { type: "busy" }
   events.push(statusEvent("busy"))
   events.push(statusEvent("busy"))
   await expect(page.getByRole("button", { name: "Stop" })).toBeVisible()
   await expect(page.getByRole("button", { name: "Stop" })).toBeVisible()
   const refreshedDiff = page.waitForRequest((request) => {
   const refreshedDiff = page.waitForRequest((request) => {
@@ -152,6 +154,7 @@ test("keeps the review tree and terminal sized when both panels are open", async
       url.searchParams.get("directory")?.replaceAll("\\", "/").endsWith("/src/branch/d00027") === true
       url.searchParams.get("directory")?.replaceAll("\\", "/").endsWith("/src/branch/d00027") === true
     )
     )
   })
   })
+  sessionStatus[sessionID] = { type: "idle" }
   events.push(statusEvent("idle"))
   events.push(statusEvent("idle"))
   await refreshedDiff
   await refreshedDiff
   await expect(preview).toContainText("after-2")
   await expect(preview).toContainText("after-2")

+ 3 - 0
packages/app/e2e/regression/session-todo-dock-navigation.spec.ts

@@ -27,6 +27,7 @@ test("animates todo lifecycle without replaying it across session tabs", async (
   test.setTimeout(90_000)
   test.setTimeout(90_000)
   const events: EventPayload[] = []
   const events: EventPayload[] = []
   const todos: Record<string, typeof activeTodos> = { [sourceID]: [], [otherID]: [] }
   const todos: Record<string, typeof activeTodos> = { [sourceID]: [], [otherID]: [] }
+  const sessionStatus: Record<string, { type: "busy" | "idle" }> = {}
 
 
   await mockOpenCodeServer(page, {
   await mockOpenCodeServer(page, {
     directory,
     directory,
@@ -60,6 +61,7 @@ test("animates todo lifecycle without replaying it across session tabs", async (
     pageMessages: () => ({ items: [] }),
     pageMessages: () => ({ items: [] }),
     events: () => events.splice(0, 1),
     events: () => events.splice(0, 1),
     eventRetry: 16,
     eventRetry: 16,
+    sessionStatus: () => sessionStatus,
     todos: (sessionID) => todos[sessionID] ?? [],
     todos: (sessionID) => todos[sessionID] ?? [],
   })
   })
   await configurePage(page)
   await configurePage(page)
@@ -69,6 +71,7 @@ test("animates todo lifecycle without replaying it across session tabs", async (
   const dock = page.locator('[data-component="session-todo-dock"]')
   const dock = page.locator('[data-component="session-todo-dock"]')
   await expect(dock).toHaveCount(0)
   await expect(dock).toHaveCount(0)
 
 
+  sessionStatus[sourceID] = { type: "busy" }
   events.push(statusEvent(sourceID, "busy"))
   events.push(statusEvent(sourceID, "busy"))
   await expect(page.getByRole("button", { name: "Stop" })).toBeVisible()
   await expect(page.getByRole("button", { name: "Stop" })).toBeVisible()
 
 

+ 3 - 2
packages/app/e2e/utils/mock-server.ts

@@ -24,7 +24,7 @@ export interface MockServerConfig {
   fileList?: (path: string) => unknown | Promise<unknown>
   fileList?: (path: string) => unknown | Promise<unknown>
   fileContent?: (path: string) => unknown | Promise<unknown>
   fileContent?: (path: string) => unknown | Promise<unknown>
   findFiles?: (input: { query: string; dirs?: string; limit?: number }) => unknown
   findFiles?: (input: { query: string; dirs?: string; limit?: number }) => unknown
-  sessionStatus?: unknown
+  sessionStatus?: Record<string, unknown> | (() => Record<string, unknown>)
 }
 }
 
 
 export async function mockOpenCodeServer(page: Page, config: MockServerConfig) {
 export async function mockOpenCodeServer(page: Page, config: MockServerConfig) {
@@ -79,7 +79,8 @@ export async function mockOpenCodeServer(page: Page, config: MockServerConfig) {
       return json(route, typeof config.permissions === "function" ? config.permissions() : (config.permissions ?? []))
       return json(route, typeof config.permissions === "function" ? config.permissions() : (config.permissions ?? []))
     if (path === "/question")
     if (path === "/question")
       return json(route, typeof config.questions === "function" ? config.questions() : (config.questions ?? []))
       return json(route, typeof config.questions === "function" ? config.questions() : (config.questions ?? []))
-    if (path === "/session/status") return json(route, config.sessionStatus ?? {})
+    if (path === "/session/status")
+      return json(route, typeof config.sessionStatus === "function" ? config.sessionStatus() : (config.sessionStatus ?? {}))
     if (path === "/vcs/diff" && config.vcsDiff) return json(route, config.vcsDiff)
     if (path === "/vcs/diff" && config.vcsDiff) return json(route, config.vcsDiff)
     if (path === "/file" && config.fileList)
     if (path === "/file" && config.fileList)
       return json(route, await config.fileList(url.searchParams.get("path") ?? ""))
       return json(route, await config.fileList(url.searchParams.get("path") ?? ""))