feat(FN-2299): add explicit View Details action for agent list cards

- Add a dedicated "View Details" button to each agent list card while preserving clickable identity behavior
- Style list card actions so lifecycle controls and the new details action align cleanly across desktop and mobile layouts
- Expand AgentsView coverage to verify button rendering, correct detail-target opening, and backward-compatible identity click behavior
- Stabilize MissionManager activity pagination test timing and document the new list-view details action in the dashboard README
This commit is contained in:
Fusion
2026-04-23 14:16:19 -07:00
committed by gsxdsm
parent f12ec7189b
commit 88bc4e7759
5 changed files with 59 additions and 2 deletions

View File

@@ -1216,6 +1216,14 @@ export function AgentsView({ addToast, projectId }: AgentsViewProps) {
</button>
</>
)}
<button
className="btn btn--sm agent-card-details-btn"
onClick={() => setSelectedAgentId(agent.id)}
title={`View details for ${agent.name}`}
aria-label={`View details for ${agent.name}`}
>
View Details
</button>
</div>
</div>
);

View File

@@ -189,6 +189,45 @@ describe("AgentsView", () => {
});
});
it("renders explicit View Details button on list cards", async () => {
render(<AgentsView addToast={mockAddToast} />);
await waitFor(() => {
expect(screen.getByRole("button", { name: "View details for Test Agent 1" })).toBeTruthy();
expect(screen.getByRole("button", { name: "View details for Test Agent 2" })).toBeTruthy();
});
expect(screen.getAllByText("View Details").length).toBeGreaterThanOrEqual(4);
});
it("opens matching detail view when clicking View Details button", async () => {
render(<AgentsView addToast={mockAddToast} />);
await waitFor(() => {
expect(screen.getByRole("button", { name: "View details for Test Agent 3" })).toBeTruthy();
});
fireEvent.click(screen.getByRole("button", { name: "View details for Test Agent 3" }));
await waitFor(() => {
expect(screen.getByTestId("agent-detail-view")).toHaveTextContent("agent-003");
});
});
it("keeps clickable identity area behavior for opening detail view", async () => {
render(<AgentsView addToast={mockAddToast} />);
const agentName = await screen.findByText("Test Agent 1");
const clickableIdentity = agentName.closest(".agent-info--clickable") as HTMLElement | null;
expect(clickableIdentity).toBeTruthy();
fireEvent.click(clickableIdentity!);
await waitFor(() => {
expect(screen.getByTestId("agent-detail-view")).toHaveTextContent("agent-001");
});
});
it("shows heartbeat interval control on agent cards with 5m minimum presets", async () => {
render(<AgentsView addToast={mockAddToast} />);

View File

@@ -954,7 +954,7 @@ describe("MissionManager", () => {
expect(screen.getByText("Mission event 65")).toBeDefined();
expect(screen.queryByTestId("mission-activity-load-more")).toBeNull();
}, { timeout: 5000 });
});
}, 15000);
it("auto-scrolls to latest mission activity on initial load", async () => {
globalThis.fetch = createDetailFetchMock(mockMissionEvents);