// @vitest-environment jsdom // // FilesProvider's arrival at one file: `openFile` (a notice's "Open") and a `?item=` link both make a // pending focus that the Files page spends once it has looked; what it found is held until the page // is left. Real storage with the tab's account pinned; only the navigation is mocked, its page // switchable. import { beforeEach, describe, expect, it, vi } from "vitest"; import { act, renderHook } from "@testing-library/react"; import type { ReactNode } from "react"; const nav = vi.hoisted(() => ({ page: "files", setPage: vi.fn() })); vi.mock("./navigationContext", () => ({ useNavigation: () => ({ page: nav.page }), useNavigationActions: () => ({ setPage: nav.setPage }), })); import { FilesProvider } from "./FilesProvider"; import { ALL_FILES, useFiles, useFilesActions } from "./filesContext"; const wrapper = ({ children }: { children: ReactNode }) => ( {children} ); const render = () => renderHook(() => ({ ...useFiles(), ...useFilesActions() }), { wrapper }); beforeEach(() => { localStorage.clear(); sessionStorage.setItem("siftlode.activeAccount", "1"); window.history.replaceState(null, "", "/"); nav.page = "files"; nav.setPage.mockClear(); }); describe("FilesProvider · arriving at one file", () => { it("openFile opens its folder on the Files page, with no search hiding it", () => { nav.page = "feed"; const { result, rerender } = render(); act(() => result.current.setSearch("valami")); act(() => result.current.openFile(7, 3)); expect(nav.setPage).toHaveBeenCalledWith("files"); expect(result.current.view).toEqual({ kind: "folder", id: 3 }); expect(result.current.search).toBe(""); nav.page = "files"; rerender(); expect(result.current.focus).toMatchObject({ id: 7 }); // The address carries it until it is spent, so a reload mid-arrival still lands on the file. expect(new URLSearchParams(window.location.search).get("item")).toBe("7"); }); it("a file in no folder opens every file", () => { const { result } = render(); act(() => result.current.openFile(7, null)); expect(result.current.view).toEqual(ALL_FILES); }); it("a ?item= link is an arrival from the start", () => { window.history.replaceState(null, "", "/?item=12"); const { result } = render(); expect(result.current.focus).toMatchObject({ id: 12 }); }); it("spent, it is what the page found — until the page is left", () => { const { result, rerender } = render(); act(() => result.current.openFile(7, null)); act(() => result.current.consumeFocus("all")); expect(result.current.focus).toBeNull(); expect(result.current.arrived).toMatchObject({ id: 7, view: "all" }); expect(new URLSearchParams(window.location.search).get("item")).toBeNull(); nav.page = "feed"; rerender(); expect(result.current.arrived).toBeNull(); nav.page = "files"; rerender(); // Back on the page later: nothing is rung or turned to again. expect(result.current.arrived).toBeNull(); }); it("an arrival found nowhere leaves nothing found", () => { const { result } = render(); act(() => result.current.openFile(7, null)); act(() => result.current.consumeFocus(null)); expect(result.current.focus).toBeNull(); expect(result.current.arrived).toBeNull(); }); it("the same file opened again is a new arrival", () => { const { result } = render(); act(() => result.current.openFile(7, null)); act(() => result.current.consumeFocus("all")); act(() => result.current.openFile(7, null)); expect(result.current.focus).toMatchObject({ id: 7 }); }); });