import { beforeEach, describe, expect, it, vi } from "vitest"; import { readFileSync } from "node:fs"; import { resolve } from "node:path"; import { applyLang, DEFAULT_SETTINGS } from "@/store/settings"; /** * `` has to be right *before first paint*, not after mount. * * Chrome decides whether to offer a translation from the language it detects * against the language the page declares. A `lang` patched in from a * `useEffect` leaves a window where the two disagree, and that window is * enough to raise the prompt on a page that was already in the reader's * language — after which accepting it rewrites the DOM under React. * * Two halves, and they are different claims: the served HTML already says so, * and the stored preference is applied without waiting for a render. */ describe("the served HTML", () => { it("declares a language in the markup itself, not from script", () => { // jsdom rewrites import.meta.url to an http URL, so resolve from the // Vite root instead of relative to this file. const html = readFileSync(resolve(process.cwd(), "index.html"), "utf8"); expect(html).toMatch(/]*\slang="en"/); }); }); describe("applyLang", () => { beforeEach(() => { document.documentElement.removeAttribute("lang"); }); it("puts the resolved language on the document", () => { applyLang({ ...DEFAULT_SETTINGS, uiLanguage: "en" }); expect(document.documentElement.lang).toBe("en"); }); it("falls back to English rather than claiming a language it cannot render", () => { applyLang({ ...DEFAULT_SETTINGS, uiLanguage: "de" }); expect(document.documentElement.lang).toBe("en"); }); it("is applied from the module the app imports before it renders", async () => { /* * main.tsx imports App, which reaches this store, before it calls * createRoot().render(). Re-importing runs the module's own side effects * against a document that has just had the attribute stripped, which is * the closest a test runner gets to "was it set before the first paint". */ document.documentElement.removeAttribute("lang"); vi.resetModules(); await import("@/store/settings"); expect(document.documentElement.lang).toBe("en"); }); });