r"""Every backend vocabulary value has a label in all three languages. The workbench renders labels with a template key — ``t(\`automationException.cause.${row.root_cause}\`)`` — so a value the backend can emit but the bundle has no label for renders as the raw enum string in the UI. That failure is invisible to the type checker, to the linter, and to every frontend test, because the key is only assembled at runtime. It is also the exact shape of the mistake this domain hit three times while being written: a constant named from memory rather than read from its definition. So the check reads BOTH sides from their real definitions and compares them, rather than restating either list. """ from __future__ import annotations import re from pathlib import Path import pytest from app.domains.automation_exception.ownership import OWNER_SOURCES from app.domains.automation_exception.taxonomy import ( REMEDIES, ROOT_CAUSES, SEVERITIES, SOURCES, STATUSES, ) _I18N_DIR = Path(__file__).resolve().parents[3] / "web" / "src" / "i18n" _LANGS = ("zh-CN", "en-US", "ja-JP") #: ``label group`` -> the backend vocabulary it must cover. _GROUPS: dict[str, tuple[str, ...]] = { "cause": ROOT_CAUSES, "severity": SEVERITIES, "status": STATUSES, "source": SOURCES, "remedy": REMEDIES, # The long-form explanation shown in the detail drawer: one per # remedy, because a remedy the drawer cannot explain is a remedy the # admin has to guess at. "remedyLong": REMEDIES, "ownerSource": OWNER_SOURCES, } _KEY_RE = re.compile(r"^\s*'([^']+)':", re.M) def _keys_for(lang: str) -> set[str]: path = _I18N_DIR / f"{lang}.ts" if not path.exists(): # pragma: no cover - repo layout guard pytest.skip(f"i18n bundle not found: {path}") return set(_KEY_RE.findall(path.read_text(encoding="utf-8"))) @pytest.mark.parametrize("lang", _LANGS) def test_every_vocabulary_value_has_a_label(lang: str) -> None: keys = _keys_for(lang) missing = [ f"automationException.{group}.{value}" for group, values in _GROUPS.items() for value in values if f"automationException.{group}.{value}" not in keys ] assert not missing, ( f"{lang} is missing labels for backend vocabulary values: {missing}. " "These render as the raw enum string in the workbench." ) def test_the_three_bundles_agree_on_this_domain() -> None: """No language may carry a key the others lack. Partial parity is worse than none: the missing side silently falls back to the key itself, which reads as a bug in the page rather than a gap in the bundle. """ prefix = "automationException." by_lang = { lang: {k for k in _keys_for(lang) if k.startswith(prefix)} for lang in _LANGS } reference = by_lang[_LANGS[0]] for lang in _LANGS[1:]: assert by_lang[lang] == reference, ( f"{lang} differs from {_LANGS[0]}: " f"only in {lang}: {sorted(by_lang[lang] - reference)}; " f"missing from {lang}: {sorted(reference - by_lang[lang])}" )