insta-toc
Version:
Simultaneously generate, update, and maintain a table of contents for your notes in real time.
129 lines (104 loc) • 5.16 kB
text/typescript
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import type { FileKey, FoldKey } from "../src/types";
import { createUiStateManagerMock } from "./mocks/pluginClassMocks";
describe("UiStateManager", () => {
const persistedUiStateSaveDelayMs = 500;
beforeEach(() => {
vi.useFakeTimers();
vi.stubGlobal("app", { plugins: { getPlugin: vi.fn(() => ({ settings: { updateDelay: 1000 } })) } });
});
afterEach(() => {
vi.restoreAllMocks();
vi.unstubAllGlobals();
vi.useRealTimers();
});
test("returns cloned persisted ui state snapshots", () => {
// Arrange
const foldKey: FoldKey = "note.md::1";
const fileKey: FileKey = "note.md";
const { uiStateManager } = createUiStateManagerMock({
tocBlockCollapseState: { [fileKey]: true },
tocFoldState: { [foldKey]: true }
});
// Act
const snapshot = uiStateManager.getPersistedUiState();
snapshot.tocFoldState.set(foldKey, false);
snapshot.tocBlockCollapseState.set(fileKey, false);
// Assert
expect(uiStateManager.getTocFoldState(foldKey)).toBe(true);
expect(uiStateManager.getTocBlockCollapsed(fileKey)).toBe(true);
});
test("persists fold state changes only when the value changes", () => {
// Arrange
const foldKey: FoldKey = "note.md::1";
const { savePersistedDataSpy, uiStateManager } = createUiStateManagerMock();
// Act
uiStateManager.setTocFoldState(foldKey, true);
uiStateManager.setTocFoldState(foldKey, true);
// Assert
expect(uiStateManager.getTocFoldState(foldKey)).toBe(true);
expect(savePersistedDataSpy).not.toHaveBeenCalled();
});
test("batches rapid fold state updates into a single debounced save", async () => {
// Arrange
const { savePersistedDataSpy, uiStateManager } = createUiStateManagerMock();
// Act
uiStateManager.setTocFoldState("note.md::1", true);
uiStateManager.setTocFoldState("note.md::2", true);
await vi.advanceTimersByTimeAsync(persistedUiStateSaveDelayMs);
// Assert
expect(savePersistedDataSpy).toHaveBeenCalledTimes(1);
});
test("persists block collapse changes only when the value changes", () => {
// Arrange
const fileKey = "note.md" as FileKey;
const { savePersistedDataSpy, uiStateManager } = createUiStateManagerMock();
// Act
uiStateManager.setTocBlockCollapsed(fileKey, true);
uiStateManager.setTocBlockCollapsed(fileKey, true);
// Assert
expect(uiStateManager.getTocBlockCollapsed(fileKey)).toBe(true);
expect(savePersistedDataSpy).not.toHaveBeenCalled();
});
test("flushPersistedData saves immediately and cancels a pending debounce", async () => {
// Arrange
const foldKey: FoldKey = "note.md::1";
const { savePersistedDataSpy, uiStateManager } = createUiStateManagerMock();
// Act
uiStateManager.setTocFoldState(foldKey, true);
await uiStateManager.flushPersistedData();
await vi.runAllTimersAsync();
// Assert
expect(savePersistedDataSpy).toHaveBeenCalledTimes(1);
});
test("prunes inactive fold keys for a file path and keeps active modern keys", async () => {
// Arrange
const activeFoldKey: FoldKey = "note.md::2";
const { savePersistedDataSpy, uiStateManager } = createUiStateManagerMock({
tocFoldState: new Map([ [ "note.md::1", true ], [ activeFoldKey, false ], [ "other.md::1", true ] ])
});
// Act
uiStateManager.pruneTocFoldStateForPath("note.md", { activeModernFoldKeys: new Set([ activeFoldKey ]) });
// Assert
expect(uiStateManager.getTocFoldState("note.md::1" as FoldKey)).toBeUndefined();
expect(uiStateManager.getTocFoldState(activeFoldKey)).toBe(false);
expect(uiStateManager.getTocFoldState("other.md::1" as FoldKey)).toBe(true);
await vi.advanceTimersByTimeAsync(persistedUiStateSaveDelayMs);
expect(savePersistedDataSpy).toHaveBeenCalledTimes(1);
});
test("moves fold state to the replacement file on rename", async () => {
// Arrange
const { savePersistedDataSpy, uiStateManager } = createUiStateManagerMock({
tocFoldState: new Map([ [ "old-note.md::1", true ], [ "old-note.md::2", false ] ])
});
// Act
uiStateManager.pruneTocFoldStateForPath("old-note.md", { replacementFile: "new-note.md" });
// Assert
expect(uiStateManager.getTocFoldState("old-note.md::1" as FoldKey)).toBeUndefined();
expect(uiStateManager.getTocFoldState("old-note.md::2" as FoldKey)).toBeUndefined();
expect(uiStateManager.getTocFoldState("new-note.md::1" as FoldKey)).toBe(true);
expect(uiStateManager.getTocFoldState("new-note.md::2" as FoldKey)).toBe(false);
await vi.advanceTimersByTimeAsync(persistedUiStateSaveDelayMs);
expect(savePersistedDataSpy).toHaveBeenCalledTimes(1);
});
});