fix(frontend): expose idea_ask_agents et renforce le fit terminal au remount projet
Panneau Permissions: idea_ask_agents est câblé côté backend MCP mais absent du groupe « Délégation agents » du panneau — ajout de l'outil et de son label, catalogue mock MCP aligné en conséquence. Terminaux: ProjectsView remonte LayoutGrid via une key au changement de projet, donc refitEpoch n'aide pas ; le montage de TerminalView ne maintenait pas assez longtemps le fit tant que la nouvelle cellule ne s'était pas stabilisée. Le chemin de montage garde désormais une traîne de refits plus longue (MOUNT_SETTLE_REFIT_FRAMES) avant de laisser la main au ResizeObserver. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -455,6 +455,52 @@ describe("TerminalView — visible launch-failure surface (ticket #14 F3)", () =
|
||||
fitSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("keeps fitting across a keyed project remount until the new cell settles", async () => {
|
||||
// ProjectsView keys LayoutGrid by project. A project switch therefore
|
||||
// unmounts/remounts TerminalView, so the mount path itself must keep a
|
||||
// short tail of fits alive while the new cell geometry settles.
|
||||
const fitSpy = vi.spyOn(FitAddon.prototype, "fit");
|
||||
const firstHandle = makeHandle({ sessionId: "project-1" });
|
||||
const secondHandle = makeHandle({ sessionId: "project-2" });
|
||||
const open = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce(firstHandle)
|
||||
.mockResolvedValueOnce(secondHandle);
|
||||
|
||||
function ProjectTerminal({ projectId }: { projectId: string }) {
|
||||
return (
|
||||
<DIProvider gateways={{ terminal: new MockTerminalGateway() } as unknown as Gateways}>
|
||||
<TerminalView
|
||||
key={projectId}
|
||||
cwd={`/cwd/${projectId}`}
|
||||
open={open}
|
||||
/>
|
||||
</DIProvider>
|
||||
);
|
||||
}
|
||||
|
||||
const { rerender } = render(<ProjectTerminal projectId="p1" />);
|
||||
await waitFor(() => expect(open).toHaveBeenCalledTimes(1));
|
||||
setTerminalBoxSize(400, 200);
|
||||
await waitFor(() => expect(firstHandle.resize).toHaveBeenCalled());
|
||||
|
||||
fitSpy.mockClear();
|
||||
rerender(<ProjectTerminal projectId="p2" />);
|
||||
await waitFor(() => expect(open).toHaveBeenCalledTimes(2));
|
||||
setTerminalBoxSize(520, 260);
|
||||
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
}
|
||||
|
||||
expect(fitSpy.mock.calls.length).toBeGreaterThan(5);
|
||||
await waitFor(() => expect(secondHandle.resize).toHaveBeenCalled());
|
||||
expect(firstHandle.close).not.toHaveBeenCalled();
|
||||
expect(secondHandle.close).not.toHaveBeenCalled();
|
||||
|
||||
fitSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("does not refit when refitSignal is left undefined (no-op for callers that don't pass it)", async () => {
|
||||
const fitSpy = vi.spyOn(FitAddon.prototype, "fit");
|
||||
const open = vi.fn(async () => makeHandle({ sessionId: "no-signal-1" }));
|
||||
|
||||
Reference in New Issue
Block a user