"""Tests for _format_pending_action — no Telegram connection required. telegram stubs are set up in conftest.py before this module is imported. """ from __future__ import annotations import sys from pathlib import Path import pytest sys.path.insert(0, str(Path(__file__).parent.parent)) from bot import _format_pending_action # --------------------------------------------------------------------------- # Bug 1 — risk_level field # --------------------------------------------------------------------------- def test_risk_level_shown_when_present(): data = { "type": "container_restart", "service": "homeassistant", "node": "chelsty-ha", "risk_level": "low", } msg = _format_pending_action("container-restart-chelsty-ha-homeassistant", data) assert "Risk: *low*" in msg assert "unknown" not in msg def test_risk_falls_back_to_legacy_risk_key(): data = { "type": "redeploy", "service": "mosquitto", "node": "chelsty-infra", "risk": "guarded", } msg = _format_pending_action("redeploy-chelsty-infra-mosquitto", data) assert "Risk: *guarded*" in msg def test_risk_unknown_when_both_absent(): data = {"type": "redeploy", "service": "foo", "node": "bar"} msg = _format_pending_action("redeploy-bar-foo", data) assert "Risk: *unknown*" in msg # --------------------------------------------------------------------------- # Bug 2 — description field # --------------------------------------------------------------------------- def test_description_shown_for_alert_only(): data = { "type": "alert_only", "service": "homeassistant", "node": "chelsty-ha", "risk_level": "info", "description": "3 entities unavailable for >1h", } msg = _format_pending_action("alert-ha-entity-unavailable-chelsty-ha", data) assert "3 entities unavailable for >1h" in msg assert "Description:" in msg def test_description_shown_for_container_restart(): data = { "type": "container_restart", "service": "homeassistant", "node": "chelsty-ha", "risk_level": "low", "description": "Restart 'homeassistant' on chelsty-ha: HA WebSocket unresponsive", } msg = _format_pending_action("container-restart-chelsty-ha-homeassistant", data) assert "HA WebSocket unresponsive" in msg def test_description_absent_no_crash(): data = {"type": "redeploy", "service": "foo", "node": "bar", "risk_level": "guarded"} msg = _format_pending_action("redeploy-bar-foo", data) assert "Description:" not in msg assert "Risk: *guarded*" in msg def test_description_truncated_at_300_chars(): long_desc = "x" * 400 data = { "type": "alert_only", "service": "homeassistant", "node": "chelsty-ha", "risk_level": "info", "description": long_desc, } msg = _format_pending_action("alert-ha-foo-chelsty-ha", data) assert "x" * 300 in msg assert "..." in msg assert "x" * 301 not in msg # --------------------------------------------------------------------------- # Combined — real HA alert_only action shape # --------------------------------------------------------------------------- def test_ha_alert_only_full_action(): """Mirrors an actual alert_only action written by supervisor._generate_ha_alert_only.""" data = { "action_id": "alert-ha-entity-unavailable-chelsty-ha", "type": "alert_only", "node": "chelsty-ha", "service": "homeassistant", "risk_level": "info", "confidence": 1.0, "description": "3 entities unavailable for >1h: sensor.power, binary_sensor.window", "status": "pending", "payload": { "location_tag": "chelsty", "reason": "ha_entity_unavailable_long", "count": 3, }, } msg = _format_pending_action(data["action_id"], data) assert "alert_only" in msg assert "chelsty-ha" in msg assert "Risk: *info*" in msg assert "3 entities unavailable" in msg assert "unknown" not in msg