Files
fusion/packages/dashboard/app/hooks/__tests__/useAutoSavePreference.test.ts
gsxdsm 06ec0e606e FN-7866: add auto-save toggle for the workspace file editor (default on)
Adds a shared, persisted auto-save preference for workspace text-file editing, defaulted to on, surfaced as a toolbar toggle in both the Files modal and right-dock Files view.

- Add useAutoSavePreference hook: persists the fn-file-editor-auto-save localStorage preference, broadcasts same-window changes via a custom event (storage events only reach other documents), and defaults to true.
- Extend useWorkspaceFileEditor with an autoSave flag that debounces (800ms) and triggers save() for a loaded, editable file with real pending changes, keyed by workspace+file+content to avoid re-firing on failed writes.
- Add an Auto-save toggle button to FileEditor's toolbar (autoSaveEnabled/onToggleAutoSave/canToggleAutoSave props), hidden for read-only/preview/binary files.
- Wire the shared preference into FileBrowserModal and DockFilesView, disabling auto-save for binary files in the modal.
- Add fileEditor.autoSave / fileEditor.toggleAutoSave i18n strings and document the new default behavior in docs/dashboard-guide.md.
- Add/extend tests covering the new hook, debounced auto-save behavior, and toolbar toggle wiring across FileEditor, FileBrowserModal, and DockFilesView.

Files changed:
 docs/dashboard-guide.md                            |   3 +
 .../dashboard/app/components/DockFilesView.tsx     |   6 +-
 .../dashboard/app/components/FileBrowserModal.tsx  |  20 ++--
 packages/dashboard/app/components/FileEditor.tsx   |  17 +++-
 .../components/__tests__/DockFilesView.test.tsx    |  37 ++++++-
 .../components/__tests__/FileBrowserModal.test.tsx |  86 +++++++++++++---
 .../app/components/__tests__/FileEditor.test.tsx   |  56 +++++++++++
 .../hooks/__tests__/useAutoSavePreference.test.ts  |  66 +++++++++++++
 .../hooks/__tests__/useWorkspaceFileEditor.test.ts | 108 +++++++++++++++++++++
 .../dashboard/app/hooks/useAutoSavePreference.ts   |  79 +++++++++++++++
 .../dashboard/app/hooks/useWorkspaceFileEditor.ts  |  47 ++++++++-
 packages/i18n/locales/en/app.json                  |   2 +
 12 files changed, 500 insertions(+), 27 deletions(-)

Fusion-Task-Id: FN-7866

Fusion-Task-Lineage: 0604de18-666d-4872-abce-2a3886c9ea55

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 12:49:37 -07:00

67 lines
2.4 KiB
TypeScript

import { act, renderHook } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { FILE_EDITOR_AUTO_SAVE_STORAGE_KEY, useAutoSavePreference } from "../useAutoSavePreference";
describe("useAutoSavePreference", () => {
beforeEach(() => {
vi.restoreAllMocks();
window.localStorage.clear();
});
it("defaults to enabled when no preference is stored", () => {
const { result } = renderHook(() => useAutoSavePreference());
expect(result.current.autoSaveEnabled).toBe(true);
});
it("reads a stored false preference", () => {
window.localStorage.setItem(FILE_EDITOR_AUTO_SAVE_STORAGE_KEY, "false");
const { result } = renderHook(() => useAutoSavePreference());
expect(result.current.autoSaveEnabled).toBe(false);
});
it("toggles and persists the preference", () => {
const { result } = renderHook(() => useAutoSavePreference());
act(() => result.current.toggleAutoSave());
expect(result.current.autoSaveEnabled).toBe(false);
expect(window.localStorage.getItem(FILE_EDITOR_AUTO_SAVE_STORAGE_KEY)).toBe("false");
});
it("sets and persists an explicit preference", () => {
const { result } = renderHook(() => useAutoSavePreference());
act(() => result.current.setAutoSaveEnabled(false));
expect(result.current.autoSaveEnabled).toBe(false);
expect(window.localStorage.getItem(FILE_EDITOR_AUTO_SAVE_STORAGE_KEY)).toBe("false");
act(() => result.current.setAutoSaveEnabled(true));
expect(result.current.autoSaveEnabled).toBe(true);
expect(window.localStorage.getItem(FILE_EDITOR_AUTO_SAVE_STORAGE_KEY)).toBe("true");
});
it("updates when another document changes storage", () => {
const { result } = renderHook(() => useAutoSavePreference());
act(() => {
window.localStorage.setItem(FILE_EDITOR_AUTO_SAVE_STORAGE_KEY, "false");
window.dispatchEvent(new StorageEvent("storage", { key: FILE_EDITOR_AUTO_SAVE_STORAGE_KEY, newValue: "false" }));
});
expect(result.current.autoSaveEnabled).toBe(false);
});
it("syncs multiple same-window editor instances", () => {
const first = renderHook(() => useAutoSavePreference());
const second = renderHook(() => useAutoSavePreference());
act(() => first.result.current.setAutoSaveEnabled(false));
expect(first.result.current.autoSaveEnabled).toBe(false);
expect(second.result.current.autoSaveEnabled).toBe(false);
});
});