Replaces the read-only 'NFO Diagnostics' page with a full per-anime
Settings page reached from the right-click context menu on series cards.
Users can now view and edit key, name, folder, tmdb_id, tvdb_id and site
for each anime; changes are persisted to the DB and optionally written
back to the NFO file or used to regenerate it.
Backend
- Rename NfoDiagnosticsResponse -> NfoSettingsResponse,
NfoSeriesDiagnostics -> NfoSeriesSettings
- Rename get_nfo_diagnostics -> get_nfo_settings,
repair_nfo -> repair_nfo_settings
- Fix nfo.py bug: repair was calling non-existent
update_series_nfo_status(); now uses update_nfo_status() and an
explicit AnimeSeriesService.update(nfo_path=...)
- New endpoints on /api/anime/{key}:
GET /settings -> AnimeSettingsResponse
PUT /settings -> AnimeSettingsResponse
(body: name/folder/tmdb_id/tvdb_id/site,
options: apply_to_nfo, rename_disk)
POST /regenerate-nfo -> AnimeSettingsRegenerateNfoResponse
- New Pydantic models: AnimeSettingsResponse,
AnimeSettingsUpdateRequest, AnimeSettingsRegenerateNfoResponse
- /anime/settings page route; /settings/nfo now 301-redirects to it
Frontend
- New AniWorld.AnimeSettingsManager JS module (single-page form,
no tabs) with public API init/loadSeries/saveSettings/regenerateNfo/
validateField/populateForm/showSaveSuccess/showError
- New anime-settings.html template + anime-settings.css
- Right-click menu: data-action 'nfo-diagnostics' replaced by
'anime-settings' (label 'Anime Settings'), navigates to
/anime/settings?key=...
- Library 'Open NFO Diagnostics' link renamed to 'Open Anime Settings'
Bug fix
- context-menu click handler was calling hide() BEFORE building the
navigation URL, which cleared currentSeriesKey to null and produced
/anime/settings?key=null. Captures the key into a local const first.
Regression-locked by tests/frontend/unit/context_menu.test.js.
Tests
- 21 new pytest tests in tests/api/test_anime_settings_endpoints.py
(GET/PUT/regenerate-nfo, auth, validation, nfo-repair bug regression)
- tests/api/test_nfo_endpoints.py trimmed to 6 focused tests
- 31 new Vitest unit tests for AnimeSettingsManager
- 5 new Vitest unit tests for ContextMenu (incl. source-invariant
regression guard for the hide()-before-key bug)
- 5 new Playwright E2E tests covering right-click, direct nav,
legacy /settings/nfo redirect, and context-menu labels
- New vitest.config.js (environment: happy-dom)
Docs
- Docs/API.md: new section 'Anime Settings Endpoints'
- Docs/CHANGELOG.md: documents the rename and the context-menu bug fix
Verified
- pytest: 27/27 (21 new + 6 trimmed nfo)
- vitest: 36/36 (31 anime-settings + 5 context-menu)
- playwright e2e: 5/5
API Endpoint Tests
This directory contains comprehensive integration tests for all FastAPI REST API endpoints in the Aniworld web application.
Test Files
1. test_auth_endpoints.py
Tests for authentication API endpoints (/api/auth/*):
- ✅ Master password setup flow
- ✅ Login with valid/invalid credentials
- ✅ Authentication status checking
- ✅ Token-based authentication
- ✅ Logout functionality
- ⚠️ Rate limiting behavior (some race conditions with trio backend)
Status: 1/2 tests passing (asyncio: ✅, trio: ⚠️ rate limiting)
2. test_anime_endpoints.py
Tests for anime management API endpoints (/api/v1/anime/*):
- ✅ List anime series with missing episodes
- ✅ Get anime series details
- ✅ Trigger rescan of local anime library
- ✅ Search for anime series
- ✅ Unauthorized access handling
- ✅ Direct function call tests
- ✅ HTTP endpoint integration tests
Status: 11/11 tests passing ✅
3. test_config_endpoints.py
Tests for configuration API endpoints (/api/config/*):
- ⚠️ Get current configuration
- ⚠️ Validate configuration
- ⚠️ Update configuration (authenticated)
- ⚠️ List configuration backups
- ⚠️ Create configuration backup
- ⚠️ Restore from backup
- ⚠️ Delete backup
- ⚠️ Configuration persistence
Status: 0/18 tests passing - needs authentication fixes
Issues:
- Config endpoints require authentication but tests need proper auth client fixture
- Mock config service may need better integration
4. test_download_endpoints.py
Tests for download queue API endpoints (/api/queue/*):
- ⚠️ Get queue status and statistics
- ⚠️ Add episodes to download queue
- ⚠️ Remove items from queue (single/multiple)
- ⚠️ Start/stop/pause/resume queue
- ⚠️ Reorder queue items
- ⚠️ Clear completed downloads
- ⚠️ Retry failed downloads
- ✅ Unauthorized access handling (2/2 tests passing)
Status: 2/36 tests passing - fixture dependency issues
Issues:
authenticated_clientfixture dependency onmock_download_servicecausing setup errors- Authentication rate limiting across test runs
- Need proper mocking of download service dependencies
Test Infrastructure
Fixtures
Common Fixtures
reset_auth_state: Auto-use fixture that clears rate limiting state between testsauthenticated_client: Creates async client with valid JWT tokenclient: Creates unauthenticated async client
Service-Specific Fixtures
mock_download_service: Mocks DownloadService for testing download endpointsmock_config_service: Mocks ConfigService with temporary config filestemp_config_dir: Provides temporary directory for config test isolation
Testing Patterns
Async/Await Pattern
All tests use pytest.mark.anyio decorator for async test support:
@pytest.mark.anyio
async def test_example(authenticated_client):
response = await authenticated_client.get("/api/endpoint")
assert response.status_code == 200
Authentication Testing
Tests use fixture-based authentication:
@pytest.fixture
async def authenticated_client():
"""Create authenticated async client."""
if not auth_service.is_configured():
auth_service.setup_master_password("TestPass123!")
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as client:
r = await client.post("/api/auth/login", json={"password": "TestPass123!"})
token = r.json()["access_token"]
client.headers["Authorization"] = f"Bearer {token}"
yield client
Service Mocking
External dependencies are mocked using unittest.mock:
@pytest.fixture
def mock_download_service():
"""Mock DownloadService for testing."""
with patch("src.server.utils.dependencies.get_download_service") as mock:
service = MagicMock()
service.get_queue_status = AsyncMock(return_value=QueueStatus(...))
mock.return_value = service
yield service
Running Tests
Run All API Tests
conda run -n AniWorld python -m pytest tests/api/ -v
Run Specific Test File
conda run -n AniWorld python -m pytest tests/api/test_auth_endpoints.py -v
Run Specific Test
conda run -n AniWorld python -m pytest tests/api/test_auth_endpoints.py::test_auth_flow_setup_login_status_logout -v
Run Only Asyncio Tests (Skip Trio)
conda run -n AniWorld python -m pytest tests/api/ -v -k "asyncio or not anyio"
Run with Detailed Output
conda run -n AniWorld python -m pytest tests/api/ -v --tb=short
Current Test Status
Summary
- Total Tests: 71
- Passing: 16 (22.5%)
- Failing: 19 (26.8%)
- Errors: 36 (50.7%)
By Category
- Anime Endpoints: 11/11 ✅ (100%)
- Auth Endpoints: 1/2 ✅ (50%) - trio race condition
- Config Endpoints: 0/18 ❌ (0%) - authentication issues
- Download Endpoints: 2/36 ⚠️ (5.6%) - fixture dependency issues
Known Issues
1. Rate Limiting Race Conditions
Symptom: Tests fail with 429 (Too Many Requests) when run with trio backend Solution:
- Fixed for asyncio by adding
reset_auth_statefixture - Trio still has timing issues with shared state
- Recommend running tests with asyncio only:
-k "asyncio or not anyio"
2. Download Service Fixture Dependencies
Symptom: authenticated_client fixture fails when it depends on mock_download_service
Error: assert 429 == 200 during login
Solution: Need to refactor fixture dependencies to avoid circular authentication issues
3. Config Endpoint Authentication
Symptom: Config endpoints return 404 or authentication errors Solution:
- ✅ Added config router to fastapi_app.py
- ⚠️ Still need to verify authentication requirements and update test fixtures
Improvements Needed
High Priority
- Fix Download Endpoint Tests: Resolve fixture dependency issues
- Fix Config Endpoint Tests: Ensure proper authentication in tests
- Resolve Trio Rate Limiting: Investigate shared state issues
Medium Priority
- Add More Edge Cases: Test boundary conditions and error scenarios
- Improve Test Coverage: Add tests for WebSocket endpoints
- Performance Tests: Add tests for high-load scenarios
Low Priority
- Test Documentation: Add more inline documentation
- Test Utilities: Create helper functions for common test patterns
- CI/CD Integration: Set up automated test runs
Contributing
When adding new API endpoint tests:
- Follow Existing Patterns: Use the same fixture and assertion patterns
- Test Both Success and Failure: Include positive and negative test cases
- Use Proper Fixtures: Leverage existing fixtures for authentication and mocking
- Document Test Purpose: Add clear docstrings explaining what each test validates
- Clean Up State: Use fixtures to ensure tests are isolated and don't affect each other