feat(skills,mcp): menus Skills et MCP unifies avec selection cochable des tools #297 (SkillsPanel devient la surface unique d'assignation cochable des skills IdeA + plugins — cible agent, recherche, groupes IdeA/Plugins, tombstones retirables, CRUD catalogue natif conserve, stores separes SkillGateway/PluginGateway; nouveau panneau MCP dedie McpPanel desktop+web — tools MCP IdeA via PermissionGateway et tools MCP plugins catalogues via PluginGateway groupes par plugin/serveur, selection cochable, fin de la saisie manuelle du nom exact, serveurs sans catalogue en tombstones retirables uniquement; retrait complet de la surface Capacites de la fiche agent et suppression d'AgentPluginCapabilities.tsx; PermissionsPanel reserve aux permissions systeme/sandbox, onglet MCP retire; raccourci Parametres > Plugins ouvre Skills avec renvois vers Skills/MCP; integration ProjectsView/ViewPanelBody/viewPlacement/WebWorkspace/webSurfaceCatalog; QA verte: tsc+vite build OK, 28+24 tests cibles OK, suite complete 1223 OK / 32 echecs sur 6 fichiers web hors perimetre classes non bloquants; scripts/ et sync tickets #296 hors perimetre; aucun push)
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Ticket #82 — the "Tools MCP IdeA" tab of the project `Permissions` panel.
|
||||
* Ticket #82/#297 — the dedicated project `MCP` panel.
|
||||
*
|
||||
* Pins the UX contract from carnet #82 (Conception UX/F): an agent without an
|
||||
* override shows it inherits the project default with non-editable controls
|
||||
@ -14,11 +14,12 @@ import { fireEvent, render, screen, waitFor, within } from "@testing-library/rea
|
||||
import {
|
||||
MockAgentGateway,
|
||||
MockPermissionGateway,
|
||||
MockPluginGateway,
|
||||
MockProfileGateway,
|
||||
} from "@/adapters/mock";
|
||||
import { DIProvider } from "@/app/di";
|
||||
import type { Gateways } from "@/ports";
|
||||
import { PermissionsPanel } from "./PermissionsPanel";
|
||||
import { McpPanel } from "./McpPanel";
|
||||
|
||||
const PROJECT_ID = "proj-mcp-permissions-test";
|
||||
|
||||
@ -32,12 +33,13 @@ async function renderPanel() {
|
||||
const gateways = {
|
||||
agent,
|
||||
permission,
|
||||
plugin: new MockPluginGateway(),
|
||||
profile: new MockProfileGateway(),
|
||||
} as unknown as Gateways;
|
||||
|
||||
render(
|
||||
<DIProvider gateways={gateways}>
|
||||
<PermissionsPanel projectId={PROJECT_ID} />
|
||||
<McpPanel projectId={PROJECT_ID} />
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
@ -48,9 +50,7 @@ async function renderPanel() {
|
||||
return { agent, permission, agentId: created.id };
|
||||
}
|
||||
|
||||
/** Switches to the "Tools MCP IdeA" tab and waits past the doc load. */
|
||||
async function openMcpToolsTab() {
|
||||
fireEvent.click(screen.getByRole("tab", { name: "Tools MCP IdeA" }));
|
||||
await screen.findByRole("navigation", { name: "cibles des permissions MCP" });
|
||||
}
|
||||
|
||||
@ -58,20 +58,16 @@ async function selectAgentTarget(name: string) {
|
||||
const nav = screen.getByRole("navigation", { name: "cibles des permissions MCP" });
|
||||
fireEvent.click(within(nav).getByRole("button", { name: new RegExp(name) }));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole("heading", { name: `Tools MCP IdeA — ${name}` })).toBeTruthy();
|
||||
expect(screen.getByRole("heading", { name: `MCP IdeA — ${name}` })).toBeTruthy();
|
||||
});
|
||||
}
|
||||
|
||||
describe("PermissionsPanel — Tools MCP IdeA tab", () => {
|
||||
it("has an accessible tablist and defaults to Système", async () => {
|
||||
describe("McpPanel", () => {
|
||||
it("is exposed as a dedicated surface", async () => {
|
||||
await renderPanel();
|
||||
|
||||
const tablist = screen.getByRole("tablist", { name: "Permissions" });
|
||||
const tabs = within(tablist).getAllByRole("tab");
|
||||
expect(tabs.map((t) => t.textContent)).toEqual(["Système", "Tools MCP IdeA"]);
|
||||
expect(screen.getByRole("tab", { name: "Système" }).getAttribute("aria-selected")).toBe(
|
||||
"true",
|
||||
);
|
||||
await openMcpToolsTab();
|
||||
expect(screen.getByRole("heading", { name: "MCP" })).toBeTruthy();
|
||||
expect(screen.queryByRole("tablist", { name: "Permissions" })).toBeNull();
|
||||
});
|
||||
|
||||
it("an agent without an override shows it inherits the project default, read-only", async () => {
|
||||
@ -131,11 +127,12 @@ describe("PermissionsPanel — Tools MCP IdeA tab", () => {
|
||||
const gateways = {
|
||||
agent,
|
||||
permission,
|
||||
plugin: new MockPluginGateway(),
|
||||
profile: new MockProfileGateway(),
|
||||
} as unknown as Gateways;
|
||||
render(
|
||||
<DIProvider gateways={gateways}>
|
||||
<PermissionsPanel projectId={PROJECT_ID} />
|
||||
<McpPanel projectId={PROJECT_ID} />
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
@ -262,7 +259,7 @@ describe("PermissionsPanel — Tools MCP IdeA tab", () => {
|
||||
expect(window.confirm).toHaveBeenCalled();
|
||||
// Still on the agent editor, with the unsaved edit intact.
|
||||
expect(
|
||||
screen.getByRole("heading", { name: "Tools MCP IdeA — DevFrontend" }),
|
||||
screen.getByRole("heading", { name: "MCP IdeA — DevFrontend" }),
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
(screen.getByRole("checkbox", { name: /idea_ticket_update_carnet$/ }) as HTMLInputElement)
|
||||
|
||||
Reference in New Issue
Block a user