"""通知配置模块测试 — 渠道CRUD + 推送历史""" import pytest from fastapi.testclient import TestClient from sqlalchemy.orm import Session from tests.conftest import create_test_user, get_token_for_user, auth_header class TestNotificationChannels: """通知渠道CRUD测试""" BASE = "/api/cma/notifications" def test_list_channels_empty(self, client: TestClient, db: Session): """空列表""" create_test_user(db) token = get_token_for_user(client) resp = client.get(f"{self.BASE}/channels", headers=auth_header(token)) assert resp.status_code == 200 assert resp.json()["data"] == [] def test_create_wecom_channel(self, client: TestClient, db: Session): """创建企微机器人渠道""" create_test_user(db) token = get_token_for_user(client) resp = client.post( f"{self.BASE}/channels", headers=auth_header(token), json={ "name": "告警群", "channel_type": "wecom", "config": {"webhook_url": "https://qyapi.weixin.qq.com/webhook/abc"}, "enabled": True, }, ) assert resp.status_code == 200 data = resp.json() assert data["name"] == "告警群" assert data["channel_type"] == "wecom" assert data["enabled"] is True def test_create_mail_channel(self, client: TestClient, db: Session): """创建邮件渠道""" create_test_user(db) token = get_token_for_user(client) resp = client.post( f"{self.BASE}/channels", headers=auth_header(token), json={ "name": "管理邮箱", "channel_type": "mail", "config": { "host": "smtp.qq.com", "port": 465, "user": "admin@example.com", "password": "pass", "to": ["admin@example.com"], }, }, ) assert resp.status_code == 200 assert resp.json()["channel_type"] == "mail" def test_update_channel(self, client: TestClient, db: Session): """更新渠道""" create_test_user(db) token = get_token_for_user(client) create_resp = client.post( f"{self.BASE}/channels", headers=auth_header(token), json={"name": "旧名称", "channel_type": "wecom", "config": {}}, ) ch_id = create_resp.json()["id"] resp = client.put( f"{self.BASE}/channels/{ch_id}", headers=auth_header(token), json={"name": "新名称", "enabled": False}, ) assert resp.status_code == 200 assert resp.json()["name"] == "新名称" assert resp.json()["enabled"] is False def test_delete_channel(self, client: TestClient, db: Session): """删除渠道""" create_test_user(db) token = get_token_for_user(client) create_resp = client.post( f"{self.BASE}/channels", headers=auth_header(token), json={"name": "待删除", "channel_type": "wecom", "config": {}}, ) ch_id = create_resp.json()["id"] resp = client.delete( f"{self.BASE}/channels/{ch_id}", headers=auth_header(token), ) assert resp.status_code == 200 assert resp.json()["message"] == "已删除" # 验证已删除 get_resp = client.get(f"{self.BASE}/channels", headers=auth_header(token)) assert len(get_resp.json()["data"]) == 0 def test_delete_channel_not_found(self, client: TestClient, db: Session): """删除不存在的渠道""" create_test_user(db) token = get_token_for_user(client) resp = client.delete(f"{self.BASE}/channels/99999", headers=auth_header(token)) assert resp.status_code == 404 def test_test_channel_network(self, client: TestClient, db: Session): """测试推送(网络可能不通,但不应500)""" create_test_user(db) token = get_token_for_user(client) create_resp = client.post( f"{self.BASE}/channels", headers=auth_header(token), json={"name": "测试", "channel_type": "wecom", "config": {"webhook_url": "http://invalid"}, "enabled": True}, ) ch_id = create_resp.json()["id"] # 网络不通,但应该返回结果而不是500 resp = client.post( f"{self.BASE}/channels/{ch_id}/test", headers=auth_header(token), ) assert resp.status_code == 200 assert "results" in resp.json() class TestNotificationLogs: """通知历史测试""" def test_logs_empty(self, client: TestClient, db: Session): """空日志""" create_test_user(db) token = get_token_for_user(client) resp = client.get("/api/cma/notifications/logs", headers=auth_header(token)) assert resp.status_code == 200 assert resp.json()["total"] == 0 def test_logs_with_data(self, client: TestClient, db: Session): """有了日志记录后可查询""" from app.models import NotificationLog from datetime import datetime # 直接插入日志 log = NotificationLog( alert_id=1, channel="wecom", recipient="测试群", title="测试通知", content="测试内容", status="sent", sent_at=datetime.now(), ) db.add(log) db.commit() create_test_user(db) token = get_token_for_user(client) resp = client.get("/api/cma/notifications/logs", headers=auth_header(token)) assert resp.status_code == 200 assert resp.json()["total"] >= 1 assert len(resp.json()["data"]) >= 1 class TestAlertPush: """手动推送测试""" def test_push_alerts_no_channels(self, client: TestClient, db: Session): """推送端点已移除,预期404""" create_test_user(db) token = get_token_for_user(client) resp = client.post("/api/cma/notifications/alerts/push", headers=auth_header(token)) assert resp.status_code == 404, "push端点已移除"