Files
FabledCurator/tests/test_fe_be_contract.py
T
bvandeusen 08420cd619 feat(I6): FE/BE enum contract test — pin JS mirrors to backend canon
The plain-JS frontend re-declares two backend enum value-sets by hand:
download-event statuses (downloadStatus.js) and platform keys
(platformColor.js). With no TS codegen, drift is silent — the same class
as the last_verified_at field mismatch.

tests/test_fe_be_contract.py parses both JS mirrors and asserts they equal
the backend canon (downloads._ALLOWED_STATUSES, platforms.known_platform_keys())
so a change on either side fails CI on whichever moved. Backend is the
source of truth. Documented the invariant in both JS file headers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 15:34:20 -04:00

45 lines
1.7 KiB
Python

"""FE/BE enum contract — guards against the field/enum drift class.
FabledCurator's frontend is plain JS (no TS codegen), so the frontend
re-declares a few backend enum value-sets by hand:
- download-event statuses → frontend/src/utils/downloadStatus.js
- platform keys → frontend/src/utils/platformColor.js
If either side edits its list without the other, the UI silently
mislabels rows or drops a platform (the `last_verified_at`-style drift).
These tests parse the JS mirrors and assert they equal the backend's
canonical definitions, so any divergence fails CI on whichever side moved.
The backend definitions are the source of truth; update the JS to match.
"""
import re
from pathlib import Path
from backend.app.api.downloads import _ALLOWED_STATUSES
from backend.app.services.platforms import known_platform_keys
_FRONTEND = Path(__file__).resolve().parents[1] / "frontend" / "src" / "utils"
def _read(name: str) -> str:
return (_FRONTEND / name).read_text(encoding="utf-8")
def test_download_status_values_match_backend() -> None:
# downloadStatus.js: each entry is `{ value: 'pending', ... }`
fe_values = set(re.findall(r"value:\s*'([a-z]+)'", _read("downloadStatus.js")))
assert fe_values == set(_ALLOWED_STATUSES), (
"downloadStatus.js DOWNLOAD_STATUSES is out of sync with backend "
"downloads._ALLOWED_STATUSES"
)
def test_platform_keys_match_backend() -> None:
# platformColor.js ICONS: each entry is `patreon: 'mdi-patreon',`
fe_keys = set(re.findall(r"^\s*(\w+):\s*'mdi-", _read("platformColor.js"), re.M))
assert fe_keys == set(known_platform_keys()), (
"platformColor.js ICONS is out of sync with backend "
"platforms.known_platform_keys()"
)