import { render } from "@testing-library/react"; import { Trans } from "react-i18next"; import { describe, it, expect, beforeAll } from "vitest"; import i18n from "#/i18n"; /** * Regression: i18next's default ``escapeValue: true`` double-escaped * interpolated values because React's text renderer also escapes — * producing entity-encoded text like ``/tmp/foo`` in the DOM. * ``index.ts`` flips it to ``false``; this test guards against accidental * reversion. */ describe("i18next interpolation", () => { beforeAll(async () => { // Register a tiny test bundle so we don't depend on translation.json. i18n.addResourceBundle( "en", "translation", { TEST_PATH_INTERPOLATION: "Reading {{path}}" }, true, true, ); await i18n.changeLanguage("en"); }); it("renders interpolated paths verbatim (no HTML-entity escaping)", () => { const { container } = render( , ); expect(container.textContent).toBe( "Reading /tmp/pr14227/part_037.diff", ); // Specifically: the forward slashes must not be encoded. expect(container.innerHTML).not.toContain("/"); expect(container.innerHTML).not.toContain("/"); }); it("still renders potentially-dangerous characters as literal text (React-side safety boundary)", () => { const { container } = render( alert(1)" }} />, ); // React's text renderer turns ``<``/``>`` into entity references — they // appear as literal characters in textContent and do NOT execute. expect(container.textContent).toContain(""); expect(container.querySelector("script")).toBeNull(); }); });