feat: Enhance admin dashboard with user, team, and event statistics, and system health monitoring
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env python3
|
||||
import pytest
|
||||
from unittest import mock
|
||||
from sqlalchemy.orm import Session
|
||||
from fastapi.testclient import TestClient
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from app.main import app
|
||||
from app.models import User, Team, Event, QRCode
|
||||
from app.views.admin import get_user_statistics, get_team_statistics
|
||||
from app.views.admin import get_event_statistics, get_system_health
|
||||
|
||||
# Fixture for mocking the database session
|
||||
@pytest.fixture
|
||||
def mock_db():
|
||||
"""Create a mock database session for testing."""
|
||||
mock_session = mock.MagicMock(spec=Session)
|
||||
return mock_session
|
||||
|
||||
# Test cases for user statistics
|
||||
def test_get_user_statistics(mock_db):
|
||||
"""Test getting user statistics."""
|
||||
# Setup mock query results
|
||||
mock_db.query().count.side_effect = [100, 80, 20]
|
||||
mock_db.query().filter().count.return_value = 10
|
||||
|
||||
# Get last 30 days
|
||||
thirty_days_ago = datetime.now() - timedelta(days=30)
|
||||
mock_db.query().filter().filter().count.return_value = 15
|
||||
|
||||
# Get the statistics
|
||||
stats = get_user_statistics(mock_db)
|
||||
|
||||
# Assert the expected results
|
||||
assert stats["total_users"] == 100
|
||||
assert stats["active_users"] == 80
|
||||
assert stats["verified_users"] == 20
|
||||
assert stats["admin_users"] == 10
|
||||
assert stats["new_registrations_30d"] == 15
|
||||
|
||||
# Test cases for team statistics
|
||||
def test_get_team_statistics(mock_db):
|
||||
"""Test getting team statistics."""
|
||||
# Setup mock query results
|
||||
mock_db.query().count.side_effect = [50, 45]
|
||||
mock_db.query().filter().count.return_value = 5
|
||||
|
||||
# Team distribution mock
|
||||
mock_team_distribution = [
|
||||
{"member_count": 0, "count": 5},
|
||||
{"member_count": 1, "count": 10},
|
||||
{"member_count": 2, "count": 15},
|
||||
{"member_count": 3, "count": 10},
|
||||
{"member_count": 4, "count": 7},
|
||||
{"member_count": 5, "count": 3}
|
||||
]
|
||||
mock_db.query().group_by().all.return_value = mock_team_distribution
|
||||
|
||||
# Get the statistics
|
||||
stats = get_team_statistics(mock_db)
|
||||
|
||||
# Assert the expected results
|
||||
assert stats["total_teams"] == 50
|
||||
assert stats["active_teams"] == 45
|
||||
assert stats["public_teams"] == 5
|
||||
assert stats["team_distribution"] == mock_team_distribution
|
||||
|
||||
# Test cases for event statistics
|
||||
def test_get_event_statistics(mock_db):
|
||||
"""Test getting event statistics."""
|
||||
# Setup mock query results
|
||||
mock_db.query().count.side_effect = [30, 25, 5]
|
||||
|
||||
# Setup mock for upcoming events
|
||||
today = datetime.now().date()
|
||||
upcoming_events = [
|
||||
mock.MagicMock(name="Event 1", event_date=today + timedelta(days=1), location="Location 1"),
|
||||
mock.MagicMock(name="Event 2", event_date=today + timedelta(days=3), location="Location 2"),
|
||||
mock.MagicMock(name="Event 3", event_date=today + timedelta(days=7), location="Location 3")
|
||||
]
|
||||
mock_db.query().filter().order_by().limit().all.return_value = upcoming_events
|
||||
|
||||
# Setup mock for attendance rates
|
||||
mock_attendance_rates = [
|
||||
{"event_id": 1, "event_name": "Event A", "attendee_count": 25},
|
||||
{"event_id": 2, "event_name": "Event B", "attendee_count": 18},
|
||||
{"event_id": 3, "event_name": "Event C", "attendee_count": 30}
|
||||
]
|
||||
mock_db.query().join().group_by().order_by().limit().all.return_value = mock_attendance_rates
|
||||
|
||||
# Get the statistics
|
||||
stats = get_event_statistics(mock_db)
|
||||
|
||||
# Assert the expected results
|
||||
assert stats["total_events"] == 30
|
||||
assert stats["past_events"] == 25
|
||||
assert stats["upcoming_events_count"] == 5
|
||||
assert len(stats["upcoming_events"]) == 3
|
||||
assert stats["attendance_rates"] == mock_attendance_rates
|
||||
|
||||
# Test cases for system health
|
||||
def test_get_system_health(mock_db):
|
||||
"""Test getting system health information."""
|
||||
# Mock database status
|
||||
mock_db.execute().fetchall.return_value = [{"status": "online"}]
|
||||
|
||||
# Get the health information
|
||||
health_info = get_system_health(mock_db)
|
||||
|
||||
# Assert expected results
|
||||
assert health_info["database_status"] == "online"
|
||||
assert "uptime" in health_info
|
||||
assert "recent_errors" in health_info
|
||||
|
||||
# Integration test for admin dashboard endpoint
|
||||
@mock.patch("app.views.admin.get_db")
|
||||
def test_admin_dashboard_endpoint(mock_get_db, mock_db):
|
||||
"""Test the admin dashboard endpoint."""
|
||||
# Setup mock DB to be returned from get_db
|
||||
mock_get_db.return_value = mock_db
|
||||
|
||||
# Mock user stats
|
||||
mock_user_stats = {
|
||||
"total_users": 100,
|
||||
"active_users": 80,
|
||||
"verified_users": 20,
|
||||
"admin_users": 10,
|
||||
"new_registrations_30d": 15
|
||||
}
|
||||
|
||||
# Mock team stats
|
||||
mock_team_stats = {
|
||||
"total_teams": 50,
|
||||
"active_teams": 45,
|
||||
"public_teams": 5,
|
||||
"team_distribution": []
|
||||
}
|
||||
|
||||
# Mock event stats
|
||||
mock_event_stats = {
|
||||
"total_events": 30,
|
||||
"past_events": 25,
|
||||
"upcoming_events_count": 5,
|
||||
"upcoming_events": [],
|
||||
"attendance_rates": []
|
||||
}
|
||||
|
||||
# Mock system health
|
||||
mock_system_health = {
|
||||
"database_status": "online",
|
||||
"uptime": "3 days, 2 hours",
|
||||
"recent_errors": []
|
||||
}
|
||||
|
||||
# Setup mock return values for our statistics functions
|
||||
with mock.patch("app.views.admin.get_user_statistics", return_value=mock_user_stats), \
|
||||
mock.patch("app.views.admin.get_team_statistics", return_value=mock_team_stats), \
|
||||
mock.patch("app.views.admin.get_event_statistics", return_value=mock_event_stats), \
|
||||
mock.patch("app.views.admin.get_system_health", return_value=mock_system_health), \
|
||||
mock.patch("app.views.admin.require_admin", return_value=lambda f: f):
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.get("/admin/dashboard")
|
||||
|
||||
# Assert the response
|
||||
assert response.status_code == 200
|
||||
assert "user_stats" in response.context
|
||||
assert "team_stats" in response.context
|
||||
assert "event_stats" in response.context
|
||||
assert "system_health" in response.context
|
||||
Reference in New Issue
Block a user