FN-6038: swap workflow toolbar edit and create buttons

Swap the workflow toolbar actions so editing appears before creation.

- move the workflow editor pencil button ahead of the new workflow plus button in the board toolbar
- add assertions covering the full toolbar order when both actions are present
- add coverage for cases where only one workflow toolbar action is available

Files changed:
 packages/dashboard/app/components/Board.tsx                     | 22 +++++++--------
 packages/dashboard/app/components/__tests__/Board.test.tsx     | 33 ++++++++++++++++++++++
 2 files changed, 44 insertions(+), 11 deletions(-)

Fusion-Task-Id: FN-6038

Fusion-Task-Lineage: 4fb28d7c-3261-4d45-9363-2b340e4aea35
This commit is contained in:
gsxdsm
2026-06-08 14:31:55 -07:00
parent 1d0921e069
commit 558720b4e5
2 changed files with 44 additions and 11 deletions

View File

@@ -456,17 +456,6 @@ export function Board({ tasks, projectId, maxConcurrent, onMoveTask, onPauseTask
</select>
</label>
)}
{onCreateWorkflow && (
<button
type="button"
className="btn btn-icon btn-sm board-workflow-create-btn"
onClick={onCreateWorkflow}
title="New workflow"
aria-label="New workflow"
>
<Plus size={15} />
</button>
)}
{onOpenWorkflowEditor && (
<button
type="button"
@@ -478,6 +467,17 @@ export function Board({ tasks, projectId, maxConcurrent, onMoveTask, onPauseTask
<Pencil size={15} />
</button>
)}
{onCreateWorkflow && (
<button
type="button"
className="btn btn-icon btn-sm board-workflow-create-btn"
onClick={onCreateWorkflow}
title="New workflow"
aria-label="New workflow"
>
<Plus size={15} />
</button>
)}
</div>
)}
<main

View File

@@ -921,6 +921,12 @@ describe("Board", () => {
});
}
function workflowToolbarActionNames() {
const toolbar = document.querySelector(".board-workflow-toolbar");
expect(toolbar).not.toBeNull();
return Array.from(toolbar?.querySelectorAll("button") ?? []).map((button) => button.getAttribute("aria-label"));
}
it("flag OFF renders the legacy single-lane board byte-identically", async () => {
fetchBoardWorkflowsMock.mockResolvedValue({
flagEnabled: false,
@@ -1000,6 +1006,7 @@ describe("Board", () => {
await waitFor(() => expect(screen.getByTestId("column-triage")).toBeDefined());
expect(screen.queryByLabelText("Select workflow")).toBeNull();
expect(workflowToolbarActionNames()).toEqual(["Edit workflows", "New workflow"]);
fireEvent.click(screen.getByRole("button", { name: "New workflow" }));
fireEvent.click(screen.getByRole("button", { name: "Edit workflows" }));
@@ -1007,8 +1014,30 @@ describe("Board", () => {
expect(onOpenWorkflowEditor).toHaveBeenCalledTimes(1);
});
it("preserves workflow toolbar partial action visibility", async () => {
const onCreateWorkflow = vi.fn();
enableFlag({}, [DEFAULT_WORKFLOW]);
const { unmount } = renderBoard({ onCreateWorkflow });
await waitFor(() => expect(screen.getByTestId("column-triage")).toBeDefined());
expect(workflowToolbarActionNames()).toEqual(["New workflow"]);
fireEvent.click(screen.getByRole("button", { name: "New workflow" }));
expect(onCreateWorkflow).toHaveBeenCalledTimes(1);
unmount();
const onOpenWorkflowEditor = vi.fn();
enableFlag({}, [DEFAULT_WORKFLOW]);
renderBoard({ onOpenWorkflowEditor });
await waitFor(() => expect(screen.getByTestId("column-triage")).toBeDefined());
expect(workflowToolbarActionNames()).toEqual(["Edit workflows"]);
fireEvent.click(screen.getByRole("button", { name: "Edit workflows" }));
expect(onOpenWorkflowEditor).toHaveBeenCalledTimes(1);
});
it("renders one selected workflow at a time and switches workflows from the dropdown", async () => {
const onCreateWorkflow = vi.fn();
const onOpenWorkflowEditor = vi.fn();
enableFlag(
{ "FN-1": "builtin:coding", "FN-2": "wf-custom", "FN-3": "wf-custom" },
[DEFAULT_WORKFLOW, CUSTOM_WORKFLOW],
@@ -1020,11 +1049,15 @@ describe("Board", () => {
mkTask({ id: "FN-3", column: "intake" }),
],
onCreateWorkflow,
onOpenWorkflowEditor,
});
const selector = await screen.findByLabelText("Select workflow") as HTMLSelectElement;
expect(selector.value).toBe("builtin:coding");
expect(workflowToolbarActionNames()).toEqual(["Edit workflows", "New workflow"]);
fireEvent.click(screen.getByRole("button", { name: "New workflow" }));
fireEvent.click(screen.getByRole("button", { name: "Edit workflows" }));
expect(onCreateWorkflow).toHaveBeenCalledTimes(1);
expect(onOpenWorkflowEditor).toHaveBeenCalledTimes(1);
expect(JSON.parse(screen.getByTestId("column-todo").getAttribute("data-tasks") || "[]").map((task: Task) => task.id)).toEqual(["FN-1"]);
expect(screen.queryByTestId("column-intake")).toBeNull();