import tempfile from pathlib import Path import pytest from httpx import ASGITransport, AsyncClient from app.core.events import EventBus from app.core.queue import DownloadQueue from app.core.storage import SqliteStorage from app.main import create_app @pytest.fixture async def client(): """Приложение без воркеров и lifespan — состояние подкладываем вручную, чтобы тесты роутов не качали реальные файлы.""" app = create_app() storage = SqliteStorage(Path(tempfile.mkdtemp()) / "test.db") await storage.init() app.state.storage = storage app.state.queue = DownloadQueue() app.state.events = EventBus() transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as c: yield c, app await storage.close() async def test_create_and_list(client): c, app = client resp = await c.post("/api/downloads", json={"urls": ["https://e.com/a.zip", "https://e.com/b.zip"]}) assert resp.status_code == 201 created = resp.json() assert len(created) == 2 assert app.state.queue.qsize() == 2 resp = await c.get("/api/downloads") assert resp.status_code == 200 assert len(resp.json()) == 2 async def test_create_empty_rejected(client): c, _ = client resp = await c.post("/api/downloads", json={"urls": [" ", ""]}) assert resp.status_code == 400 async def test_create_validation_requires_urls(client): c, _ = client resp = await c.post("/api/downloads", json={"urls": []}) assert resp.status_code == 422 # min_length=1 async def test_delete(client): c, _ = client created = (await c.post("/api/downloads", json={"urls": ["https://e.com/a.zip"]})).json() did = created[0]["id"] assert (await c.delete(f"/api/downloads/{did}")).status_code == 204 assert (await c.delete(f"/api/downloads/{did}")).status_code == 404 async def test_health(client): c, _ = client resp = await c.get("/api/health") assert resp.status_code == 200 and resp.json()["status"] == "ok"