import uuid from typing import Dict import pytest from fastapi import FastAPI from fastapi.testclient import TestClient from sqlalchemy.orm import Session from app.api.routes.event_themes import router as event_themes_router from app.core.database import get_db from app.main import app as main_app # Mock the get_db dependency @pytest.fixture def override_get_db(db_session): """Override get_db dependency for testing.""" return db_session @pytest.fixture def app(override_get_db): """Create a FastAPI test application with overridden dependencies.""" app = FastAPI() app.include_router(event_themes_router, prefix="/event_themes", tags=["event_themes"]) # Override the get_db dependency app.dependency_overrides[get_db] = lambda: override_get_db return app @pytest.fixture def client(app: FastAPI) -> TestClient: return TestClient(app) @pytest.fixture def theme_data() -> Dict: return { "name": "Animal Safari", "description": "A wild and fun theme with safari animals", "preview_image_url": "https://example.com/safari.jpg", "color_palette": { "primary": "#f4a261", "secondary": "#2a9d8f", "background": "#ffffff", "text": "#264653" }, "fonts": { "header": "Safari Display", "body": "Nunito Sans" } } class TestEventThemesRoutes: def test_create_theme_success(self, client, db_session, theme_data): # Act response = client.post("/event_themes", json=theme_data) # Assert assert response.status_code == 200 data = response.json() assert data["name"] == theme_data["name"] assert data["description"] == theme_data["description"] assert data["preview_image_url"] == theme_data["preview_image_url"] assert data["color_palette"] == theme_data["color_palette"] assert data["fonts"] == theme_data["fonts"] assert "id" in data def test_create_theme_invalid_data(self, client, db_session): # Arrange invalid_data = { "name": "", # Empty name should not be allowed "color_palette": {}, # Empty color palette "fonts": {} # Empty fonts } # Act response = client.post("/event_themes", json=invalid_data) print(response.json()) # Assert assert response.status_code == 422 def test_list_themes_empty(self, client, db_session): # Act response = client.get("/event_themes") # Assert assert response.status_code == 200 assert response.json() == [] def test_list_themes_with_data(self, client, db_session, theme_data): # Arrange create_response = client.post("/event_themes", json=theme_data) assert create_response.status_code == 200 # Act response = client.get("/event_themes") # Assert assert response.status_code == 200 themes = response.json() assert len(themes) == 1 assert themes[0]["name"] == theme_data["name"] assert "id" in themes[0] def test_get_theme_by_id(self, client, db_session, theme_data): # Arrange create_response = client.post("/event_themes", json=theme_data) assert create_response.status_code == 200 created_theme = create_response.json() # Act response = client.get(f"/event_themes/{created_theme['id']}") # Assert assert response.status_code == 200 data = response.json() assert data["name"] == theme_data["name"] assert data["color_palette"] == theme_data["color_palette"] assert data["fonts"] == theme_data["fonts"] assert data["id"] == created_theme["id"] def test_get_theme_not_found(self, client, db_session): # Act random_id = str(uuid.uuid4()) response = client.get(f"/event_themes/{random_id}") # Assert assert response.status_code == 404 assert response.json()["detail"] == "Theme not found" def test_update_theme_success(self, client, db_session, theme_data): # Arrange create_response = client.post("/event_themes", json=theme_data) assert create_response.status_code == 200 created_theme = create_response.json() update_data = { "name": "Updated Safari Theme", "color_palette": { "primary": "#ff0000", "secondary": "#00ff00", "background": "#ffffff", "text": "#000000" } } # Act response = client.patch( f"/event_themes/{created_theme['id']}", json=update_data ) # Assert assert response.status_code == 200 data = response.json() assert data["name"] == update_data["name"] assert data["color_palette"] == update_data["color_palette"] assert data["id"] == created_theme["id"] # Original fonts should remain unchanged assert data["fonts"] == theme_data["fonts"] def test_update_theme_not_found(self, client, db_session): # Arrange random_id = str(uuid.uuid4()) update_data = { "name": "Updated Theme" } # Act response = client.patch( f"/event_themes/{random_id}", json=update_data ) # Assert assert response.status_code == 404 assert response.json()["detail"] == "Theme not found" def test_update_theme_invalid_data(self, client, db_session, theme_data): # Act response = client.post("/event_themes", json=theme_data) # Assert initial creation assert response.status_code == 200 theme = response.json() assert "id" in theme # Act - update with invalid data invalid_data = { "color_palette": "not_a_dict" # Should be a dictionary } response = client.patch(f"/event_themes/{theme['id']}", json=invalid_data) # Assert assert response.status_code == 422 def test_list_themes_pagination(self, client, db_session, theme_data): # Arrange # Create multiple themes for i in range(5): theme_data_copy = theme_data.copy() theme_data_copy["name"] = f"Theme {i}" response = client.post("/event_themes", json=theme_data_copy) assert response.status_code == 200 # Act response = client.get("/event_themes?skip=2&limit=2") # Assert assert response.status_code == 200 themes = response.json() assert len(themes) == 2 # Should only return 2 themes assert themes[0]["name"] == "Theme 2" assert themes[1]["name"] == "Theme 3" assert all("id" in theme for theme in themes) def test_list_themes_default_pagination(self, client, db_session, theme_data): # Arrange # Create more than default limit themes for i in range(15): # Reduced from 150 for faster testing theme_data_copy = theme_data.copy() theme_data_copy["name"] = f"Theme {i}" response = client.post("/event_themes", json=theme_data_copy) assert response.status_code == 200 # Act response = client.get("/event_themes") # Assert assert response.status_code == 200 themes = response.json() assert len(themes) <= 100 # Default limit is 100 assert all("id" in theme for theme in themes) def test_update_theme_partial(self, client, db_session, theme_data): # Arrange create_response = client.post("/event_themes", json=theme_data) assert create_response.status_code == 200 created_theme = create_response.json() update_data = { "name": "Partially Updated Theme" } # Act response = client.patch( f"/event_themes/{created_theme['id']}", json=update_data ) # Assert assert response.status_code == 200 data = response.json() assert data["name"] == update_data["name"] assert data["id"] == created_theme["id"] # Other fields should remain unchanged assert data["color_palette"] == theme_data["color_palette"] assert data["fonts"] == theme_data["fonts"] def test_create_theme_missing_required_fields(self, client, db_session): # Arrange incomplete_data = { "description": "Missing required name field" } # Act response = client.post("/event_themes", json=incomplete_data) # Assert assert response.status_code == 422