// @vitest-environment jsdom // // ChannelsProvider's tab-history behaviour: setView pushes a `_chTab` history entry + persists the tab, // and a genuine browser Back (popstate carrying `_chTab`) restores + re-persists it. This wiring was // re-routed through usePersistedTab in R13 S2b, so it's exercised here rather than only by hand E2E. // // Uses REAL storage (jsdom localStorage/sessionStorage) with the tab's account pinned to 1, so // usePersistedTab / useSortState / useFilterState all resolve their account-scoped keys; only // NavigationProvider (the sole runtime dependency) is mocked, pinned to the channels page. import { describe, it, expect, beforeEach, vi } from "vitest"; import { renderHook, act } from "@testing-library/react"; import type { ReactNode } from "react"; vi.mock("./NavigationProvider", () => ({ useNavigation: () => ({ page: "channels" }), useNavigationActions: () => ({ setPage: vi.fn() }), })); import { ChannelsProvider, useChannels, useChannelsActions } from "./ChannelsProvider"; const wrapper = ({ children }: { children: ReactNode }) => ( {children} ); const render = () => renderHook(() => ({ ...useChannels(), ...useChannelsActions() }), { wrapper }); const VIEW_KEY = "siftlode.channelsView.1"; // account-scoped (accountKey suffixes the pinned id) beforeEach(() => { localStorage.clear(); sessionStorage.setItem("siftlode.activeAccount", "1"); // pin the tab's account window.history.replaceState({ sfPage: "channels" }, ""); // setView only owns an entry on this page }); describe("ChannelsProvider tab history", () => { it("setView pushes a _chTab history entry and persists the tab", () => { const { result } = render(); expect(result.current.view).toBe("subscribed"); // default act(() => result.current.setView("hidden")); expect(result.current.view).toBe("hidden"); expect(window.history.state).toMatchObject({ sfPage: "channels", _chTab: "hidden" }); expect(localStorage.getItem(VIEW_KEY)).toBe("hidden"); }); it("does NOT push a new entry when re-selecting the current tab", () => { const { result } = render(); const spy = vi.spyOn(window.history, "pushState"); act(() => result.current.setView("subscribed")); // already the current tab expect(spy).not.toHaveBeenCalled(); spy.mockRestore(); }); it("a genuine Back (popstate carrying _chTab) restores and re-persists that tab", () => { const { result } = render(); act(() => result.current.setView("blocked")); expect(result.current.view).toBe("blocked"); // Browser Back to an entry stamped with a different tab. act(() => window.dispatchEvent(new PopStateEvent("popstate", { state: { _chTab: "discovery" } })), ); expect(result.current.view).toBe("discovery"); expect(localStorage.getItem(VIEW_KEY)).toBe("discovery"); }); it("ignores a popstate for an entry outside the manager (no _chTab)", () => { const { result } = render(); act(() => result.current.setView("hidden")); act(() => window.dispatchEvent(new PopStateEvent("popstate", { state: { sfPage: "feed" } }))); expect(result.current.view).toBe("hidden"); // unchanged }); });