chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
"""
|
||||
Integration tests for the task management router.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
|
||||
|
||||
_LITE_MODE = os.getenv("LITE_MODE", "").lower() in {"true", "1"}
|
||||
|
||||
|
||||
async def test_task_routes_require_admin(test_client, standard_user):
|
||||
"""Non-admin users should be blocked from accessing task APIs."""
|
||||
headers = standard_user["headers"]
|
||||
|
||||
list_response = await test_client.get("/api/tasks", headers=headers)
|
||||
assert list_response.status_code == 403
|
||||
|
||||
detail_response = await test_client.get("/api/tasks/some-task", headers=headers)
|
||||
assert detail_response.status_code == 403
|
||||
|
||||
cancel_response = await test_client.post("/api/tasks/some-task/cancel", headers=headers)
|
||||
assert cancel_response.status_code == 403
|
||||
|
||||
|
||||
async def test_admin_can_list_tasks(test_client, admin_headers):
|
||||
"""Admin should receive a well-formed task list payload."""
|
||||
response = await test_client.get("/api/tasks", headers=admin_headers)
|
||||
assert response.status_code == 200, response.text
|
||||
|
||||
payload = response.json()
|
||||
assert "tasks" in payload
|
||||
assert isinstance(payload["tasks"], list)
|
||||
assert "summary" in payload
|
||||
assert isinstance(payload["summary"], dict)
|
||||
|
||||
|
||||
async def test_cancel_unknown_task_returns_client_error(test_client, admin_headers):
|
||||
"""Cancelling a non-existent task should surface a 400 response."""
|
||||
response = await test_client.post("/api/tasks/not-real/cancel", headers=admin_headers)
|
||||
assert response.status_code == 400, response.text
|
||||
|
||||
|
||||
async def test_enqueue_document_creates_task(
|
||||
test_client,
|
||||
admin_headers,
|
||||
):
|
||||
"""Trigger knowledge ingestion to ensure a task record is materialised."""
|
||||
if _LITE_MODE:
|
||||
enqueue_response = await test_client.post(
|
||||
"/api/knowledge/databases/lite-mode-disabled/documents",
|
||||
json={"items": [], "params": {"content_type": "file"}},
|
||||
headers=admin_headers,
|
||||
)
|
||||
assert enqueue_response.status_code == 404
|
||||
return
|
||||
|
||||
create_response = await test_client.post(
|
||||
"/api/knowledge/databases",
|
||||
json={
|
||||
"database_name": f"pytest_task_router_{uuid.uuid4().hex[:8]}",
|
||||
"description": "Task router integration test",
|
||||
"embedding_model_spec": "siliconflow-cn:Pro/BAAI/bge-m3",
|
||||
"kb_type": "milvus",
|
||||
"additional_params": {},
|
||||
},
|
||||
headers=admin_headers,
|
||||
)
|
||||
assert create_response.status_code == 200, create_response.text
|
||||
kb_id = create_response.json()["kb_id"]
|
||||
|
||||
try:
|
||||
enqueue_response = await test_client.post(
|
||||
f"/api/knowledge/databases/{kb_id}/documents",
|
||||
json={
|
||||
"items": [],
|
||||
"params": {"content_type": "file"},
|
||||
},
|
||||
headers=admin_headers,
|
||||
)
|
||||
assert enqueue_response.status_code == 200, enqueue_response.text
|
||||
|
||||
enqueue_payload = enqueue_response.json()
|
||||
assert enqueue_payload.get("status") == "queued"
|
||||
task_id = enqueue_payload.get("task_id")
|
||||
assert task_id, "Knowledge ingestion did not return a task_id"
|
||||
|
||||
# The task should be queryable immediately after enqueueing.
|
||||
detail_response = await test_client.get(f"/api/tasks/{task_id}", headers=admin_headers)
|
||||
assert detail_response.status_code == 200, detail_response.text
|
||||
detail_payload = detail_response.json().get("task", {})
|
||||
assert detail_payload.get("id") == task_id
|
||||
assert detail_payload.get("status") in {"queued", "pending", "running", "failed", "success", "cancelled"}
|
||||
|
||||
# Ensure the task surfaces in the list endpoint within a short window.
|
||||
for _ in range(10):
|
||||
list_response = await test_client.get("/api/tasks", headers=admin_headers)
|
||||
assert list_response.status_code == 200, list_response.text
|
||||
all_tasks = list_response.json().get("tasks", [])
|
||||
if any(entry.get("id") == task_id for entry in all_tasks):
|
||||
break
|
||||
await asyncio.sleep(0.2)
|
||||
else:
|
||||
pytest.fail("Task did not appear in list endpoint within timeout window")
|
||||
|
||||
# Poll for terminal state to validate worker bookkeeping.
|
||||
for _ in range(20):
|
||||
detail_response = await test_client.get(f"/api/tasks/{task_id}", headers=admin_headers)
|
||||
task_status = detail_response.json().get("task", {}).get("status")
|
||||
if task_status in {"success", "failed", "cancelled"}:
|
||||
break
|
||||
await asyncio.sleep(0.5)
|
||||
else:
|
||||
pytest.fail("Task did not reach a terminal status within timeout window")
|
||||
finally:
|
||||
await test_client.delete(f"/api/knowledge/databases/{kb_id}", headers=admin_headers)
|
||||
Reference in New Issue
Block a user