Files
fusion/packages/dashboard/app/hooks/__tests__/usePoppedOutTasks.test.ts
gsxdsm 7246df22f6 FN-7944: add setting to keep task popups attached to their Board/List view
Adds an opt-in project setting so open task-detail popups stay attached to the Board or List view where they were opened, instead of floating over every main-content view.

- New project setting taskPopupsBoardListOnly (default: off) in settings-schema.ts and ProjectSettings type, with default preserved via settings-defaults tests.
- usePoppedOutTasks now stores each popup's originating TaskView alongside its task snapshot (PoppedOutTaskEntry), keeping legacy tasks output for existing callers.
- App.tsx adds isTaskPopupVisibleForView() gating helper and filters popped-out entries to the current view for rendering/keyboard-close handling, while hidden popups remain mounted in hook state (not cleared) so switching back to the originating view restores them with shared persisted geometry.
- Settings -> Appearance gets a new "Keep task popups on their Board/List view" checkbox (AppearanceSection.tsx) with i18n strings and updated settings search text in SettingsModal.
- Documentation updated in docs/dashboard-guide.md and docs/settings-reference.md to describe the render-only hide/restore behavior.
- New/updated tests: App.taskPopupViewGating.test.tsx, usePoppedOutTasks.test.ts, AppearanceSection.test.tsx, settings-default-descriptions.test.tsx, settings-defaults.test.ts.

Files changed:
 docs/dashboard-guide.md                            |   5 +-
 docs/settings-reference.md                         |   1 +
 .../core/src/__tests__/settings-defaults.test.ts   |  13 +++
 packages/core/src/settings-schema.ts               |   5 +
 packages/core/src/types.ts                         |   7 ++
 packages/dashboard/app/App.tsx                     |  49 +++++++--
 .../app/__tests__/App.taskPopupViewGating.test.tsx | 113 +++++++++++++++++++++
 .../dashboard/app/components/SettingsModal.tsx     |   3 +-
 .../settings/sections/AppearanceSection.tsx        |   8 ++
 .../sections/__tests__/AppearanceSection.test.tsx  |  21 ++++
 .../settings-default-descriptions.test.tsx         |   1 +
 .../app/hooks/__tests__/usePoppedOutTasks.test.ts  |  14 +++
 packages/dashboard/app/hooks/useAppSettings.ts     |   4 +
 packages/dashboard/app/hooks/usePoppedOutTasks.ts  |  27 +++--
 packages/i18n/locales/en/app.json                  |   2 +
 15 files changed, 255 insertions(+), 18 deletions(-)

Fusion-Task-Id: FN-7944
Fusion-Task-Lineage: 4b8ced0e-1853-429f-8482-163821a35ae6
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-13 08:58:51 -07:00

46 lines
1.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { renderHook, act } from "@testing-library/react";
import { usePoppedOutTasks } from "../usePoppedOutTasks";
const task = (id: string) => ({ id, title: id, status: "todo" } as never);
describe("usePoppedOutTasks", () => {
it("popOut adds a task and dedupes by id", () => {
const { result } = renderHook(() => usePoppedOutTasks());
act(() => {
result.current.popOut(task("1"));
result.current.popOut(task("1"));
result.current.popOut(task("2"));
});
expect(result.current.tasks.map((t) => t.id)).toEqual(["1", "2"]);
});
it("records the originating task view for view-attached popups", () => {
const { result } = renderHook(() => usePoppedOutTasks());
act(() => {
result.current.popOut(task("1"), "board");
result.current.popOut(task("2"), "list");
});
expect(result.current.entries.map((entry) => [entry.task.id, entry.originTaskView])).toEqual([
["1", "board"],
["2", "list"],
]);
});
it("close removes only the matching id", () => {
const { result } = renderHook(() => usePoppedOutTasks());
act(() => {
result.current.popOut(task("1"));
result.current.popOut(task("2"));
result.current.close("1");
});
expect(result.current.tasks.map((t) => t.id)).toEqual(["2"]);
});
});