Files
gh-christianlouis-dmarq/backend/app/tests/test_imap_endpoints.py
T

161 lines
5.7 KiB
Python

"""
Tests for the /api/v1/imap endpoints.
Covers connection testing, report fetching (foreground and background), and status.
"""
from unittest.mock import MagicMock, patch
from fastapi.testclient import TestClient
class TestImapTestConnection:
"""Tests for POST /api/v1/imap/test-connection"""
def test_successful_connection(self, authed_client: TestClient):
mock_client = MagicMock()
mock_client.test_connection.return_value = (
True,
"Connection successful",
{
"message_count": 5,
"unread_count": 2,
"dmarc_count": 1,
"available_mailboxes": ["INBOX", "Sent"],
"server": "imap.example.com",
"port": 993,
},
)
with patch("app.api.api_v1.endpoints.imap.IMAPClient", return_value=mock_client):
response = authed_client.post(
"/api/v1/imap/test-connection",
json={
"server": "imap.example.com",
"port": 993,
"username": "user@example.com",
"password": "secret",
"ssl": True,
},
)
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert data["message_count"] == 5
assert data["unread_count"] == 2
assert "INBOX" in data["available_mailboxes"]
def test_failed_connection(self, authed_client: TestClient):
mock_client = MagicMock()
mock_client.test_connection.return_value = (False, "Connection failed", {})
with patch("app.api.api_v1.endpoints.imap.IMAPClient", return_value=mock_client):
response = authed_client.post(
"/api/v1/imap/test-connection",
json={"server": "bad.example.com", "port": 993},
)
assert response.status_code == 200
data = response.json()
assert data["success"] is False
assert data["message_count"] == 0
def test_requires_auth(self, client: TestClient):
"""Without auth, the endpoint should return 401."""
response = client.post(
"/api/v1/imap/test-connection",
json={"server": "imap.example.com", "port": 993},
)
assert response.status_code == 401
class TestImapFetchReports:
"""Tests for POST /api/v1/imap/fetch-reports"""
def test_fetch_foreground_success(self, authed_client: TestClient):
mock_client = MagicMock()
mock_client.fetch_reports.return_value = {
"success": True,
"processed": 3,
"reports_found": 2,
"new_domains": ["example.com"],
"errors": [],
}
with patch("app.api.api_v1.endpoints.imap.IMAPClient", return_value=mock_client):
response = authed_client.post("/api/v1/imap/fetch-reports?days=7")
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert data["processed_emails"] == 3
assert data["reports_found"] == 2
def test_fetch_days_too_low(self, authed_client: TestClient):
response = authed_client.post("/api/v1/imap/fetch-reports?days=0")
assert response.status_code == 400
def test_fetch_days_too_high(self, authed_client: TestClient):
response = authed_client.post("/api/v1/imap/fetch-reports?days=400")
assert response.status_code == 400
def test_fetch_background_for_long_range(self, authed_client: TestClient):
"""Days > 14 should queue a background task."""
mock_client = MagicMock()
with patch("app.api.api_v1.endpoints.imap.IMAPClient", return_value=mock_client):
response = authed_client.post("/api/v1/imap/fetch-reports?days=30")
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert "background" in data["message"].lower()
def test_fetch_with_errors_in_result(self, authed_client: TestClient):
mock_client = MagicMock()
mock_client.fetch_reports.return_value = {
"success": True,
"processed": 1,
"reports_found": 0,
"new_domains": [],
"errors": ["Could not parse email 1"],
}
with patch("app.api.api_v1.endpoints.imap.IMAPClient", return_value=mock_client):
response = authed_client.post("/api/v1/imap/fetch-reports?days=3")
assert response.status_code == 200
data = response.json()
assert data["errors"] is not None
def test_fetch_exception_returns_500(self, authed_client: TestClient):
mock_client = MagicMock()
mock_client.fetch_reports.side_effect = RuntimeError("unexpected")
with patch("app.api.api_v1.endpoints.imap.IMAPClient", return_value=mock_client):
response = authed_client.post("/api/v1/imap/fetch-reports?days=5")
assert response.status_code == 500
def test_requires_auth(self, client: TestClient):
response = client.post("/api/v1/imap/fetch-reports?days=7")
assert response.status_code == 401
class TestImapStatus:
"""Tests for GET /api/v1/imap/status"""
def test_status_returns_200(self, authed_client: TestClient):
response = authed_client.get("/api/v1/imap/status")
assert response.status_code == 200
def test_status_response_structure(self, authed_client: TestClient):
response = authed_client.get("/api/v1/imap/status")
data = response.json()
assert "is_running" in data
assert "timestamp" in data
def test_requires_auth(self, client: TestClient):
response = client.get("/api/v1/imap/status")
assert response.status_code == 401