from __future__ import annotations import pytest from httpx import AsyncClient @pytest.mark.integration class TestJobsAPI: """ Интеграционные тесты для API endpoints. """ async def test_trigger_job_creates_new_job( self, client: AsyncClient, clean_queue_tables, queue_name: str, task_name: str, ): """ Тест создания новой задачи через API. """ payload = { "queue": queue_name, "task": task_name, "args": {"test_key": "test_value"}, "lock_key": "lock_api_1", "partition_key": "part1", "priority": 100, "max_attempts": 5, "lease_ttl_sec": 60, } response = await client.post("/api/v1/jobs/trigger", json=payload) assert response.status_code == 200 data = response.json() assert "job_id" in data assert data["status"] == "queued" async def test_trigger_job_with_idempotency_key( self, client: AsyncClient, clean_queue_tables, queue_name: str, task_name: str, ): """ Тест идемпотентности через idempotency_key. """ payload = { "queue": queue_name, "task": task_name, "args": {}, "idempotency_key": "unique_key_123", "lock_key": "lock_idem", "priority": 100, "max_attempts": 5, "lease_ttl_sec": 60, } response1 = await client.post("/api/v1/jobs/trigger", json=payload) response2 = await client.post("/api/v1/jobs/trigger", json=payload) assert response1.status_code == 200 assert response2.status_code == 200 data1 = response1.json() data2 = response2.json() assert data1["job_id"] == data2["job_id"] assert data1["status"] == data2["status"] == "queued" async def test_get_status_returns_job_status( self, client: AsyncClient, clean_queue_tables, queue_name: str, task_name: str, ): """ Тест получения статуса задачи через API. """ payload = { "queue": queue_name, "task": task_name, "args": {}, "lock_key": "lock_status", "priority": 100, "max_attempts": 5, "lease_ttl_sec": 60, } create_response = await client.post("/api/v1/jobs/trigger", json=payload) job_id = create_response.json()["job_id"] status_response = await client.get(f"/api/v1/jobs/{job_id}/status") assert status_response.status_code == 200 data = status_response.json() assert data["job_id"] == job_id assert data["status"] == "queued" assert data["attempt"] == 0 async def test_get_status_returns_404_for_nonexistent_job( self, client: AsyncClient, clean_queue_tables, ): """ Тест получения статуса несуществующей задачи. """ fake_job_id = "00000000-0000-0000-0000-000000000000" response = await client.get(f"/api/v1/jobs/{fake_job_id}/status") assert response.status_code == 404 async def test_cancel_job_sets_cancel_flag( self, client: AsyncClient, clean_queue_tables, queue_name: str, task_name: str, ): """ Тест отмены задачи через API. """ payload = { "queue": queue_name, "task": task_name, "args": {}, "lock_key": "lock_cancel", "priority": 100, "max_attempts": 5, "lease_ttl_sec": 60, } create_response = await client.post("/api/v1/jobs/trigger", json=payload) job_id = create_response.json()["job_id"] cancel_response = await client.post(f"/api/v1/jobs/{job_id}/cancel") assert cancel_response.status_code == 200 data = cancel_response.json() assert data["job_id"] == job_id async def test_cancel_nonexistent_job_returns_404( self, client: AsyncClient, clean_queue_tables, ): """ Тест отмены несуществующей задачи. """ fake_job_id = "00000000-0000-0000-0000-000000000000" response = await client.post(f"/api/v1/jobs/{fake_job_id}/cancel") assert response.status_code == 404 async def test_health_endpoint_returns_200( self, client: AsyncClient, ): """ Тест health check endpoint. """ response = await client.get("/health") assert response.status_code == 200