Some checks failed
CI / lint-and-test (push) Has been cancelled
- Cache Graph API tokens with expiry-aware reuse in graph/auth.py - Add tenacity-based retry/backoff wrapper (utils/http.py) and apply to all Graph/source API calls - Add Pydantic request/response models (models/api.py) and FastAPI query constraints - Add unit tests for event_model, auth and integration tests for API endpoints - Configure ruff linter/formatter in pyproject.toml - Add GitHub Actions CI pipeline (.github/workflows/ci.yml) - Add requirements-dev.txt with pytest, mongomock, httpx, ruff - Clean up typing imports and fix ruff linting across codebase
99 lines
3.0 KiB
Python
99 lines
3.0 KiB
Python
from datetime import UTC, datetime
|
|
|
|
|
|
def test_health(client):
|
|
response = client.get("/health")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "ok"
|
|
assert data["database"] == "connected"
|
|
|
|
|
|
def test_list_events_empty(client):
|
|
response = client.get("/api/events")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["items"] == []
|
|
assert data["total"] == 0
|
|
|
|
|
|
def test_list_events_pagination(client, mock_events_collection):
|
|
for i in range(5):
|
|
mock_events_collection.insert_one({
|
|
"id": f"evt-{i}",
|
|
"timestamp": datetime.now(UTC).isoformat(),
|
|
"service": "Directory",
|
|
"operation": "Add user",
|
|
"result": "success",
|
|
"actor_display": f"Actor {i}",
|
|
"raw_text": "",
|
|
})
|
|
response = client.get("/api/events?page=1&page_size=2")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["total"] == 5
|
|
assert len(data["items"]) == 2
|
|
assert data["page"] == 1
|
|
assert data["page_size"] == 2
|
|
|
|
|
|
def test_list_events_filter_by_service(client, mock_events_collection):
|
|
mock_events_collection.insert_one({
|
|
"id": "evt-1",
|
|
"timestamp": datetime.now(UTC).isoformat(),
|
|
"service": "Exchange",
|
|
"operation": "Update",
|
|
"result": "success",
|
|
"actor_display": "Alice",
|
|
"raw_text": "",
|
|
})
|
|
mock_events_collection.insert_one({
|
|
"id": "evt-2",
|
|
"timestamp": datetime.now(UTC).isoformat(),
|
|
"service": "Directory",
|
|
"operation": "Add",
|
|
"result": "success",
|
|
"actor_display": "Bob",
|
|
"raw_text": "",
|
|
})
|
|
response = client.get("/api/events?service=Exchange")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["total"] == 1
|
|
assert data["items"][0]["service"] == "Exchange"
|
|
|
|
|
|
def test_list_events_page_size_validation(client):
|
|
response = client.get("/api/events?page_size=0")
|
|
assert response.status_code == 422
|
|
response = client.get("/api/events?page_size=501")
|
|
assert response.status_code == 422
|
|
|
|
|
|
def test_filter_options(client, mock_events_collection):
|
|
mock_events_collection.insert_one({
|
|
"id": "evt-1",
|
|
"timestamp": datetime.now(UTC).isoformat(),
|
|
"service": "Intune",
|
|
"operation": "Assign",
|
|
"result": "failure",
|
|
"actor_display": "Charlie",
|
|
"actor_upn": "charlie@example.com",
|
|
"raw_text": "",
|
|
})
|
|
response = client.get("/api/filter-options")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "Intune" in data["services"]
|
|
assert "Assign" in data["operations"]
|
|
assert "failure" in data["results"]
|
|
assert "Charlie" in data["actors"]
|
|
assert "charlie@example.com" in data["actor_upns"]
|
|
|
|
|
|
def test_fetch_audit_logs_validation(client):
|
|
response = client.get("/api/fetch-audit-logs?hours=0")
|
|
assert response.status_code == 422
|
|
response = client.get("/api/fetch-audit-logs?hours=721")
|
|
assert response.status_code == 422
|