py/tests/test_errcode_pane.py
"""Robot-UI tests (LAW) for the ERROR-CODES pane — the Streamlit twin of
facett-demo's ``Errors`` tab (LAW #2: both demos in lockstep).
Asserts, as DATA (never a matched string):
* the generated catalog loads and is non-trivial;
* every code is well-formed ``facet-<component>-<n>`` and globally unique;
* every code carries a Phase-2 REACTION from the shared vocabulary;
* the reaction matrix rows are ``<mount>:<code>`` with a consistent reaction;
* the pane renders headlessly inside the app without an exception, and the
``Errors`` tab is actually reachable in the shipped app.
"""
from __future__ import annotations
import json
import os
import re
import pytest
from streamlit.testing.v1 import AppTest
from facett_demo.panes import errcode_pane
import facett_demo
APP = os.path.join(os.path.dirname(os.path.abspath(facett_demo.__file__)), "app.py")
CODE_RE = re.compile(r"^facet-[a-z0-9]+-\d+$")
#: The shared reaction vocabulary (facett_core::errcode::Reaction).
REACTIONS = {"retry", "empty_state", "reconnect", "fallback", "diagnose"}
def test_registry_json_loads_and_is_populated() -> None:
reg = errcode_pane.registry()
assert reg["scheme"] == "facet-<component>-<n>"
assert reg["code_count"] >= 20, "the catalog is populated"
assert reg["code_count"] == len(reg["codes"])
assert reg["component_count"] == len(reg["components"])
assert reg["wired_count"] >= 1
def test_every_code_is_well_formed_and_unique() -> None:
reg = errcode_pane.registry()
seen: set[str] = set()
per_component: dict[str, set[int]] = {}
for c in reg["codes"]:
assert CODE_RE.match(c["code"]), f"malformed code {c['code']}"
assert c["code"] == f"facet-{c['component']}-{c['n']}"
assert c["code"] not in seen, f"duplicate code {c['code']}"
seen.add(c["code"])
ns = per_component.setdefault(c["component"], set())
assert c["n"] not in ns, f"duplicate n={c['n']} in {c['component']}"
ns.add(c["n"])
assert c["message"], "every code has a visible message"
assert c["source_url"].startswith("https://gunnar.rs/nordisk/facett")
assert c["status"] in {"wired", "reserved"}
def test_every_code_has_a_phase2_reaction() -> None:
reg = errcode_pane.registry()
for c in reg["codes"]:
assert c["reaction"] in REACTIONS, f"{c['code']} has an unknown reaction"
assert c["reaction_describes"], "the reaction explains what to DO"
assert {r["token"] for r in reg["reactions"]} == REACTIONS
def test_reaction_matrix_rows_are_mounted_codes() -> None:
reg = errcode_pane.registry()
by_code = {c["code"]: c for c in reg["codes"]}
assert reg["reaction_pairs"] == len(reg["reaction_matrix"])
assert reg["reaction_pairs"] >= 1
seen: set[str] = set()
for row in reg["reaction_matrix"]:
assert row["mounted_code"] == f"{row['mount']}:{row['code']}"
assert row["mounted_code"] not in seen, "matrix rows are unique"
seen.add(row["mounted_code"])
assert "/" in row["mount"], "a mount is <app>/<surface>"
# The reaction is a property of the CODE — the mount must not change it.
assert row["reaction"] == by_code[row["code"]]["reaction"]
def test_errors_tab_renders_in_the_shipped_app() -> None:
"""The pane must be REACHABLE in the shipped app (LAW #2), not just importable."""
at = AppTest.from_file(APP, default_timeout=60).run()
assert not at.exception, f"app raised: {at.exception}"
labels = [t.label for t in at.tabs]
assert any("Errors" in lbl for lbl in labels), f"no Errors tab in {labels}"
def test_code_chip_paints_the_clear_pink() -> None:
"""The code chip carries the SAME clear pink the native demo paints."""
chip = errcode_pane.code_chip("facet-map-2")
assert errcode_pane.PINK == "#FF40B4"
assert errcode_pane.PINK in chip
assert "facet-map-2" in chip