feat(FN-3350): tokenize task detail danger/error styling
Fixes task detail modal danger/error styling by switching to token-based CSS variables for consistent theming across dark and light modes. Fusion-Task-Id: FN-3350
This commit is contained in:
@@ -324,7 +324,7 @@ describe("Column in-progress/in-review bulk actions", () => {
|
||||
expect(screen.getByRole("menuitem", { name: /Move All to Todo/i })).toBeTruthy();
|
||||
});
|
||||
|
||||
it.each(["in-progress", "in-review"] as const)("Stop All pauses only non-paused tasks in %s", async (column) => {
|
||||
it.each(["in-progress", "in-review"] as const)("Stop All pauses only manually-pausable tasks in %s", async (column) => {
|
||||
const user = userEvent.setup();
|
||||
const onPauseTask = vi.fn().mockResolvedValue({} as Task);
|
||||
|
||||
@@ -335,7 +335,8 @@ describe("Column in-progress/in-review bulk actions", () => {
|
||||
tasks={[
|
||||
{ ...makeTask("FN-001"), column, paused: false },
|
||||
{ ...makeTask("FN-002"), column, paused: true },
|
||||
{ ...makeTask("FN-003"), column, paused: false },
|
||||
{ ...makeTask("FN-003"), column, paused: false, assignedAgentId: "agent-1" },
|
||||
{ ...makeTask("FN-004"), column, paused: false },
|
||||
]}
|
||||
onPauseTask={onPauseTask}
|
||||
/>,
|
||||
@@ -348,7 +349,8 @@ describe("Column in-progress/in-review bulk actions", () => {
|
||||
expect(onPauseTask).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
expect(onPauseTask).toHaveBeenCalledWith("FN-001");
|
||||
expect(onPauseTask).toHaveBeenCalledWith("FN-003");
|
||||
expect(onPauseTask).toHaveBeenCalledWith("FN-004");
|
||||
expect(onPauseTask).not.toHaveBeenCalledWith("FN-003");
|
||||
expect(screen.queryByRole("menu")).toBeNull();
|
||||
expect(mockConfirm).toHaveBeenCalledWith({
|
||||
title: "Stop All Tasks",
|
||||
@@ -374,7 +376,7 @@ describe("Column in-progress/in-review bulk actions", () => {
|
||||
expect(screen.getByText("No tasks in this column")).toBeTruthy();
|
||||
});
|
||||
|
||||
it.each(["in-progress", "in-review"] as const)("disables Stop All when all %s tasks are already paused", async (column) => {
|
||||
it.each(["in-progress", "in-review"] as const)("disables Stop All when no %s tasks are manually pausable", async (column) => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(
|
||||
@@ -383,7 +385,7 @@ describe("Column in-progress/in-review bulk actions", () => {
|
||||
column={column}
|
||||
tasks={[
|
||||
{ ...makeTask("FN-010"), column, paused: true },
|
||||
{ ...makeTask("FN-011"), column, paused: true },
|
||||
{ ...makeTask("FN-011"), column, paused: false, assignedAgentId: "agent-1" },
|
||||
]}
|
||||
onPauseTask={vi.fn().mockResolvedValue({} as Task)}
|
||||
/>,
|
||||
@@ -391,7 +393,7 @@ describe("Column in-progress/in-review bulk actions", () => {
|
||||
|
||||
await user.click(screen.getByRole("button", { name: `${column === "in-progress" ? "In Progress" : "In Review"} column actions` }));
|
||||
expect(screen.getByRole("menuitem", { name: /Stop All/i })).toBeDisabled();
|
||||
expect(screen.getByText("All tasks are already paused")).toBeTruthy();
|
||||
expect(screen.getByText("No manually pausable tasks")).toBeTruthy();
|
||||
});
|
||||
|
||||
it.each(["in-progress", "in-review"] as const)("Move All to Todo moves every task in %s", async (column) => {
|
||||
|
||||
@@ -210,6 +210,26 @@ describe("ListView", () => {
|
||||
expect(standardRow.querySelector(".list-execution-mode-badge")).toBeNull();
|
||||
});
|
||||
|
||||
it("shows paused by agent status in table view", () => {
|
||||
const tasks = [
|
||||
createMockTask({ id: "FN-001", column: "in-progress", paused: true, pausedByAgentId: "agent-1" }),
|
||||
];
|
||||
|
||||
renderListView({ tasks });
|
||||
expect(screen.getByText("paused by agent")).toBeDefined();
|
||||
});
|
||||
|
||||
it("shows paused by agent status in mobile card view", () => {
|
||||
const matchMediaSpy = mockMobileViewport();
|
||||
const tasks = [
|
||||
createMockTask({ id: "FN-001", column: "in-progress", paused: true, pausedByAgentId: "agent-1" }),
|
||||
];
|
||||
|
||||
renderListView({ tasks });
|
||||
expect(screen.getByText("paused by agent")).toBeDefined();
|
||||
matchMediaSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("shows empty state when no tasks", () => {
|
||||
renderListView({ tasks: [] });
|
||||
expect(screen.getByText("No tasks yet")).toBeDefined();
|
||||
|
||||
@@ -93,6 +93,23 @@ describe("TaskCard", () => {
|
||||
expect(container.querySelector(".card-status-badge")).toBeNull();
|
||||
});
|
||||
|
||||
it("shows paused by agent label when pausedByAgentId is set", () => {
|
||||
render(
|
||||
<TaskCard task={makeTask({ paused: true, pausedByAgentId: "agent-1" })} onOpenDetail={noop} addToast={noop} />,
|
||||
);
|
||||
|
||||
expect(screen.getByText("paused by agent")).toBeDefined();
|
||||
});
|
||||
|
||||
it("shows plain paused label when pausedByAgentId is not set", () => {
|
||||
render(
|
||||
<TaskCard task={makeTask({ paused: true })} onOpenDetail={noop} addToast={noop} />,
|
||||
);
|
||||
|
||||
expect(screen.getByText("paused")).toBeDefined();
|
||||
expect(screen.queryByText("paused by agent")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders fast-mode indicator only when executionMode is fast", () => {
|
||||
const { container, rerender } = render(
|
||||
<TaskCard task={makeTask({ executionMode: "fast" })} onOpenDetail={noop} addToast={noop} />,
|
||||
|
||||
@@ -4090,6 +4090,49 @@ describe("TaskDetailModal", () => {
|
||||
expect(screen.getByRole("menuitem", { name: "Unpause" })).toBeTruthy();
|
||||
});
|
||||
|
||||
it("hides Pause/Unpause button for agent-assigned tasks", async () => {
|
||||
const { fetchAgent } = await import("../../api");
|
||||
vi.mocked(fetchAgent).mockResolvedValue({ id: "agent-1", name: "Agent 1", role: "executor", state: "active" } as any);
|
||||
|
||||
render(
|
||||
<TaskDetailModal
|
||||
task={makeTask({ column: "triage", paused: true, assignedAgentId: "agent-1" })}
|
||||
onClose={noop}
|
||||
onMoveTask={noopMove}
|
||||
onDeleteTask={noopDelete}
|
||||
onMergeTask={noopMerge}
|
||||
onOpenDetail={noopOpenDetail}
|
||||
addToast={noop}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: /actions/i }));
|
||||
|
||||
expect(screen.queryByRole("menuitem", { name: "Pause" })).toBeNull();
|
||||
expect(screen.queryByRole("menuitem", { name: "Unpause" })).toBeNull();
|
||||
});
|
||||
|
||||
it("shows paused-by-agent indicator for agent-paused tasks", async () => {
|
||||
const { fetchAgent } = await import("../../api");
|
||||
vi.mocked(fetchAgent).mockResolvedValue({ id: "agent-1", name: "Agent 1", role: "executor", state: "paused" } as any);
|
||||
|
||||
render(
|
||||
<TaskDetailModal
|
||||
task={makeTask({ column: "triage", paused: true, assignedAgentId: "agent-1", pausedByAgentId: "agent-1" })}
|
||||
onClose={noop}
|
||||
onMoveTask={noopMove}
|
||||
onDeleteTask={noopDelete}
|
||||
onMergeTask={noopMerge}
|
||||
onOpenDetail={noopOpenDetail}
|
||||
addToast={noop}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: /actions/i }));
|
||||
|
||||
expect(screen.getByText("Paused by agent")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("does NOT render Actions dropdown for a non-paused, non-awaiting-approval, non-retryable triage task", () => {
|
||||
render(
|
||||
<TaskDetailModal
|
||||
|
||||
Reference in New Issue
Block a user