Netdata.cloud bot for Zulip
1"""Tests for webhook functionality.""" 2 3from datetime import datetime 4 5import pytest 6 7from netdata_zulip_bot.formatter import ZulipMessageFormatter 8from netdata_zulip_bot.models import ( 9 AlertNotification, 10 ReachabilityNotification, 11 WebhookPayload, 12) 13 14 15class TestWebhookPayload: 16 """Test webhook payload parsing.""" 17 18 def test_parse_alert_notification(self): 19 """Test parsing alert notification payload.""" 20 data = { 21 "message": "Critical alert on production server", 22 "alert": "high_cpu_usage", 23 "info": "CPU usage exceeded 90%", 24 "chart": "system.cpu", 25 "context": "cpu.utilization", 26 "space": "production", 27 "severity": "critical", 28 "date": "2024-01-15T14:30:00Z", 29 "alert_url": "https://app.netdata.cloud/spaces/abc/alerts/123", 30 } 31 32 notification = WebhookPayload.parse(data) 33 assert isinstance(notification, AlertNotification) 34 assert notification.severity.value == "critical" 35 assert notification.alert == "high_cpu_usage" 36 assert isinstance(notification.date, datetime) 37 38 def test_parse_reachability_notification(self): 39 """Test parsing reachability notification payload.""" 40 data = { 41 "message": "Host web-server-01 is unreachable", 42 "url": "https://app.netdata.cloud/hosts/web-server-01", 43 "host": "web-server-01", 44 "severity": "critical", 45 "status": {"reachable": False, "text": "unreachable"}, 46 } 47 48 notification = WebhookPayload.parse(data) 49 assert isinstance(notification, ReachabilityNotification) 50 assert notification.severity.value == "critical" 51 assert notification.host == "web-server-01" 52 assert not notification.status.reachable 53 54 def test_parse_unknown_payload_raises_error(self): 55 """Test that unknown payload types raise ValueError.""" 56 data = {"unknown_field": "value"} 57 58 with pytest.raises(ValueError, match="Unknown notification type"): 59 WebhookPayload.parse(data) 60 61 62class TestZulipMessageFormatter: 63 """Test Zulip message formatting.""" 64 65 def setup_method(self): 66 """Set up test fixtures.""" 67 self.formatter = ZulipMessageFormatter() 68 69 def test_format_critical_alert(self): 70 """Test formatting critical alert notification.""" 71 alert = AlertNotification( 72 message="Critical alert on production server", 73 alert="high_cpu_usage", 74 info="CPU usage exceeded 90% for 5 minutes", 75 chart="system.cpu", 76 context="cpu.utilization", 77 space="production", 78 severity="critical", 79 date=datetime(2024, 1, 15, 14, 30, 0), 80 alert_url="https://app.netdata.cloud/spaces/abc/alerts/123", 81 ) 82 83 topic, content = self.formatter.format_alert(alert) 84 85 assert topic == "critical" 86 assert "🔴" in content 87 assert "**high_cpu_usage**" in content 88 assert "production" in content 89 assert "Critical" in content 90 assert "2024-01-15 14:30:00 UTC" in content 91 assert ( 92 "[View Alert](https://app.netdata.cloud/spaces/abc/alerts/123)" in content 93 ) 94 95 def test_format_warning_alert(self): 96 """Test formatting warning alert notification.""" 97 alert = AlertNotification( 98 message="Warning: High memory usage", 99 alert="high_memory_usage", 100 info="Memory usage at 85%", 101 chart="system.ram", 102 context="memory.utilization", 103 space="staging", 104 severity="warning", 105 date=datetime(2024, 1, 15, 10, 15, 0), 106 alert_url="https://app.netdata.cloud/spaces/def/alerts/456", 107 ) 108 109 topic, content = self.formatter.format_alert(alert) 110 111 assert topic == "warning" 112 assert "⚠️" in content 113 assert "Warning" in content 114 115 def test_format_clear_alert(self): 116 """Test formatting clear alert notification.""" 117 alert = AlertNotification( 118 message="Alert cleared: CPU usage normal", 119 alert="high_cpu_usage", 120 info="CPU usage returned to normal levels", 121 chart="system.cpu", 122 context="cpu.utilization", 123 space="production", 124 severity="clear", 125 date=datetime(2024, 1, 15, 15, 0, 0), 126 alert_url="https://app.netdata.cloud/spaces/abc/alerts/123", 127 ) 128 129 topic, content = self.formatter.format_alert(alert) 130 131 assert topic == "clear" 132 assert "" in content 133 assert "Clear" in content 134 135 def test_format_reachability_unreachable(self): 136 """Test formatting unreachable host notification.""" 137 notification = ReachabilityNotification( 138 message="Host web-server-01 is unreachable", 139 url="https://app.netdata.cloud/hosts/web-server-01", 140 host="web-server-01", 141 severity="critical", 142 status={"reachable": False, "text": "unreachable"}, 143 ) 144 145 topic, content = self.formatter.format_reachability(notification) 146 147 assert topic == "reachability" 148 assert "🔴" in content # critical severity 149 assert "" in content # unreachable status 150 assert "web-server-01" in content 151 assert "Unreachable" in content 152 assert "[View Host](https://app.netdata.cloud/hosts/web-server-01)" in content 153 154 def test_format_reachability_reachable(self): 155 """Test formatting reachable host notification.""" 156 notification = ReachabilityNotification( 157 message="Host web-server-01 is reachable again", 158 url="https://app.netdata.cloud/hosts/web-server-01", 159 host="web-server-01", 160 severity="info", 161 status={"reachable": True, "text": "reachable"}, 162 ) 163 164 topic, content = self.formatter.format_reachability(notification) 165 166 assert topic == "reachability" 167 assert "ℹ️" in content # info severity 168 assert "" in content # reachable status 169 assert "Reachable" in content