Fix async loading bugs and add test results
Critical Fixes:
- Fix async context manager usage in fastapi_app.py (async for -> async with)
- Add broadcast() method to WebSocketService
- Initialize BackgroundLoaderService properly in lifespan function
Testing:
- Execute manual testing (Tests 1, 5, 8, 9)
- Create comprehensive test results document
- Verify API endpoints return 202 Accepted
- Confirm database persistence works
- Validate startup incomplete series check
Test Results:
- Response time: 61ms (target: < 500ms) ✅
- 4 series found with missing data on startup
- Database fields properly persisted
- All critical bugs fixed
Files:
- check_db.py: Database inspection utility
- docs/MANUAL_TESTING_RESULTS.md: Comprehensive test results
- src/server/fastapi_app.py: Fixed async context manager, initialized BackgroundLoaderService
- src/server/services/websocket_service.py: Added broadcast() method
This commit is contained in:
@@ -5,15 +5,16 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
## Prerequisites
|
||||
|
||||
1. **Server Running**: Make sure the FastAPI server is running:
|
||||
```bash
|
||||
conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload
|
||||
```
|
||||
|
||||
```bash
|
||||
conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload
|
||||
```
|
||||
|
||||
2. **Browser**: Use a modern browser with developer tools (Chrome/Firefox recommended)
|
||||
|
||||
3. **Authentication**: You'll need to be logged in
|
||||
- Username: `admin`
|
||||
- Password: `Hallo123!`
|
||||
- Username: `admin`
|
||||
- Password: `Hallo123!`
|
||||
|
||||
## Test Scenarios
|
||||
|
||||
@@ -22,17 +23,19 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that series appear immediately in the UI when added, even while data loads in background.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Open browser to `http://127.0.0.1:8000`
|
||||
2. Log in with admin credentials
|
||||
3. Open browser DevTools (F12) → Network tab
|
||||
4. Add a new series via search or URL
|
||||
5. **Expected Results**:
|
||||
- API response returns quickly (< 500ms)
|
||||
- Response status code is `202 Accepted`
|
||||
- Series appears immediately in the series grid
|
||||
- Series card shows loading indicator
|
||||
- API response returns quickly (< 500ms)
|
||||
- Response status code is `202 Accepted`
|
||||
- Series appears immediately in the series grid
|
||||
- Series card shows loading indicator
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ Series visible within 1 second of submitting
|
||||
- ✅ Loading indicator present on series card
|
||||
- ✅ UI remains responsive
|
||||
@@ -42,11 +45,13 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that loading progress indicators display correctly.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. After adding a series (from Test 1), observe the series card
|
||||
2. Look for the loading indicator section
|
||||
3. Check the progress items display
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
- Loading indicator appears below series stats
|
||||
- Shows spinning icon with status message (e.g., "Loading episodes...")
|
||||
- Progress items show checkmarks (✓) for completed tasks
|
||||
@@ -54,6 +59,7 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
- Four progress items visible: Episodes, NFO, Logo, Images
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ Loading indicator visible
|
||||
- ✅ Status message updates as loading progresses
|
||||
- ✅ Progress items accurately reflect completion state
|
||||
@@ -64,21 +70,24 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that loading status updates in real-time via WebSocket.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Open browser DevTools → Network tab → WS (WebSocket filter)
|
||||
2. Ensure WebSocket connection is established
|
||||
3. Add a new series
|
||||
4. Monitor WebSocket messages
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
- WebSocket messages with type `series_loading_update` appear
|
||||
- Messages contain:
|
||||
- `series_id` or `series_key`
|
||||
- `status` (loading_episodes, loading_nfo, etc.)
|
||||
- `progress` object with boolean flags
|
||||
- `message` describing current operation
|
||||
- `series_id` or `series_key`
|
||||
- `status` (loading_episodes, loading_nfo, etc.)
|
||||
- `progress` object with boolean flags
|
||||
- `message` describing current operation
|
||||
- Series card updates automatically without page refresh
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ WebSocket messages received during loading
|
||||
- ✅ UI updates in real-time
|
||||
- ✅ No need to refresh page to see updates
|
||||
@@ -89,16 +98,19 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that loading completes successfully and UI updates accordingly.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Add a series and wait for loading to complete (may take 10-30 seconds)
|
||||
2. Observe the series card when loading finishes
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
- Loading indicator disappears when complete
|
||||
- All progress items show checkmarks
|
||||
- Series card no longer has "loading" class
|
||||
- Series data is fully populated (episodes, NFO, etc.)
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ Loading indicator removed upon completion
|
||||
- ✅ Series card shows complete data
|
||||
- ✅ No errors in browser console
|
||||
@@ -109,36 +121,41 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that application checks for incomplete series on startup.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Add a series (let it start loading)
|
||||
2. **Stop the server** while loading is in progress:
|
||||
```bash
|
||||
pkill -f "uvicorn.*fastapi_app"
|
||||
```
|
||||
```bash
|
||||
pkill -f "uvicorn.*fastapi_app"
|
||||
```
|
||||
3. Check the database to see incomplete series:
|
||||
```bash
|
||||
conda run -n AniWorld python -c "
|
||||
from src.server.database.service import get_db
|
||||
from src.server.database.models import AnimeSeries
|
||||
from sqlalchemy import select
|
||||
|
||||
db = next(get_db())
|
||||
series = db.execute(
|
||||
select(AnimeSeries).where(AnimeSeries.loading_status != 'completed')
|
||||
).scalars().all()
|
||||
|
||||
for s in series:
|
||||
print(f'{s.key}: {s.loading_status}')
|
||||
"
|
||||
```
|
||||
|
||||
```bash
|
||||
conda run -n AniWorld python -c "
|
||||
from src.server.database.service import get_db
|
||||
from src.server.database.models import AnimeSeries
|
||||
from sqlalchemy import select
|
||||
|
||||
db = next(get_db())
|
||||
series = db.execute(
|
||||
select(AnimeSeries).where(AnimeSeries.loading_status != 'completed')
|
||||
).scalars().all()
|
||||
|
||||
for s in series:
|
||||
print(f'{s.key}: {s.loading_status}')
|
||||
"
|
||||
```
|
||||
|
||||
4. **Restart the server**
|
||||
5. Check server logs for startup messages
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
- Server logs show: "Found X series with missing data. Starting background loading..."
|
||||
- Incomplete series are automatically queued for loading
|
||||
- Loading resumes for incomplete series
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ Startup logs mention incomplete series
|
||||
- ✅ Loading resumes automatically
|
||||
- ✅ Incomplete series complete successfully
|
||||
@@ -148,10 +165,12 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that multiple series can load concurrently without blocking.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Rapidly add 3-5 series (within a few seconds)
|
||||
2. Observe all series cards
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
- All series appear immediately in UI
|
||||
- All series show loading indicators
|
||||
- Loading progresses for multiple series simultaneously
|
||||
@@ -159,6 +178,7 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
- No series blocks others from loading
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ All series visible immediately
|
||||
- ✅ All series show loading indicators
|
||||
- ✅ No UI freezing or blocking
|
||||
@@ -169,18 +189,21 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that errors are handled gracefully.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. **Simulate an error scenario**:
|
||||
- Add a series with invalid URL
|
||||
- Or disconnect from internet during loading
|
||||
- Add a series with invalid URL
|
||||
- Or disconnect from internet during loading
|
||||
2. Observe the series card
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
- Series card updates to show error state
|
||||
- Loading status changes to "failed"
|
||||
- Error message is displayed
|
||||
- Other series continue loading normally
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ Error state visible in UI
|
||||
- ✅ Error doesn't crash application
|
||||
- ✅ Other series unaffected
|
||||
@@ -191,36 +214,40 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that loading status is properly persisted to database.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Add a series
|
||||
2. While loading, check database directly:
|
||||
```bash
|
||||
conda run -n AniWorld python -c "
|
||||
from src.server.database.service import get_db
|
||||
from src.server.database.models import AnimeSeries
|
||||
from sqlalchemy import select
|
||||
|
||||
db = next(get_db())
|
||||
series = db.execute(select(AnimeSeries)).scalars().all()
|
||||
|
||||
for s in series:
|
||||
print(f'{s.name}:')
|
||||
print(f' Status: {s.loading_status}')
|
||||
print(f' Episodes: {s.episodes_loaded}')
|
||||
print(f' NFO: {s.nfo_loaded}')
|
||||
print(f' Logo: {s.logo_loaded}')
|
||||
print(f' Images: {s.images_loaded}')
|
||||
print(f' Started: {s.loading_started_at}')
|
||||
print()
|
||||
"
|
||||
```
|
||||
|
||||
```bash
|
||||
conda run -n AniWorld python -c "
|
||||
from src.server.database.service import get_db
|
||||
from src.server.database.models import AnimeSeries
|
||||
from sqlalchemy import select
|
||||
|
||||
db = next(get_db())
|
||||
series = db.execute(select(AnimeSeries)).scalars().all()
|
||||
|
||||
for s in series:
|
||||
print(f'{s.name}:')
|
||||
print(f' Status: {s.loading_status}')
|
||||
print(f' Episodes: {s.episodes_loaded}')
|
||||
print(f' NFO: {s.nfo_loaded}')
|
||||
print(f' Logo: {s.logo_loaded}')
|
||||
print(f' Images: {s.images_loaded}')
|
||||
print(f' Started: {s.loading_started_at}')
|
||||
print()
|
||||
"
|
||||
```
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
- Database shows loading_status field
|
||||
- Boolean flags (episodes_loaded, nfo_loaded, etc.) update as loading progresses
|
||||
- loading_started_at timestamp is set
|
||||
- loading_completed_at is set when done
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ All new fields present in database
|
||||
- ✅ Values update during loading
|
||||
- ✅ Timestamps accurately reflect start/completion
|
||||
@@ -230,29 +257,34 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that new API endpoints work correctly.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Use curl or Postman to test endpoints directly:
|
||||
|
||||
**Add Series (returns 202)**:
|
||||
```bash
|
||||
curl -X POST "http://127.0.0.1:8000/api/anime/add" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-d '{"url": "https://aniworld.to/anime/stream/test-series"}'
|
||||
```
|
||||
**Add Series (returns 202)**:
|
||||
|
||||
**Get Loading Status**:
|
||||
```bash
|
||||
curl "http://127.0.0.1:8000/api/anime/SERIES_KEY/loading-status" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
```
|
||||
```bash
|
||||
curl -X POST "http://127.0.0.1:8000/api/anime/add" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-d '{"url": "https://aniworld.to/anime/stream/test-series"}'
|
||||
```
|
||||
|
||||
**Get Loading Status**:
|
||||
|
||||
```bash
|
||||
curl "http://127.0.0.1:8000/api/anime/SERIES_KEY/loading-status" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
```
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
- POST returns 202 Accepted
|
||||
- Response includes loading_status field
|
||||
- GET loading-status returns detailed status object
|
||||
- Status object includes progress breakdown
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ POST returns 202 status code
|
||||
- ✅ Response format matches documentation
|
||||
- ✅ GET endpoint returns current status
|
||||
@@ -263,11 +295,13 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
**Objective**: Verify that loading indicators are properly styled.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Add a series with loading indicator visible
|
||||
2. Inspect the series card with browser DevTools
|
||||
3. Check CSS classes applied
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
- `.loading-indicator` class present
|
||||
- `.loading-status` shows flex layout
|
||||
- `.progress-items` displays horizontally with gap
|
||||
@@ -276,6 +310,7 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
- Spinner icon animates
|
||||
|
||||
**Pass Criteria**:
|
||||
|
||||
- ✅ Loading indicator styled correctly
|
||||
- ✅ Colors match theme
|
||||
- ✅ Layout is responsive
|
||||
@@ -286,11 +321,13 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
### Issue: Loading indicator doesn't appear
|
||||
|
||||
**Possible Causes**:
|
||||
|
||||
- JavaScript error in console
|
||||
- WebSocket not connected
|
||||
- CSS not loaded
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. Check browser console for errors
|
||||
2. Verify WebSocket connection in Network tab
|
||||
3. Hard refresh page (Ctrl+Shift+R)
|
||||
@@ -298,11 +335,13 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
### Issue: Loading never completes
|
||||
|
||||
**Possible Causes**:
|
||||
|
||||
- Backend service error
|
||||
- External API unavailable (TMDB, Aniworld)
|
||||
- Network timeout
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. Check server logs for errors
|
||||
2. Verify external services are accessible
|
||||
3. Check database for error in loading_error field
|
||||
@@ -310,11 +349,13 @@ This guide provides step-by-step instructions for manually testing the asynchron
|
||||
### Issue: WebSocket updates not working
|
||||
|
||||
**Possible Causes**:
|
||||
|
||||
- WebSocket connection failed
|
||||
- Event handler not registered
|
||||
- Browser console shows errors
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. Check WebSocket connection status in DevTools
|
||||
2. Verify `series_loading_update` event handler exists
|
||||
3. Check for JavaScript errors
|
||||
@@ -341,25 +382,26 @@ After completing all tests, verify:
|
||||
|
||||
Record these metrics during testing:
|
||||
|
||||
| Metric | Target | Actual | Pass/Fail |
|
||||
|--------|--------|--------|-----------|
|
||||
| Series add response time | < 500ms | | |
|
||||
| UI update latency | < 100ms | | |
|
||||
| WebSocket message latency | < 100ms | | |
|
||||
| Complete loading time | < 30s | | |
|
||||
| Concurrent series handling | 5+ | | |
|
||||
| Memory usage increase | < 100MB | | |
|
||||
| No UI blocking | Yes | | |
|
||||
| Metric | Target | Actual | Pass/Fail |
|
||||
| -------------------------- | ------- | ------ | --------- |
|
||||
| Series add response time | < 500ms | | |
|
||||
| UI update latency | < 100ms | | |
|
||||
| WebSocket message latency | < 100ms | | |
|
||||
| Complete loading time | < 30s | | |
|
||||
| Concurrent series handling | 5+ | | |
|
||||
| Memory usage increase | < 100MB | | |
|
||||
| No UI blocking | Yes | | |
|
||||
|
||||
## Test Results Summary
|
||||
|
||||
**Date**: _________________
|
||||
**Date**: ********\_********
|
||||
|
||||
**Tester**: _________________
|
||||
**Tester**: ********\_********
|
||||
|
||||
**Pass/Fail**: _________________
|
||||
**Pass/Fail**: ********\_********
|
||||
|
||||
**Notes**:
|
||||
|
||||
```
|
||||
(Add any observations, issues found, or additional notes here)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user