diff --git a/apps/app/src/components/plugin/management/BrowsePluginsTab.test.tsx b/apps/app/src/components/plugin/management/BrowsePluginsTab.test.tsx index b94b048c5..32f16ab51 100644 --- a/apps/app/src/components/plugin/management/BrowsePluginsTab.test.tsx +++ b/apps/app/src/components/plugin/management/BrowsePluginsTab.test.tsx @@ -37,6 +37,17 @@ const INCOMPATIBLE_ENTRY: PluginCatalogSearchEntry = { incompatibleReason: "Requires a newer BB version", }; +const GITHUB_ENTRY: PluginCatalogSearchEntry = { + ...MEMORY_ENTRY, + entryId: "github", + pluginId: "github", + displayName: "GitHub", + description: "Browse GitHub issues and pull requests in BB.", + icon: "Github", + category: "Developer tools", + source: "builtin:github", +}; + const INSTALLED_MEMORY_PLUGIN = { id: "memory", source: "builtin:memory", @@ -79,7 +90,7 @@ describe("BrowsePluginsTab", () => { } if (url === "/api/v1/plugin-catalog/search?q=") { return jsonResponse({ - results: [MEMORY_ENTRY, INCOMPATIBLE_ENTRY], + results: [MEMORY_ENTRY, INCOMPATIBLE_ENTRY, GITHUB_ENTRY], }); } if (url === "/api/v1/plugins") { @@ -109,6 +120,10 @@ describe("BrowsePluginsTab", () => { expect( screen.getByRole("textbox", { name: "Search plugins" }), ).toBeTruthy(); + const githubGrid = screen + .getByRole("button", { name: "Open GitHub details" }) + .closest('[class*="auto-fill"]'); + expect(githubGrid?.className).toContain("auto-fill"); expect(screen.queryByText(MEMORY_ENTRY.source)).toBeNull(); expect(screen.getByText("Requires a newer BB version")).toBeTruthy(); diff --git a/apps/app/src/components/plugin/management/BrowsePluginsTab.tsx b/apps/app/src/components/plugin/management/BrowsePluginsTab.tsx index ee43ba069..9022eb2a1 100644 --- a/apps/app/src/components/plugin/management/BrowsePluginsTab.tsx +++ b/apps/app/src/components/plugin/management/BrowsePluginsTab.tsx @@ -136,7 +136,9 @@ export function BrowsePluginsTab({

{category}

- + {categoryEntries.map((entry) => ( + ) : skill.scope === "plugin" ? ( + + } + accessibleLabel={`${skill.name} is included with ${includedPluginDescription(skill)}`} + /> ) : undefined } description={description} @@ -315,7 +327,7 @@ export function SkillsOverview({ normalizedQuery === "" && providerFilters.length === 0 ? "No skills in your library." : normalizedQuery === "" - ? "No skills match these agents." + ? "No skills match these providers." : `No skills match "${query}"` } /> @@ -367,7 +379,7 @@ export function SkillsOverview({ controls={ <> { }); expect(markup).not.toContain("claude-skill"); expect(markup).toContain("Review the current diff."); - expect(markup).toContain('aria-label="Agent: 1 selected"'); + expect(markup).toContain('aria-label="Provider: 1 selected"'); expect(markup).toContain("Sort"); expect(markup).toContain('role="tab"'); expect(markup).toContain("Library"); @@ -269,6 +269,25 @@ describe("SkillsOverview", () => { ); }); + it("labels skills bundled with plugins", () => { + const markup = render({ + skills: [ + makeSkill({ + name: "automations", + provider: null, + scope: "plugin", + pluginId: "automations", + manageable: false, + }), + ], + }); + + expect(markup).toContain(">Plugin<"); + expect(markup).toContain( + 'aria-label="automations is included with Automations (bb plugin)"', + ); + }); + it("renders browse content as the active full-page collection mode", () => { const registrySkill = makeRegistrySkill({ installs: 123_456, stars: 654 }); const markup = renderToStaticMarkup( @@ -317,7 +336,7 @@ describe("SkillsOverview", () => { ); fireEvent.pointerDown( - screen.getByRole("button", { name: "Agent: 1 selected" }), + screen.getByRole("button", { name: "Provider: 1 selected" }), ); await waitFor(() => { @@ -358,13 +377,13 @@ describe("SkillsOverview", () => { await waitFor(() => { expect( - screen.getByRole("button", { name: "Agent: 1 selected" }), + screen.getByRole("button", { name: "Provider: 1 selected" }), ).toBeTruthy(); expect(screen.queryByText("codex-skill")).toBeNull(); }); fireEvent.pointerDown( - screen.getByRole("button", { name: "Agent: 1 selected" }), + screen.getByRole("button", { name: "Provider: 1 selected" }), ); const bbFilter = screen.getByRole("menuitemcheckbox", { name: "bb" }); expect(bbFilter.getAttribute("aria-checked")).toBe("true"); @@ -396,7 +415,7 @@ describe("SkillsOverview", () => { ); fireEvent.pointerDown( - screen.getByRole("button", { name: "Agent: 1 selected" }), + screen.getByRole("button", { name: "Provider: 1 selected" }), ); fireEvent.click(screen.getByRole("menuitemcheckbox", { name: "bb" })); fireEvent.click(