Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
246 lines
8.7 KiB
Python
246 lines
8.7 KiB
Python
"""
|
|
Tests pour les routes de gestion des alertes.
|
|
|
|
Couvre:
|
|
- Création d'alertes
|
|
- Liste des alertes
|
|
- Comptage non lues
|
|
- Marquage comme lues
|
|
"""
|
|
|
|
import pytest
|
|
from unittest.mock import patch, AsyncMock
|
|
from httpx import AsyncClient
|
|
|
|
pytestmark = pytest.mark.unit
|
|
|
|
|
|
class TestCreateAlert:
|
|
"""Tests pour POST /api/alerts."""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_alert_success(self, client: AsyncClient, db_session):
|
|
"""Création d'alerte réussie."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
|
|
response = await client.post(
|
|
"/api/alerts",
|
|
json={
|
|
"category": "system",
|
|
"level": "warning",
|
|
"title": "Test Alert",
|
|
"message": "This is a test alert"
|
|
}
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["title"] == "Test Alert"
|
|
assert data["message"] == "This is a test alert"
|
|
assert data["level"] == "warning"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_alert_minimal(self, client: AsyncClient, db_session):
|
|
"""Création avec champs minimaux."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
|
|
response = await client.post(
|
|
"/api/alerts",
|
|
json={"message": "Minimal alert"}
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["message"] == "Minimal alert"
|
|
assert data["category"] == "general" # default
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_alert_broadcasts_ws(self, client: AsyncClient, db_session):
|
|
"""Création broadcast via WebSocket."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
|
|
await client.post(
|
|
"/api/alerts",
|
|
json={"message": "WS test alert"}
|
|
)
|
|
|
|
mock_ws.broadcast.assert_called_once()
|
|
call_args = mock_ws.broadcast.call_args[0][0]
|
|
assert call_args["type"] == "alert_created"
|
|
|
|
|
|
class TestGetAlerts:
|
|
"""Tests pour GET /api/alerts."""
|
|
|
|
async def test_list_alerts_empty(self, client: AsyncClient, db_session):
|
|
"""Liste vide quand pas d'alertes."""
|
|
response = await client.get("/api/alerts")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "alerts" in data
|
|
assert "count" in data
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_alerts_with_data(self, client: AsyncClient, db_session):
|
|
"""Liste les alertes depuis la BD."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
|
|
await client.post("/api/alerts", json={"message": "Alert 1"})
|
|
await client.post("/api/alerts", json={"message": "Alert 2"})
|
|
|
|
response = await client.get("/api/alerts")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["count"] >= 2
|
|
|
|
async def test_list_alerts_with_pagination(self, client: AsyncClient, db_session):
|
|
"""Pagination fonctionne."""
|
|
response = await client.get("/api/alerts?limit=5&offset=0")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "alerts" in data
|
|
|
|
async def test_list_alerts_unread_only(self, client: AsyncClient, db_session):
|
|
"""Filtre alertes non lues."""
|
|
response = await client.get("/api/alerts?unread_only=true")
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
class TestUnreadCount:
|
|
"""Tests pour GET /api/alerts/unread-count."""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_unread_count(self, client: AsyncClient, db_session):
|
|
"""Comptage des alertes non lues."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
|
|
# Create an alert first
|
|
await client.post("/api/alerts", json={"message": "Test alert"})
|
|
|
|
response = await client.get("/api/alerts/unread-count")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
# Response has 'unread' key instead of 'count'
|
|
assert "unread" in data or "count" in data
|
|
|
|
|
|
class TestMarkAsRead:
|
|
"""Tests pour POST /api/alerts/{alert_id}/read."""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mark_as_read_success(self, client: AsyncClient, db_session):
|
|
"""Marquer une alerte comme lue."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
create_response = await client.post(
|
|
"/api/alerts",
|
|
json={"message": "Alert to mark as read"}
|
|
)
|
|
|
|
alert_id = create_response.json()["id"]
|
|
response = await client.post(f"/api/alerts/{alert_id}/read")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert str(data["id"]) == str(alert_id)
|
|
assert "message" in data
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mark_as_read_not_found(self, client: AsyncClient, db_session):
|
|
"""Marquer une alerte inexistante retourne 404."""
|
|
response = await client.post("/api/alerts/nonexistent-id/read")
|
|
|
|
assert response.status_code == 404
|
|
assert "non trouvée" in response.json()["detail"]
|
|
|
|
|
|
class TestMarkAllAsRead:
|
|
"""Tests pour POST /api/alerts/mark-all-read."""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mark_all_as_read_success(self, client: AsyncClient, db_session):
|
|
"""Marquer toutes les alertes comme lues."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
|
|
# Create some alerts
|
|
await client.post("/api/alerts", json={"message": "Alert 1"})
|
|
await client.post("/api/alerts", json={"message": "Alert 2"})
|
|
|
|
response = await client.post("/api/alerts/mark-all-read")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "message" in data
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mark_all_as_read_broadcasts_ws(self, client: AsyncClient, db_session):
|
|
"""Marquer tout comme lu broadcast via WebSocket."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
|
|
await client.post("/api/alerts", json={"message": "Alert"})
|
|
await client.post("/api/alerts/mark-all-read")
|
|
|
|
# Should have been called for create and for mark-all-read
|
|
assert mock_ws.broadcast.call_count >= 1
|
|
|
|
|
|
class TestDeleteAlert:
|
|
"""Tests pour DELETE /api/alerts/{alert_id}."""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_alert_success(self, client: AsyncClient, db_session):
|
|
"""Suppression d'une alerte réussie."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
create_response = await client.post(
|
|
"/api/alerts",
|
|
json={"message": "Alert to delete"}
|
|
)
|
|
|
|
alert_id = create_response.json()["id"]
|
|
response = await client.delete(f"/api/alerts/{alert_id}")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert str(data["id"]) == str(alert_id)
|
|
assert "supprimée" in data["message"].lower() or "message" in data
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_alert_not_found(self, client: AsyncClient, db_session):
|
|
"""Suppression d'une alerte inexistante retourne 404."""
|
|
response = await client.delete("/api/alerts/nonexistent-id")
|
|
|
|
assert response.status_code == 404
|
|
assert "non trouvée" in response.json()["detail"]
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_alert_verify_removed(self, client: AsyncClient, db_session):
|
|
"""Vérifier que l'alerte est bien supprimée."""
|
|
with patch("app.routes.alerts.ws_manager") as mock_ws:
|
|
mock_ws.broadcast = AsyncMock()
|
|
create_response = await client.post(
|
|
"/api/alerts",
|
|
json={"message": "Alert to verify deletion"}
|
|
)
|
|
|
|
alert_id = create_response.json()["id"]
|
|
|
|
# Delete
|
|
await client.delete(f"/api/alerts/{alert_id}")
|
|
|
|
# Try to mark as read - should fail
|
|
response = await client.post(f"/api/alerts/{alert_id}/read")
|
|
assert response.status_code == 404
|