import pytest_asyncio from httpx import ASGITransport, AsyncClient from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import sessionmaker from playlist_sync.api import app from playlist_sync.services.application_service import ApplicationService from playlist_sync.services.database import get_session @pytest_asyncio.fixture(scope="function") async def client(db_engine): from playlist_sync.models.application import Application TestSessionLocal = sessionmaker( db_engine, class_=AsyncSession, expire_on_commit=False ) # Seed a "us" application so country_code resolution works in tests async with TestSessionLocal() as session: session.add( Application( id=1, name="US", spotify_region_code="US", active=True, fallback_application=False, global_push_application=False, workout_market=False, ) ) await session.commit() # Invalidate in-memory cache so tests see the seeded row ApplicationService.invalidate_cache() async def override_get_session(): async with TestSessionLocal() as session: yield session app.dependency_overrides[get_session] = override_get_session async with AsyncClient( transport=ASGITransport(app=app), base_url="http://test" ) as ac: yield ac app.dependency_overrides.clear() ApplicationService.invalidate_cache() async def test_health_check(client): response = await client.get("/health") assert response.status_code in (200, 503) # 503 when Redis not available in CI data = response.json() assert "status" in data assert data["status"] in ("healthy", "degraded") assert "database" in data assert "redis" in data async def test_create_and_list_sync(client, db_engine): from playlist_sync.models.sync_task import PlaylistSynchronization TestSessionLocal = sessionmaker( db_engine, class_=AsyncSession, expire_on_commit=False ) async with TestSessionLocal() as session: new_sync = PlaylistSynchronization( application_id=1, from_playlist_id="source-123", from_service_type=0, # ServiceType.Spotify to_playlist_id="target-456", to_service_account_id=789, title="Test Sync", ) session.add(new_sync) await session.commit() list_response = await client.get("/PlaylistSync/playlists") assert list_response.status_code == 200 assert len(list_response.json()) > 0 assert list_response.json()[0].get("title") == "Test Sync" # POST uses PlaylistSyncCreate schema (not the table model directly) create_payload = { "from_playlist_id": "source-789", "to_playlist_id": "target-000", "to_service_account_id": 111, "title": "New Sync", } create_response = await client.post( "/PlaylistSync/us/playlists", json=create_payload ) assert create_response.status_code == 201 assert create_response.json().get("title") == "New Sync" async def test_delete_sync(client, db_engine): from playlist_sync.models.sync_task import PlaylistSynchronization TestSessionLocal = sessionmaker( db_engine, class_=AsyncSession, expire_on_commit=False ) async with TestSessionLocal() as session: sync = PlaylistSynchronization( application_id=1, from_playlist_id="del-1", from_service_type=2, # ServiceType.YouTube to_playlist_id="del-2", to_service_account_id=3, title="To Delete", ) session.add(sync) await session.commit() await session.refresh(sync) sync_id = sync.id del_response = await client.delete(f"/PlaylistSync/us/playlists/{sync_id}") assert del_response.status_code == 204 log_response = await client.get(f"/PlaylistSync/us/playlists/{sync_id}/log") assert log_response.status_code == 200 assert log_response.json() == []