From 4f3243bdd4d2649d627039c8f49a5e981f963a02 Mon Sep 17 00:00:00 2001 From: Rahul A Mistry Date: Mon, 27 Jul 2026 00:52:27 +0000 Subject: [PATCH 1/2] fix(ui): keep mutable selects open --- .../remote-session-settings.spec.ts | 54 +++++++++++++++++-- packages/ui/src/v2/components/select-v2.tsx | 1 + 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/packages/app/e2e/regression/remote-session-settings.spec.ts b/packages/app/e2e/regression/remote-session-settings.spec.ts index 35a0aa44cda8..ebd5436b2621 100644 --- a/packages/app/e2e/regression/remote-session-settings.spec.ts +++ b/packages/app/e2e/regression/remote-session-settings.spec.ts @@ -43,6 +43,37 @@ test("session settings use the remote server context", async ({ page }) => { await expect(dialog.getByRole("switch", { name: "Server A Model" })).toHaveCount(0) }) +test("mutable settings selects reopen after changing their value", async ({ page }) => { + const permissionRequests: string[] = [] + const configUpdates: Record[] = [] + await mockServers(page, permissionRequests, [], configUpdates) + await configureServers(page) + + await page.goto(`/server/${base64Encode(serverB)}/session/${sessionB.id}`) + await expect(page.getByText(sessionB.title).first()).toBeVisible() + await page.keyboard.press("Control+,") + + const content = page.locator('[data-slot="select-v2-content"]') + const theme = page.locator('[data-action="settings-theme"]') + await theme.click() + await expect(content).toBeVisible() + await content.locator('[data-component="menu-v2-item"]:not([data-selected])').first().click() + await theme.click() + await expect(content).toBeVisible() + await theme.click() + await expect(content).toHaveCount(0) + + const shell = page.locator('[data-action="settings-shell"]') + await shell.click() + await expect(content).toBeVisible() + await content.getByText("PowerShell").click() + await expect.poll(() => configUpdates).toEqual([{ shell: "powershell" }]) + await shell.click() + await expect(content).toBeVisible() + await shell.click() + await expect(content).toHaveCount(0) +}) + test("auto-accept responds for an unfocused server session", async ({ page }) => { const permissionRequests: string[] = [] const permissionResponses: PermissionResponse[] = [] @@ -161,7 +192,13 @@ async function configureServers(page: Page, tabs: { type: "session"; server: str ) } -async function mockServers(page: Page, permissionRequests: string[], permissionResponses: PermissionResponse[] = []) { +async function mockServers( + page: Page, + permissionRequests: string[], + permissionResponses: PermissionResponse[] = [], + configUpdates: Record[] = [], +) { + let config: Record = {} await page.route("**/*", async (route) => { const url = new URL(route.request().url()) if (url.origin !== serverA && url.origin !== serverB) return route.fallback() @@ -220,9 +257,20 @@ async function mockServers(page: Page, permissionRequests: string[], permissionR permissionRequests.push(url.toString()) return json(route, []) } - if (["/skill", "/command", "/lsp", "/formatter", "/question", "/vcs/diff", "/pty/shells"].includes(url.pathname)) + if (url.pathname === "/pty/shells") + return json(route, [ + { path: "C:/Program Files/PowerShell/7/pwsh.exe", name: "powershell", acceptable: true }, + { path: "C:/Windows/System32/cmd.exe", name: "cmd", acceptable: true }, + ]) + if (["/skill", "/command", "/lsp", "/formatter", "/question", "/vcs/diff"].includes(url.pathname)) return json(route, []) - if (["/global/config", "/config", "/provider/auth", "/mcp"].includes(url.pathname)) return json(route, {}) + if (url.pathname === "/global/config" || url.pathname === "/config") { + if (route.request().method() !== "PATCH") return json(route, config) + config = { ...config, ...(route.request().postDataJSON() as Record) } + configUpdates.push(config) + return json(route, config) + } + if (["/provider/auth", "/mcp"].includes(url.pathname)) return json(route, {}) if (url.pathname === "/provider") return json(route, provider(remote ? "server-b" : "server-a")) if (url.pathname === "/agent") return json(route, [{ name: "build", mode: "primary" }]) if (url.pathname === "/project" || url.pathname === "/project/current") { diff --git a/packages/ui/src/v2/components/select-v2.tsx b/packages/ui/src/v2/components/select-v2.tsx index 7f9a2b5d3761..57348ed39209 100644 --- a/packages/ui/src/v2/components/select-v2.tsx +++ b/packages/ui/src/v2/components/select-v2.tsx @@ -121,6 +121,7 @@ export function SelectV2(props: SelectV2Props) { {...others} multiple={false} + allowDuplicateSelectionEvents={false} disabled={local.disabled} data-component="select-v2-root" placement={local.placement ?? (inline() ? "bottom-end" : "bottom-start")} From a6a8e28dc06b888e868e753bab8d0bab706f2e05 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Mon, 27 Jul 2026 10:46:13 +0800 Subject: [PATCH 2/2] test(app): remove select reopen e2e --- .../remote-session-settings.spec.ts | 54 ++----------------- 1 file changed, 3 insertions(+), 51 deletions(-) diff --git a/packages/app/e2e/regression/remote-session-settings.spec.ts b/packages/app/e2e/regression/remote-session-settings.spec.ts index ebd5436b2621..35a0aa44cda8 100644 --- a/packages/app/e2e/regression/remote-session-settings.spec.ts +++ b/packages/app/e2e/regression/remote-session-settings.spec.ts @@ -43,37 +43,6 @@ test("session settings use the remote server context", async ({ page }) => { await expect(dialog.getByRole("switch", { name: "Server A Model" })).toHaveCount(0) }) -test("mutable settings selects reopen after changing their value", async ({ page }) => { - const permissionRequests: string[] = [] - const configUpdates: Record[] = [] - await mockServers(page, permissionRequests, [], configUpdates) - await configureServers(page) - - await page.goto(`/server/${base64Encode(serverB)}/session/${sessionB.id}`) - await expect(page.getByText(sessionB.title).first()).toBeVisible() - await page.keyboard.press("Control+,") - - const content = page.locator('[data-slot="select-v2-content"]') - const theme = page.locator('[data-action="settings-theme"]') - await theme.click() - await expect(content).toBeVisible() - await content.locator('[data-component="menu-v2-item"]:not([data-selected])').first().click() - await theme.click() - await expect(content).toBeVisible() - await theme.click() - await expect(content).toHaveCount(0) - - const shell = page.locator('[data-action="settings-shell"]') - await shell.click() - await expect(content).toBeVisible() - await content.getByText("PowerShell").click() - await expect.poll(() => configUpdates).toEqual([{ shell: "powershell" }]) - await shell.click() - await expect(content).toBeVisible() - await shell.click() - await expect(content).toHaveCount(0) -}) - test("auto-accept responds for an unfocused server session", async ({ page }) => { const permissionRequests: string[] = [] const permissionResponses: PermissionResponse[] = [] @@ -192,13 +161,7 @@ async function configureServers(page: Page, tabs: { type: "session"; server: str ) } -async function mockServers( - page: Page, - permissionRequests: string[], - permissionResponses: PermissionResponse[] = [], - configUpdates: Record[] = [], -) { - let config: Record = {} +async function mockServers(page: Page, permissionRequests: string[], permissionResponses: PermissionResponse[] = []) { await page.route("**/*", async (route) => { const url = new URL(route.request().url()) if (url.origin !== serverA && url.origin !== serverB) return route.fallback() @@ -257,20 +220,9 @@ async function mockServers( permissionRequests.push(url.toString()) return json(route, []) } - if (url.pathname === "/pty/shells") - return json(route, [ - { path: "C:/Program Files/PowerShell/7/pwsh.exe", name: "powershell", acceptable: true }, - { path: "C:/Windows/System32/cmd.exe", name: "cmd", acceptable: true }, - ]) - if (["/skill", "/command", "/lsp", "/formatter", "/question", "/vcs/diff"].includes(url.pathname)) + if (["/skill", "/command", "/lsp", "/formatter", "/question", "/vcs/diff", "/pty/shells"].includes(url.pathname)) return json(route, []) - if (url.pathname === "/global/config" || url.pathname === "/config") { - if (route.request().method() !== "PATCH") return json(route, config) - config = { ...config, ...(route.request().postDataJSON() as Record) } - configUpdates.push(config) - return json(route, config) - } - if (["/provider/auth", "/mcp"].includes(url.pathname)) return json(route, {}) + if (["/global/config", "/config", "/provider/auth", "/mcp"].includes(url.pathname)) return json(route, {}) if (url.pathname === "/provider") return json(route, provider(remote ? "server-b" : "server-a")) if (url.pathname === "/agent") return json(route, [{ name: "build", mode: "primary" }]) if (url.pathname === "/project" || url.pathname === "/project/current") {