import { createNavigationMock, renderWithUser } from "@repo/test-utils"; import { screen, waitFor } from "@testing-library/react"; import { useEffect, useRef, useState } from "react"; import { beforeEach, describe, expect, test } from "vitest"; import { type LocationStateDefinition, useLocationGetKey, useLocationGetState, useLocationSetState, useLocationState, useLocationStateValue, } from "./hooks"; import { LocationStateProvider } from "./provider"; import { LOCATION_KEY_PREFIX } from "./stores"; const mockNavigation = createNavigationMock("/"); // @ts-expect-error globalThis.navigation = mockNavigation; beforeEach(() => { mockNavigation.navigate("/"); sessionStorage.clear(); }); describe(useLocationState, () => { function LocationSyncCounter() { const [count, setCount] = useLocationState({ name: "count", defaultValue: 0, storeName: "session", }); return (

count: {count}

); } function LocationSyncCounterPage() { return ( ); } test("The `count` can be updated.", async () => { // Arrange const { user } = renderWithUser(); // Act await user.click(await screen.findByRole("button", { name: "increment" })); // Assert expect(screen.getByRole("heading")).toHaveTextContent("count: 1"); }); test("The `count` can be updated with updater.", async () => { // Arrange const { user } = renderWithUser(); // Act await user.click( await screen.findByRole("button", { name: "increment with updater" }), ); // Assert expect(screen.getByRole("heading")).toHaveTextContent("count: 1"); }); test("The `count` is reset at navigation.", async () => { // Arrange const { user } = renderWithUser(); await user.click(await screen.findByRole("button", { name: "increment" })); // Act mockNavigation.navigate("/anywhere"); // Assert await waitFor(() => expect(screen.getByRole("heading")).toHaveTextContent("count: 0"), ); }); test("If there is a value in `sessionStorage`, it will be restored as the initial value.", async () => { // Arrange const key = mockNavigation.currentEntry?.key as string; sessionStorage.setItem( `${LOCATION_KEY_PREFIX}::value:${key}`, `{"count":2}`, ); // Act renderWithUser(); // Assert await waitFor(() => expect(screen.getByRole("heading")).toHaveTextContent("count: 2"), ); }); }); describe(useLocationStateValue, () => { function LocationSyncCounter() { const counter: LocationStateDefinition = { name: "count", defaultValue: 0, storeName: "session", }; const count = useLocationStateValue(counter); return

count: {count}

; } function LocationSyncCounterPage() { return ( ); } test("If there is a value in `sessionStorage`, it will be restored as the initial value.", async () => { // Arrange const key = mockNavigation.currentEntry?.key as string; sessionStorage.setItem( `${LOCATION_KEY_PREFIX}::value:${key}`, `{"count":2}`, ); // Act renderWithUser(); // Assert await waitFor(() => expect(screen.getByRole("heading")).toHaveTextContent("count: 2"), ); }); }); describe(useLocationSetState, () => { function LocationSyncCounter() { const counter: LocationStateDefinition = { name: "counter", defaultValue: 0, storeName: "session", }; const rendered = useRef(1); const setCount = useLocationSetState(counter); useEffect(() => { rendered.current++; }, []); return (

rendered: {rendered.current}

); } function LocationSyncCounterPage() { return ( ); } test("`setCount` does not re-render.", async () => { // Arrange const { user } = renderWithUser(); // Act await user.click(await screen.findByRole("button", { name: "increment" })); // Assert expect(screen.getByRole("heading")).toHaveTextContent("rendered: 1"); }); }); describe(useLocationGetState, () => { function LocationSyncOnceCounter() { const counter: LocationStateDefinition = { name: "count", defaultValue: 0, storeName: "session", }; const getState = useLocationGetState(counter); const [, setState] = useState(false); return ( <>

count: {getState()}

); } function LocationSyncCounterPage() { return ( ); } test("If there is a value in `sessionStorage`, it is not re-rendered.", async () => { // Arrange const key = mockNavigation.currentEntry?.key as string; sessionStorage.setItem( `${LOCATION_KEY_PREFIX}::value:${key}`, `{"count":2}`, ); // Act renderWithUser(); // Assert await waitFor(() => expect(screen.getByRole("heading")).toHaveTextContent("count: 0"), ); }); test("Always get the latest values.", async () => { // Arrange const key = mockNavigation.currentEntry?.key as string; sessionStorage.setItem( `${LOCATION_KEY_PREFIX}::value:${key}`, `{"count":2}`, ); const { user } = renderWithUser(); // Act await user.click( await screen.findByRole("button", { name: "force render" }), ); // Assert expect(screen.getByRole("heading")).toHaveTextContent("count: 2"); }); }); describe(useLocationGetKey, () => { function LocationSyncKeyDisplay() { const getLocationKey = useLocationGetKey(); const [key, setKey] = useState(); return (

key: {key ?? "undefined"}

); } function LocationSyncKeyPage() { return ( ); } test("Returns a function that gets the current location key", async () => { // Arrange const { user } = renderWithUser(); // Act await user.click(await screen.findByRole("button", { name: "get key" })); // Assert expect(screen.getByRole("heading")).not.toHaveTextContent("key: undefined"); }); test("Does not cause re-renders when location key changes", async () => { // Arrange const { user } = renderWithUser(); await user.click(screen.getByRole("button", { name: "get key" })); const initialKey = screen.getByRole("heading", { level: 1 }).textContent; // Act mockNavigation.navigate("/new-path"); // Assert expect(screen.getByRole("heading", { level: 1 })).toHaveTextContent( initialKey!, ); }); test("Always gets the latest key when re-render", async () => { // Arrange const initialKey = mockNavigation.currentEntry?.key as string; const { user } = renderWithUser(); mockNavigation.navigate("/new-path"); // Act await user.click(screen.getByRole("button", { name: "get key" })); // Assert const displayedKey = screen.getByRole("heading", { level: 1 }).textContent; expect(displayedKey).not.toContain("undefined"); expect(displayedKey).not.toBe(`key: ${initialKey}`); // Should be different from initial key }); });