diff --git a/ui/src/pages/apps/Browse.test.tsx b/ui/src/pages/apps/Browse.test.tsx index 1696a5d4e5a..d45b47bce22 100644 --- a/ui/src/pages/apps/Browse.test.tsx +++ b/ui/src/pages/apps/Browse.test.tsx @@ -81,6 +81,7 @@ describe("Browse store door (PAP-13254 door 1)", () => { galleryEntry({ key: "github", name: "GitHub", tagline: "Open PRs and issues." }), galleryEntry({ key: "slack", name: "Slack", tagline: "Post messages to channels." }), galleryEntry({ key: "notion", name: "Notion", tagline: "Read and update workspace content." }), + galleryEntry({ key: "linear", name: "Linear", tagline: "Read issues and projects." }), galleryEntry({ key: "acme", name: "Acme CRM", tagline: "Sync deals and contacts." }), ], }); @@ -126,7 +127,7 @@ describe("Browse store door (PAP-13254 door 1)", () => { expect(text).toContain("Connect your own tool"); }); - it("enables Notion, Zapier, and custom URLs while fading unfinished integrations", async () => { + it("enables allowlisted direct OAuth apps, Zapier, and custom URLs while fading unfinished integrations", async () => { await renderBrowse(); const zapierTiles = Array.from(container.querySelectorAll("button")).filter((button) => @@ -138,6 +139,9 @@ describe("Browse store door (PAP-13254 door 1)", () => { const notionTiles = Array.from(container.querySelectorAll("button")).filter((button) => button.textContent?.includes("Notion"), ); + const linearTiles = Array.from(container.querySelectorAll("button")).filter((button) => + button.textContent?.includes("Linear"), + ); const tile = Array.from(container.querySelectorAll("button")).find((button) => button.textContent?.includes("Acme CRM"), ); @@ -149,6 +153,9 @@ describe("Browse store door (PAP-13254 door 1)", () => { expect(zapierTiles.every((button) => !button.disabled)).toBe(true); expect(notionTiles).toHaveLength(2); expect(notionTiles.every((button) => !button.disabled)).toBe(true); + expect(linearTiles).toHaveLength(2); + expect(linearTiles.every((button) => !button.disabled)).toBe(true); + expect(linearTiles.every((button) => button.textContent?.includes("Connect"))).toBe(true); expect(githubTiles.every((button) => button.disabled)).toBe(true); expect(tile?.disabled).toBe(true); expect(byoCard?.disabled).toBe(false); @@ -165,6 +172,11 @@ describe("Browse store door (PAP-13254 door 1)", () => { }); expect(navigateMock).toHaveBeenCalledWith("/apps/connect?source=notion"); + await act(async () => { + linearTiles[0]?.dispatchEvent(new MouseEvent("click", { bubbles: true })); + }); + expect(navigateMock).toHaveBeenCalledWith("/apps/connect?source=linear"); + await act(async () => { byoCard?.dispatchEvent(new MouseEvent("click", { bubbles: true })); }); diff --git a/ui/src/pages/apps/Browse.tsx b/ui/src/pages/apps/Browse.tsx index e7daa94c478..27fc21678aa 100644 --- a/ui/src/pages/apps/Browse.tsx +++ b/ui/src/pages/apps/Browse.tsx @@ -20,14 +20,14 @@ import { AdvancedToolsLink, BYO_CONNECT_HREF, ByoConnectCard, - NOTION_CONNECT_HREF, POPULAR_KEYS, ZAPIER_CONNECT_HREF, } from "./store-cards"; +import { appSourceConnectHref, isMcpDirectOAuthConnectSlug } from "./app-connect-policy"; function connectHrefFor(entry: AppGalleryDisplayEntry): string | null { const slug = appDefinitionSlug(entry); - if (slug === "notion") return NOTION_CONNECT_HREF; + if (isMcpDirectOAuthConnectSlug(slug)) return appSourceConnectHref(slug); if (slug === "zapier") return ZAPIER_CONNECT_HREF; return null; }