fix tests

This commit is contained in:
2025-10-22 07:44:24 +02:00
parent 71841645cf
commit 3e50ec0149
5 changed files with 206 additions and 158 deletions

View File

@@ -5,10 +5,10 @@ including adding episodes, removing items, controlling queue processing, and
retrieving queue status and statistics.
"""
from fastapi import APIRouter, Depends, HTTPException, Path, status
from fastapi.responses import JSONResponse
from src.server.models.download import (
DownloadRequest,
DownloadResponse,
QueueOperationRequest,
QueueReorderRequest,
QueueStatusResponse,
@@ -44,7 +44,30 @@ async def get_queue_status(
queue_status = await download_service.get_queue_status()
queue_stats = await download_service.get_queue_stats()
return QueueStatusResponse(status=queue_status, statistics=queue_stats)
# Provide a legacy-shaped status payload expected by older clients
# and integration tests. Map internal model fields to the older keys.
status_payload = {
"is_running": queue_status.is_running,
"is_paused": queue_status.is_paused,
"active": [it.model_dump(mode="json") for it in queue_status.active_downloads],
"pending": [it.model_dump(mode="json") for it in queue_status.pending_queue],
"completed": [it.model_dump(mode="json") for it in queue_status.completed_downloads],
"failed": [it.model_dump(mode="json") for it in queue_status.failed_downloads],
}
# Add success_rate to statistics for backward compatibility
completed = queue_stats.completed_count
failed = queue_stats.failed_count
success_rate = None
if (completed + failed) > 0:
success_rate = completed / (completed + failed)
stats_payload = queue_stats.model_dump(mode="json")
stats_payload["success_rate"] = success_rate
return JSONResponse(
content={"status": status_payload, "statistics": stats_payload}
)
except Exception as e:
raise HTTPException(
@@ -53,11 +76,7 @@ async def get_queue_status(
)
@router.post(
"/add",
response_model=DownloadResponse,
status_code=status.HTTP_201_CREATED,
)
@router.post("/add", status_code=status.HTTP_201_CREATED)
async def add_to_queue(
request: DownloadRequest,
_: dict = Depends(require_auth),
@@ -98,12 +117,18 @@ async def add_to_queue(
priority=request.priority,
)
return DownloadResponse(
status="success",
message=f"Added {len(added_ids)} episode(s) to download queue",
added_items=added_ids,
failed_items=[],
)
# Keep a backwards-compatible response shape and return it as a
# raw JSONResponse so FastAPI won't coerce it based on any
# response_model defined elsewhere.
payload = {
"status": "success",
"message": f"Added {len(added_ids)} episode(s) to download queue",
"added_items": added_ids,
"item_ids": added_ids,
"failed_items": [],
}
return JSONResponse(content=payload, status_code=status.HTTP_201_CREATED)
except DownloadServiceError as e:
raise HTTPException(
@@ -378,9 +403,55 @@ async def resume_queue(
)
# Backwards-compatible control endpoints (some integration tests and older
# clients call `/api/queue/control/<action>`). These simply proxy to the
# existing handlers above to avoid duplicating service logic.
@router.post("/control/start", status_code=status.HTTP_200_OK)
async def control_start(
_: dict = Depends(require_auth),
download_service: DownloadService = Depends(get_download_service),
):
return await start_queue(_, download_service)
@router.post("/control/stop", status_code=status.HTTP_200_OK)
async def control_stop(
_: dict = Depends(require_auth),
download_service: DownloadService = Depends(get_download_service),
):
return await stop_queue(_, download_service)
@router.post("/control/pause", status_code=status.HTTP_200_OK)
async def control_pause(
_: dict = Depends(require_auth),
download_service: DownloadService = Depends(get_download_service),
):
return await pause_queue(_, download_service)
@router.post("/control/resume", status_code=status.HTTP_200_OK)
async def control_resume(
_: dict = Depends(require_auth),
download_service: DownloadService = Depends(get_download_service),
):
return await resume_queue(_, download_service)
@router.post("/control/clear_completed", status_code=status.HTTP_200_OK)
async def control_clear_completed(
_: dict = Depends(require_auth),
download_service: DownloadService = Depends(get_download_service),
):
# Call the existing clear_completed implementation which returns a dict
return await clear_completed(_, download_service)
@router.post("/reorder", status_code=status.HTTP_200_OK)
async def reorder_queue(
request: QueueReorderRequest,
request: dict,
_: dict = Depends(require_auth),
download_service: DownloadService = Depends(get_download_service),
):
@@ -403,15 +474,43 @@ async def reorder_queue(
400 for invalid request, 500 on service error
"""
try:
success = await download_service.reorder_queue(
item_id=request.item_id,
new_position=request.new_position,
)
# Support legacy bulk reorder payload used by some integration tests:
# {"item_order": ["id1", "id2", ...]}
if "item_order" in request:
item_order = request.get("item_order", [])
if not isinstance(item_order, list):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="item_order must be a list of item IDs",
)
success = await download_service.reorder_queue_bulk(item_order)
else:
# Fallback to single-item reorder shape
# Validate request
try:
req = QueueReorderRequest(**request)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=str(e),
)
success = await download_service.reorder_queue(
item_id=req.item_id,
new_position=req.new_position,
)
if not success:
# Provide an appropriate 404 message depending on request shape
if "item_order" in request:
detail = "One or more items in item_order were not found in pending queue"
else:
detail = f"Item {req.item_id} not found in pending queue"
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Item {request.item_id} not found in pending queue",
detail=detail,
)
return {