From dba2caf2f676e812fbc98981a079d71e4d3d1606 Mon Sep 17 00:00:00 2001 From: Dotta Date: Sat, 3 Oct 2026 06:59:46 -0500 Subject: [PATCH] fix(mcp): preserve write opt-out across organization selection Co-Authored-By: Paperclip --- ui/src/pages/McpConnect.test.tsx | 11 +++++++++-- ui/src/pages/McpConnect.tsx | 2 +- ui/storybook/stories/public-mcp-consent.stories.tsx | 4 ++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ui/src/pages/McpConnect.test.tsx b/ui/src/pages/McpConnect.test.tsx index 7c09cd4e951..0fb3c3833e7 100644 --- a/ui/src/pages/McpConnect.test.tsx +++ b/ui/src/pages/McpConnect.test.tsx @@ -20,7 +20,10 @@ vi.mock("../api/client", () => ({ api: { get: vi.fn(async () => ({ id: route.id, clientName: "Assistant", redirectOrigin: "https://assistant.example.test", requestedWrite: route.requestedWrite, offlineAccess: true, requiresSignIn: false, requestedCompanyId: route.companyId, - companies: route.unavailable ? [] : [{ id: route.companyId ?? "company-one", name: "Acme Research", logoUrl: "/api/assets/acme-logo/content", canWrite: route.canWrite }], setupUrl: null, + companies: route.unavailable ? [] : [ + { id: route.companyId ?? "company-one", name: "Acme Research", logoUrl: "/api/assets/acme-logo/content", canWrite: route.canWrite }, + ...(!route.companyId ? [{ id: "company-two", name: "Design Partners", logoUrl: null, canWrite: true }] : []), + ], setupUrl: null, })), post: vi.fn(() => new Promise(() => {})), } })); @@ -45,7 +48,7 @@ function setup() { }; } -it("defaults eligible writes on after selection, preserves opt-out on refetch, and submits read-only consent", async () => { +it("defaults eligible writes on and preserves opt-out across organization changes and refetch", async () => { const page = setup(); try { await vi.waitFor(() => expect(page.container.querySelector('input[type="radio"]')).not.toBeNull()); @@ -54,6 +57,10 @@ it("defaults eligible writes on after selection, preserves opt-out on refetch, a flushSync(() => (page.container.querySelector('input[type="radio"]') as HTMLInputElement).click()); expect(page.checkbox().getAttribute("aria-checked")).toBe("true"); flushSync(() => page.checkbox().click()); + flushSync(() => (page.container.querySelector('input[value="company-two"]') as HTMLInputElement).click()); + expect(page.checkbox().getAttribute("aria-checked")).toBe("false"); + flushSync(() => (page.container.querySelector('input[value="company-one"]') as HTMLInputElement).click()); + expect(page.checkbox().getAttribute("aria-checked")).toBe("false"); await page.client.invalidateQueries({ queryKey: ["mcp-request", route.id] }); expect(page.checkbox().getAttribute("aria-checked")).toBe("false"); flushSync(() => page.connect().click()); diff --git a/ui/src/pages/McpConnect.tsx b/ui/src/pages/McpConnect.tsx index 4f4d90ad31e..ad44ce7ebf3 100644 --- a/ui/src/pages/McpConnect.tsx +++ b/ui/src/pages/McpConnect.tsx @@ -44,7 +44,7 @@ function McpConnectRequest({ id }: { id: string }) { :
Organization {data.companies.map((item) => )} diff --git a/ui/storybook/stories/public-mcp-consent.stories.tsx b/ui/storybook/stories/public-mcp-consent.stories.tsx index a10967708e7..9add31c92b1 100644 --- a/ui/storybook/stories/public-mcp-consent.stories.tsx +++ b/ui/storybook/stories/public-mcp-consent.stories.tsx @@ -27,10 +27,14 @@ export const AllowDelegation: Story = { play: async context => { export const SwitchingOrganizationsResetsConsent: Story = { play: async context => { await AllowDelegation.play!(context); const c = within(context.canvasElement); + await userEvent.click(c.getByRole("checkbox")); await userEvent.click(c.getByRole("radio", { name: "Design Partners" })); await expect(c.getByRole("checkbox")).not.toBeChecked(); await expect(c.getByRole("checkbox")).toBeDisabled(); await expect(c.getByText("Your role in this organization is read-only.")).toBeVisible(); + await userEvent.click(c.getByRole("radio", { name: "Acme Research" })); + await expect(c.getByRole("checkbox")).toBeEnabled(); + await expect(c.getByRole("checkbox")).not.toBeChecked(); } }; export const ReadOnlyRequest: Story = { parameters: { fixture: { request: { clientName: "Claude", redirectOrigin: "https://claude.ai", requestedWrite: false, offlineAccess: false } } } }; export const SignInRequired: Story = { parameters: { fixture: { request: { requiresSignIn: true, companies: [] } } } };