import { act } from "react"; import { createRoot, type Root } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; vi.mock("../../lib/i18n", () => ({ t: (_key: string, fallback?: string) => fallback ?? _key, })); import LanguageSelector from "./LanguageSelector"; const roots: Root[] = []; beforeEach(() => { window.localStorage.clear(); window.history.replaceState({}, "", "/"); document.body.innerHTML = ""; }); afterEach(() => { for (const root of roots.splice(0)) { act(() => { root.unmount(); }); } vi.restoreAllMocks(); }); function renderSelector() { const container = document.createElement("div"); document.body.appendChild(container); const root = createRoot(container); roots.push(root); act(() => { root.render(); }); return container; } describe("LanguageSelector", () => { it("prefers the locale stored in localStorage", () => { window.localStorage.setItem("locale", "en"); const container = renderSelector(); const select = container.querySelector("select") as HTMLSelectElement; expect(select.value).toBe("en"); }); it("falls back to the path locale when storage is empty", () => { window.history.replaceState({}, "", "/ko"); const container = renderSelector(); const select = container.querySelector("select") as HTMLSelectElement; expect(select.value).toBe("ko"); }); it("saves the selected locale and dispatches a development event", () => { vi.stubEnv("MODE", "development"); const dispatchEvent = vi.spyOn(window, "dispatchEvent"); window.history.replaceState({}, "", "/ko"); const container = renderSelector(); const select = container.querySelector("select") as HTMLSelectElement; act(() => { select.value = "en"; select.dispatchEvent(new Event("change", { bubbles: true })); }); expect(window.localStorage.getItem("locale")).toBe("en"); expect(dispatchEvent).toHaveBeenCalled(); expect(select.value).toBe("en"); }); });