feat(FN-3065): merge fusion/fn-3065

This merge lands v0.14.0, bringing task ingest contract documentation and todo creation wiring (FN-3065), a new Global → General settings pane with `fn --version` integration, and a fix for persisting priority changes from PATCH /tasks/:id. All changeset artifacts were consumed by the release; 53 fi

Fusion-Task-Id: FN-3065
This commit is contained in:
Fusion
2026-05-01 16:39:03 -07:00
committed by gsxdsm
parent 8c8c7f5e4f
commit 92d7c7bbb8
5 changed files with 24 additions and 8 deletions

View File

@@ -440,8 +440,9 @@ describe("TodoView", () => {
});
it("clicking Create Task button calls createTask with item text", async () => {
const onTaskCreated = vi.fn();
mockCreateTask.mockResolvedValueOnce({ id: "FN-123" });
render(<TodoView addToast={addToast} projectId="project-1" />);
render(<TodoView addToast={addToast} projectId="project-1" onTaskCreated={onTaskCreated} />);
fireEvent.click(screen.getByTestId("create-task-from-item-1"));
@@ -451,6 +452,7 @@ describe("TodoView", () => {
"project-1",
);
});
expect(onTaskCreated).toHaveBeenCalledWith({ id: "FN-123" });
expect(addToast).toHaveBeenCalledWith("Created FN-123 from todo", "success");
});
@@ -467,8 +469,9 @@ describe("TodoView", () => {
});
it("selecting an agent creates task assigned to that agent", async () => {
const onTaskCreated = vi.fn();
mockCreateTask.mockResolvedValueOnce({ id: "FN-234" });
render(<TodoView addToast={addToast} projectId="project-1" />);
render(<TodoView addToast={addToast} projectId="project-1" onTaskCreated={onTaskCreated} />);
fireEvent.click(screen.getByTestId("assign-agent-for-item-1"));
@@ -481,6 +484,7 @@ describe("TodoView", () => {
"project-1",
);
});
expect(onTaskCreated).toHaveBeenCalledWith({ id: "FN-234" });
expect(addToast).toHaveBeenCalledWith("Created FN-234 and assigned to Builder", "success");
});
@@ -524,13 +528,15 @@ describe("TodoView", () => {
});
it("error handling shows error toast", async () => {
const onTaskCreated = vi.fn();
mockCreateTask.mockRejectedValueOnce(new Error("boom"));
render(<TodoView addToast={addToast} />);
render(<TodoView addToast={addToast} onTaskCreated={onTaskCreated} />);
fireEvent.click(screen.getByTestId("create-task-from-item-1"));
await waitFor(() => {
expect(addToast).toHaveBeenCalledWith("Failed to create task: boom", "error");
});
expect(onTaskCreated).not.toHaveBeenCalled();
});
});

View File

@@ -264,9 +264,9 @@ describe("SettingsModal mobile adaptations", () => {
const { container, getByText, getAllByText } = render(<SettingsModal onClose={vi.fn()} addToast={vi.fn()} />);
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
// Authentication is first with no scope banner by default - click General to see project scope
// Authentication is first with no scope banner by default - click the Project-scoped General section
expect(container.querySelectorAll(".settings-scope-icon").length).toBeGreaterThan(0);
await user.click(getAllByText("General")[0]);
await user.click(getAllByText("General")[1]);
// Verify project scope banner contains icon elements (SVG from Lucide, not emoji)
const projectBanner = container.querySelector(".settings-scope-project");