// @vitest-environment jsdom // // A rail mounts anew on each visit to its page and seeds its layout from the `me` cache. When the shell // held the layout, a change lived on in its state; now the rail must leave the change where its next // mount looks, or a visit to another page and back brings the server's older layout back. import { describe, expect, it, vi } from "vitest"; import { renderHook, act } from "@testing-library/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import type { ReactNode } from "react"; import { api } from "./api"; import { qk } from "./queryKeys"; import { usePanelLayout } from "./useRail"; vi.mock("react-i18next", async (importOriginal) => ({ ...(await importOriginal()), useTranslation: () => ({ t: (k: string) => k }), })); const OLD = { order: ["year", "date", "channel", "tags", "language", "topic"], collapsed: {}, hidden: {}, }; const NEW = { order: ["tags", "date", "year", "channel", "language", "topic"], collapsed: {}, hidden: {}, }; describe("a rail's layout", () => { it("is the changed one on the next visit, not the server's older copy", () => { vi.spyOn(api, "savePrefs").mockResolvedValue(undefined as never); const qc = new QueryClient(); qc.setQueryData(qk.me(), { id: 1, preferences: { sidebarLayout: OLD } }); const wrapper = ({ children }: { children: ReactNode }) => ( {children} ); const first = renderHook(() => usePanelLayout("feed"), { wrapper }); expect(first.result.current[0].order).toEqual(OLD.order); act(() => first.result.current[1](NEW)); first.unmount(); const next = renderHook(() => usePanelLayout("feed"), { wrapper }); expect(next.result.current[0].order).toEqual(NEW.order); expect(api.savePrefs).toHaveBeenCalledWith({ sidebarLayout: NEW }); }); });