"""Regression checks for #6808: the boot script must not fabricate a theme choice. `syncSettings` in static/boot.js deliberately lets the server win on a first visit, because (its own comment) "empty (new-browser) state is indistinguishable from a user who chose the defaults". The inline bootstrap in static/index.html used to defeat that: it resolved a theme with `localStorage.getItem('hermes-theme')||'dark'` and then wrote the result back unconditionally, so a brand-new browser stored `hermes-theme=dark` before any request was made. syncSettings then saw an "explicit" value, ignored the server's SETTINGS_DEFAULTS, and POSTed the fabricated value back — making the server-side appearance default unreachable for deployments that change it. These cases pin the distinction the fix introduces, which nothing covered before: ABSENT appearance state is not the same as EXPLICIT appearance state. - both keys absent -> no setItem at all (and the dark pre-paint is UNCHANGED) - either key present -> both values are normalised and persisted - legacy names -> migration still happens, exactly as before The third is the reason the guard is on the PAIR rather than per key. The write is not pointless: it canonicalises legacy names (`solarized` -> dark+poseidon). With `hermes-theme=solarized` and no `hermes-skin`, a per-key guard would never write the derived skin and the mapping would be lost on the next load. """ import json import re import shutil import subprocess import tempfile from pathlib import Path import pytest ROOT = Path(__file__).resolve().parent.parent INDEX_HTML = ROOT / "static" / "index.html" NODE = shutil.which("node") pytestmark = pytest.mark.skipif( NODE is None, reason="node is required to execute the appearance bootstrap harness", ) def _bootstrap_script() -> str: """The inline appearance bootstrap, lifted out of index.html.""" html = INDEX_HTML.read_text(encoding="utf-8") for m in re.finditer(r"", html, re.S): body = m.group(1) if "hermes-theme" in body and "legacy" in body and "skins" in body: return body raise AssertionError("appearance bootstrap