"""Tests for settings endpoints.""" from fastapi.testclient import TestClient from sqlalchemy.orm import Session from app.models.settings import Settings from app.models.user import User def test_get_settings_admin( client: TestClient, db: Session, admin_headers: dict[str, str], ) -> None: """Test GET /api/admin/settings returns settings for admin.""" # Create default settings settings = Settings( id=1, min_duration_minutes=30, max_duration_minutes=480, working_hours_start=8, working_hours_end=20, max_bookings_per_day_per_user=3, min_hours_before_cancel=2, ) db.add(settings) db.commit() response = client.get("/api/admin/settings", headers=admin_headers) assert response.status_code == 200 data = response.json() assert data["min_duration_minutes"] == 30 assert data["max_duration_minutes"] == 480 assert data["working_hours_start"] == 8 assert data["working_hours_end"] == 20 assert data["max_bookings_per_day_per_user"] == 3 assert data["min_hours_before_cancel"] == 2 def test_get_settings_creates_default_if_not_exist( client: TestClient, db: Session, admin_headers: dict[str, str], ) -> None: """Test GET /api/admin/settings creates default settings if not exist.""" response = client.get("/api/admin/settings", headers=admin_headers) assert response.status_code == 200 data = response.json() assert data["min_duration_minutes"] == 30 assert data["max_duration_minutes"] == 480 # Verify it was created in DB settings = db.query(Settings).filter(Settings.id == 1).first() assert settings is not None assert settings.min_duration_minutes == 30 def test_get_settings_non_admin_forbidden( client: TestClient, auth_headers: dict[str, str], ) -> None: """Test GET /api/admin/settings forbidden for non-admin.""" response = client.get("/api/admin/settings", headers=auth_headers) assert response.status_code == 403 def test_update_settings_admin( client: TestClient, db: Session, admin_headers: dict[str, str], ) -> None: """Test PUT /api/admin/settings updates settings for admin.""" # Create default settings settings = Settings( id=1, min_duration_minutes=30, max_duration_minutes=480, working_hours_start=8, working_hours_end=20, max_bookings_per_day_per_user=3, min_hours_before_cancel=2, ) db.add(settings) db.commit() # Update settings update_data = { "min_duration_minutes": 60, "max_duration_minutes": 600, "working_hours_start": 9, "working_hours_end": 18, "max_bookings_per_day_per_user": 5, "min_hours_before_cancel": 4, } response = client.put("/api/admin/settings", headers=admin_headers, json=update_data) assert response.status_code == 200 data = response.json() assert data["min_duration_minutes"] == 60 assert data["max_duration_minutes"] == 600 assert data["working_hours_start"] == 9 assert data["working_hours_end"] == 18 assert data["max_bookings_per_day_per_user"] == 5 assert data["min_hours_before_cancel"] == 4 # Verify update in DB db.refresh(settings) assert settings.min_duration_minutes == 60 assert settings.max_bookings_per_day_per_user == 5 def test_update_settings_validation_min_max_duration( client: TestClient, db: Session, admin_headers: dict[str, str], ) -> None: """Test PUT /api/admin/settings validates min <= max duration.""" # Create default settings settings = Settings(id=1) db.add(settings) db.commit() # Try to set min > max (but within Pydantic range) update_data = { "min_duration_minutes": 400, "max_duration_minutes": 100, "working_hours_start": 8, "working_hours_end": 20, "max_bookings_per_day_per_user": 3, "min_hours_before_cancel": 2, } response = client.put("/api/admin/settings", headers=admin_headers, json=update_data) assert response.status_code == 400 assert "duration" in response.json()["detail"].lower() def test_update_settings_validation_working_hours( client: TestClient, db: Session, admin_headers: dict[str, str], ) -> None: """Test PUT /api/admin/settings validates start < end hours.""" # Create default settings settings = Settings(id=1) db.add(settings) db.commit() # Try to set start >= end update_data = { "min_duration_minutes": 30, "max_duration_minutes": 480, "working_hours_start": 20, "working_hours_end": 8, "max_bookings_per_day_per_user": 3, "min_hours_before_cancel": 2, } response = client.put("/api/admin/settings", headers=admin_headers, json=update_data) assert response.status_code == 400 assert "working hours" in response.json()["detail"].lower() def test_update_settings_non_admin_forbidden( client: TestClient, auth_headers: dict[str, str], ) -> None: """Test PUT /api/admin/settings forbidden for non-admin.""" update_data = { "min_duration_minutes": 60, "max_duration_minutes": 600, "working_hours_start": 9, "working_hours_end": 18, "max_bookings_per_day_per_user": 5, "min_hours_before_cancel": 4, } response = client.put("/api/admin/settings", headers=auth_headers, json=update_data) assert response.status_code == 403 # ===== Audit Log Integration Tests ===== def test_settings_update_creates_audit_log( client: TestClient, admin_token: str, test_admin: User, db: Session, ) -> None: """Test that updating settings creates an audit log entry with changed fields.""" from app.models.audit_log import AuditLog # Create default settings settings = Settings( id=1, min_duration_minutes=30, max_duration_minutes=480, working_hours_start=8, working_hours_end=20, max_bookings_per_day_per_user=3, min_hours_before_cancel=2, ) db.add(settings) db.commit() # Update settings update_data = { "min_duration_minutes": 60, "max_duration_minutes": 600, "working_hours_start": 9, "working_hours_end": 18, "max_bookings_per_day_per_user": 5, "min_hours_before_cancel": 4, } response = client.put( "/api/admin/settings", headers={"Authorization": f"Bearer {admin_token}"}, json=update_data ) assert response.status_code == 200 # Check audit log was created audit = db.query(AuditLog).filter( AuditLog.action == "settings_updated", AuditLog.target_id == 1 ).first() assert audit is not None assert audit.target_type == "settings" assert audit.user_id == test_admin.id # Check that changed fields are tracked with old and new values changed_fields = audit.details["changed_fields"] assert "min_duration_minutes" in changed_fields assert changed_fields["min_duration_minutes"]["old"] == 30 assert changed_fields["min_duration_minutes"]["new"] == 60 assert "max_duration_minutes" in changed_fields assert changed_fields["max_duration_minutes"]["old"] == 480 assert changed_fields["max_duration_minutes"]["new"] == 600 assert "working_hours_start" in changed_fields assert "working_hours_end" in changed_fields assert "max_bookings_per_day_per_user" in changed_fields assert "min_hours_before_cancel" in changed_fields assert len(changed_fields) == 6 # All 6 fields changed