fix: Implement /api/anime/add endpoint correctly
- Fixed 501 Not Implemented error by replacing non-existent AddSeries method - Added Serie import from src.core.entities.series - Implemented proper series creation using Serie class following CLI pattern - Added input validation for empty link and name fields - Series are now correctly added to series_app.List using add() method - Call refresh_series_list() to update cache after adding Tests: - Added test for unauthorized access (401) - Added test for successful addition with authentication (200) - Added test for empty name validation (400) - Added test for empty link validation (400) - Updated FakeSeriesApp mock to support add() and refresh_series_list() All tests passing.
This commit is contained in:
parent
02764f7e6f
commit
adfbdf56d0
@ -3,6 +3,7 @@ from typing import Any, List, Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from src.core.entities.series import Serie
|
||||
from src.server.utils.dependencies import (
|
||||
get_optional_series_app,
|
||||
get_series_app,
|
||||
@ -540,24 +541,50 @@ async def add_series(
|
||||
HTTPException: If adding the series fails
|
||||
"""
|
||||
try:
|
||||
if not hasattr(series_app, "AddSeries"):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
||||
detail="Add series functionality not available",
|
||||
)
|
||||
|
||||
result = series_app.AddSeries(request.link, request.name)
|
||||
|
||||
if result:
|
||||
return {
|
||||
"status": "success",
|
||||
"message": f"Successfully added series: {request.name}"
|
||||
}
|
||||
else:
|
||||
# Validate inputs
|
||||
if not request.link or not request.link.strip():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Failed to add series - series may already exist",
|
||||
detail="Series link cannot be empty",
|
||||
)
|
||||
|
||||
if not request.name or not request.name.strip():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Series name cannot be empty",
|
||||
)
|
||||
|
||||
# Check if series_app has the List attribute
|
||||
if not hasattr(series_app, "List"):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
||||
detail="Series list functionality not available",
|
||||
)
|
||||
|
||||
# Create a new Serie object
|
||||
# Following the pattern from CLI:
|
||||
# Serie(key, name, site, folder, episodeDict)
|
||||
# The key and folder are both the link in this case
|
||||
# episodeDict is empty {} for a new series
|
||||
serie = Serie(
|
||||
key=request.link.strip(),
|
||||
name=request.name.strip(),
|
||||
site="aniworld.to",
|
||||
folder=request.name.strip(),
|
||||
episodeDict={}
|
||||
)
|
||||
|
||||
# Add the series to the list
|
||||
series_app.List.add(serie)
|
||||
|
||||
# Refresh the series list to update the cache
|
||||
if hasattr(series_app, "refresh_series_list"):
|
||||
series_app.refresh_series_list()
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"message": f"Successfully added series: {request.name}"
|
||||
}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as exc:
|
||||
|
||||
@ -43,6 +43,16 @@ class FakeSeriesApp:
|
||||
"""Trigger rescan with callback."""
|
||||
callback()
|
||||
|
||||
def add(self, serie):
|
||||
"""Add a serie to the list."""
|
||||
# Check if already exists
|
||||
if not any(s.key == serie.key for s in self._items):
|
||||
self._items.append(serie)
|
||||
|
||||
def refresh_series_list(self):
|
||||
"""Refresh series list."""
|
||||
pass
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def reset_auth_state():
|
||||
@ -144,3 +154,61 @@ async def test_get_anime_detail_endpoint_unauthorized():
|
||||
response = await client.get("/api/v1/anime/1")
|
||||
# Should work or require auth
|
||||
assert response.status_code in (200, 401, 404, 503)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_series_endpoint_unauthorized():
|
||||
"""Test POST /api/anime/add without authentication."""
|
||||
transport = ASGITransport(app=app)
|
||||
async with AsyncClient(transport=transport, base_url="http://test") as client:
|
||||
response = await client.post(
|
||||
"/api/anime/add",
|
||||
json={"link": "test-link", "name": "Test Anime"}
|
||||
)
|
||||
# Should require auth
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_series_endpoint_authenticated(authenticated_client):
|
||||
"""Test POST /api/anime/add with authentication."""
|
||||
response = await authenticated_client.post(
|
||||
"/api/anime/add",
|
||||
json={"link": "test-anime-link", "name": "Test New Anime"}
|
||||
)
|
||||
|
||||
# The endpoint should succeed (returns 200 or may fail if series exists)
|
||||
assert response.status_code in (200, 400)
|
||||
data = response.json()
|
||||
|
||||
if response.status_code == 200:
|
||||
assert data["status"] == "success"
|
||||
assert "Test New Anime" in data["message"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_series_endpoint_empty_name(authenticated_client):
|
||||
"""Test POST /api/anime/add with empty name."""
|
||||
response = await authenticated_client.post(
|
||||
"/api/anime/add",
|
||||
json={"link": "test-link", "name": ""}
|
||||
)
|
||||
|
||||
# Should return 400 for empty name
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
assert "name" in data["detail"].lower()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_series_endpoint_empty_link(authenticated_client):
|
||||
"""Test POST /api/anime/add with empty link."""
|
||||
response = await authenticated_client.post(
|
||||
"/api/anime/add",
|
||||
json={"link": "", "name": "Test Anime"}
|
||||
)
|
||||
|
||||
# Should return 400 for empty link
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
assert "link" in data["detail"].lower()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user