"""Acceptance tests for the approved three-theme mockup redesign.""" from __future__ import annotations import ast from pathlib import Path import re from types import SimpleNamespace import pytest pytest.importorskip("customtkinter") import customtkinter as ctk from antigravity_provider.router.ui.components import AccountCardWidget from antigravity_provider.router.ui.theme import Theme @pytest.fixture(scope="module") def ui_root(): root = ctk.CTk() root.withdraw() yield root root.destroy() @pytest.mark.unit def test_every_restored_account_handler_has_a_ui_trigger() -> None: required = {"test", "set_main", "set_orchestrator", "assign_role"} configured = {action for action, _label in AccountCardWidget.MANAGEMENT_ACTIONS} assert configured == required app_path = Path("src/antigravity_provider/router/hermes_hub_app.py") tree = ast.parse(app_path.read_text(encoding="utf-8")) handled = { node.comparators[0].value for node in ast.walk(tree) if isinstance(node, ast.Compare) and isinstance(node.left, ast.Name) and node.left.id == "action" and len(node.ops) == 1 and isinstance(node.ops[0], ast.Eq) and len(node.comparators) == 1 and isinstance(node.comparators[0], ast.Constant) and isinstance(node.comparators[0].value, str) } assert required <= handled @pytest.mark.unit def test_three_schemes_have_identical_token_coverage() -> None: assert set(Theme.PALETTES) == {"dark", "hybrid", "light"} token_sets = [set(palette) for palette in Theme.PALETTES.values()] assert token_sets[0] == token_sets[1] == token_sets[2] backgrounds = {palette["BG_WINDOW"] for palette in Theme.PALETTES.values()} assert len(backgrounds) == 3 @pytest.mark.unit def test_ui_colors_are_centralized_in_theme_tokens() -> None: roots = [ Path("src/antigravity_provider/router/ui"), Path("src/antigravity_provider/router/hermes_hub_app.py"), ] offenders = [] for root in roots: files = [root] if root.is_file() else list(root.rglob("*.py")) for file in files: if file.name == "theme.py": continue if re.search(r"#[0-9A-Fa-f]{3,8}", file.read_text(encoding="utf-8")): offenders.append(str(file)) assert offenders == [] @pytest.mark.unit def test_approved_mockup_numbers_are_not_shipped_as_placeholders() -> None: source_files = list(Path("src/antigravity_provider/router/ui").rglob("*.py")) source_files.append(Path("src/antigravity_provider/router/hermes_hub_app.py")) source = "\n".join(file.read_text(encoding="utf-8") for file in source_files) for fictional_value in ("78%", "09:00–21:00", "842 rps", "99.98%", "42 Мбит/с"): assert fictional_value not in source @pytest.mark.unit def test_apply_scheme_updates_shared_semantic_aliases() -> None: original = Theme.current_scheme try: for scheme in Theme.SCHEMES: assert Theme.apply_scheme(scheme) == scheme assert Theme.COLOR_POSITIVE == Theme.STATUS_HEALTHY assert Theme.COLOR_CAUTION == Theme.STATUS_WARNING assert Theme.COLOR_BRAND == Theme.ACCENT finally: Theme.apply_scheme(original) @pytest.mark.ui def test_restored_account_buttons_invoke_each_action(ui_root) -> None: calls = [] card = AccountCardWidget( ui_root, "profile-1", "user@example.test", "OpenAI Codex", on_action=lambda action, profile: calls.append((action, profile.profile_id)), ) card.profile_model = SimpleNamespace(profile_id="profile-1") try: card.pack() for action, _label in AccountCardWidget.MANAGEMENT_ACTIONS: card.action_buttons[action].invoke() assert calls == [(action, "profile-1") for action, _label in AccountCardWidget.MANAGEMENT_ACTIONS] finally: card.destroy()