Add multi-league foundation

This commit is contained in:
Christian Krakau-Louis
2026-05-22 20:47:28 +02:00
parent e032994628
commit 15e1dc227b
23 changed files with 775 additions and 205 deletions
+121 -159
View File
@@ -1,170 +1,132 @@
#!/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
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# 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
from app.models import Base, Event, EventAttendee, Team, TeamMembership, User
from app.views.admin import (
get_event_statistics,
get_system_health,
get_team_statistics,
get_user_statistics,
)
# 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}
@pytest.fixture()
def db_session():
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(bind=engine)
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
db = TestingSessionLocal()
try:
yield db
finally:
db.close()
def seed_users(db):
now = datetime.utcnow()
users = [
User(
username="admin",
email="admin@example.com",
hashed_password="hash",
is_active=True,
is_verified=True,
is_admin=True,
created_at=now - timedelta(days=2),
),
User(
username="verified",
email="verified@example.com",
hashed_password="hash",
is_active=True,
is_verified=True,
is_admin=False,
created_at=now - timedelta(days=10),
),
User(
username="inactive",
email="inactive@example.com",
hashed_password="hash",
is_active=False,
is_verified=False,
is_admin=False,
created_at=now - timedelta(days=60),
),
]
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
db.add_all(users)
db.commit()
return users
# 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
def test_get_user_statistics(db_session):
seed_users(db_session)
stats = get_user_statistics(db_session)
assert stats["total_users"] == 3
assert stats["active_users"] == 2
assert stats["verified_users"] == 2
assert stats["admin_users"] == 1
assert stats["new_registrations_30d"] == 2
assert len(stats["monthly_registrations"]) == 6
assert len(stats["month_labels"]) == 6
def test_get_team_statistics(db_session):
users = seed_users(db_session)
teams = [
Team(name="Open Team", is_active=True, is_public=True),
Team(name="Private Team", is_active=True, is_public=False),
Team(name="Archived Team", is_active=False, is_public=False),
]
db_session.add_all(teams)
db_session.commit()
db_session.add_all([
TeamMembership(user_id=users[0].id, team_id=teams[0].id),
TeamMembership(user_id=users[1].id, team_id=teams[0].id),
TeamMembership(user_id=users[2].id, team_id=teams[1].id),
])
db_session.commit()
stats = get_team_statistics(db_session)
assert stats["total_teams"] == 3
assert stats["active_teams"] == 2
assert stats["public_teams"] == 1
assert {"member_count": 2, "count": 1} in stats["team_distribution"]
assert {"member_count": 1, "count": 1} in stats["team_distribution"]
def test_get_event_statistics(db_session):
users = seed_users(db_session)
now = datetime.now()
past_event = Event(name="Past Quiz", event_date=now - timedelta(days=1))
future_event = Event(name="Future Quiz", event_date=now + timedelta(days=7))
db_session.add_all([past_event, future_event])
db_session.commit()
db_session.add_all([
EventAttendee(event_id=past_event.id, user_id=users[0].id),
EventAttendee(event_id=past_event.id, user_id=users[1].id),
])
db_session.commit()
stats = get_event_statistics(db_session)
assert stats["total_events"] == 2
assert stats["past_events"] == 1
assert stats["upcoming_events_count"] == 1
assert [event.name for event in stats["upcoming_events"]] == ["Future Quiz"]
assert stats["attendance_rates"][0].event_name == "Past Quiz"
assert stats["attendance_rates"][0].attendee_count == 2
def test_get_system_health(db_session):
health_info = get_system_health(db_session)
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
assert health_info["recent_errors"] == []