test(FN-4722): complete Step 7 — add goals navigation coverage

Fusion-Task-Id: FN-4722
Fusion-Task-Lineage: 51be7260-82f0-4ec9-a350-06778b8eb01b
This commit is contained in:
Fusion (runfusion.ai)
2026-05-16 06:25:15 -07:00
committed by gsxdsm
parent b3690a7402
commit d703fac103
5 changed files with 107 additions and 1 deletions

View File

@@ -1198,7 +1198,7 @@ export function Header({
<>
<button
ref={viewOverflowTriggerRef}
className={`view-toggle-btn${["research", "skills", "insights", "memory", "reliability", "dev-server", "devserver", "graph", "stash-recovery"].includes(view) || (experimentalFeatures?.evalsView && view === "evals") || (experimentalFeatures?.goalsView && view === "goalsView") || (todosEnabled && todosOpen) || isPluginViewId(view) ? " active" : ""}
className={`view-toggle-btn${["research", "skills", "insights", "memory", "reliability", "dev-server", "devserver", "graph", "stash-recovery"].includes(view) || (experimentalFeatures?.evalsView && view === "evals") || (experimentalFeatures?.goalsView && view === "goalsView") || (todosEnabled && todosOpen) || isPluginViewId(view) ? " active" : ""}`}
onClick={() => setIsViewOverflowOpen((prev) => !prev)}
title="More views"
aria-label="More views"

View File

@@ -370,6 +370,10 @@ vi.mock("../../components/TodoView", () => ({
),
}));
vi.mock("../../components/GoalsView", () => ({
GoalsView: () => <div data-testid="goals-view">Goals View</div>,
}));
vi.mock("../../components/ChatView", () => ({
ChatView: () => <FileBrowserProbe testId="fb-probe-chat" />,
}));
@@ -2583,6 +2587,42 @@ describe("App view switching", () => {
// Cleanup
localStorage.removeItem(taskViewStorageKey());
});
it("renders goals view when goalsView experimental feature is enabled", async () => {
localStorage.setItem(taskViewStorageKey(), "goalsView");
(fetchSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
...defaultSettings,
experimentalFeatures: { goalsView: true },
});
render(<App />);
await waitFor(() => {
expect(screen.getByTestId("goals-view")).toBeTruthy();
});
localStorage.removeItem(taskViewStorageKey());
});
it("redirects to board when goalsView experimental feature is disabled and taskView is goalsView", async () => {
localStorage.setItem(taskViewStorageKey(), "goalsView");
(fetchSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
...defaultSettings,
experimentalFeatures: { goalsView: false },
});
render(<App />);
await waitFor(() => {
expect(fetchSettings).toHaveBeenCalled();
});
await waitFor(() => {
expect(document.querySelector(".board")).toBeTruthy();
});
localStorage.removeItem(taskViewStorageKey());
});
});
describe("App GitHub import", () => {

View File

@@ -311,6 +311,27 @@ describe("Header", () => {
expect(onChangeView).toHaveBeenCalledWith("evals");
expect(screen.queryByTestId("view-overflow-evals")).toBeNull();
});
it("gates goals overflow entry and routes to goalsView when enabled", () => {
const hidden = renderHeader({ onChangeView: noop, experimentalFeatures: { goalsView: false, insights: true } });
fireEvent.click(screen.getByTestId("view-toggle-overflow-trigger"));
expect(screen.queryByTestId("view-overflow-goals")).toBeNull();
hidden.unmount();
const onChangeView = vi.fn();
renderHeader({ onChangeView, view: "goalsView", experimentalFeatures: { goalsView: true } });
const trigger = screen.getByTestId("view-toggle-overflow-trigger");
expect(trigger.className).toContain("active");
fireEvent.click(trigger);
const goalsItem = screen.getByTestId("view-overflow-goals");
expect(goalsItem.className).toContain("active");
fireEvent.click(goalsItem);
expect(onChangeView).toHaveBeenCalledWith("goalsView");
expect(screen.queryByTestId("view-overflow-goals")).toBeNull();
});
});
describe("terminal split button", () => {

View File

@@ -516,6 +516,31 @@ describe("MobileNavBar", () => {
expect(props.onChangeView).toHaveBeenCalledWith("evals");
});
it("gates goals item in more sheet, routes to goalsView, and marks More active on goals view", () => {
const hidden = render(<MobileNavBar {...createDefaultProps()} experimentalFeatures={{}} />);
fireEvent.click(screen.getByTestId("mobile-nav-tab-more"));
expect(screen.queryByTestId("mobile-more-item-goals")).toBeNull();
hidden.unmount();
const props = createDefaultProps();
const { container } = render(
<MobileNavBar
{...props}
view="goalsView"
experimentalFeatures={{ goalsView: true }}
/>,
);
const moreTab = screen.getByTestId("mobile-nav-tab-more");
expect(moreTab.className).toContain("mobile-nav-tab--active");
fireEvent.click(moreTab);
fireEvent.click(screen.getByTestId("mobile-more-item-goals"));
expect(container.querySelector(".mobile-more-sheet")).toBeNull();
expect(props.onChangeView).toHaveBeenCalledWith("goalsView");
});
it("activity log item in more sheet calls onOpenActivityLog", () => {
const props = createDefaultProps();
const { container } = render(<MobileNavBar {...props} />);

View File

@@ -225,4 +225,24 @@ describe("useAppSettings", () => {
expect(result.current.todosEnabled).toBe(true);
});
});
it("derives goalsEnabled from experimentalFeatures.goalsView", async () => {
mockFetchSettings.mockResolvedValueOnce({
autoMerge: false,
globalPause: false,
enginePaused: false,
prAuthAvailable: true,
taskStuckTimeoutMs: 600000,
showQuickChatFAB: false,
experimentalFeatures: {
goalsView: true,
},
} as never);
const { result } = renderHook(() => useAppSettings("proj_123"));
await waitFor(() => {
expect(result.current.goalsEnabled).toBe(true);
});
});
});