8.6 KiB
Logout Tracking System - Testing Checklist
Purpose: Verify the logout tracking system works correctly for all scenarios
Pre-Testing Setup
- Backend container restarted
- Frontend container restarted
- Browser DevTools console open
- Backend logs accessible (
docker logs -f igny8_backend)
Test 1: Manual Logout
Steps:
- Login to the app
- Navigate to any page (e.g.,
/dashboard) - Click the logout button
Expected Results:
- Console shows:
🚪 LOGOUT - User Action: - Redirected to
/signin - Yellow alert box appears on signin page
- Alert shows: "User manually logged out"
- Original page shown in alert:
/dashboard - Click ℹ️ icon shows technical details
- Technical details show:
- Code:
MANUAL_LOGOUT - Source:
manual_user_action - Path:
/dashboard(or whatever page you were on) - User email in context
- Timestamp
- Code:
- After refresh, alert is gone (single display)
Test 2: Token Expiration (401)
Steps:
- Login to the app
- Get the access token from localStorage
- In browser console, manually expire it:
localStorage.setItem('access_token', 'invalid_token') - Navigate to a protected page or make an API call
Expected Results:
- Console shows:
🚨 LOGOUT TRIGGERED - Token Refresh Failedor🚨 LOGOUT TRIGGERED - No Refresh Token - Redirected to
/signin - Yellow alert box appears
- Alert shows token-related message
- Original page shown in alert
- Technical details show correct error code
Test 3: Session Contamination (Account Mismatch)
Steps:
- Login with a user account
- In Django admin or shell, create session contamination:
# Get a session and modify _account_id to wrong value from django.contrib.sessions.models import Session session = Session.objects.first() data = session.get_decoded() data['_account_id'] = 99999 # Non-existent account session.session_data = session.encode(data) session.save() - Refresh the app or make an API call
Expected Results:
- Backend logs show:
[AUTO-LOGOUT] SESSION_ACCOUNT_MISMATCH - Console shows:
🚨 LOGOUT TRIGGERED - Backend Validation Failed - Redirected to
/signin - Yellow alert shows: "Session contamination: account ID mismatch"
- Technical details show:
- Code:
SESSION_ACCOUNT_MISMATCH - Source:
backend_middleware - Context: stored vs current account IDs
- Code:
- Backend logs include IP, path, user ID, timestamp
Test 4: Missing Account
Steps:
- In Django admin, remove account from a user:
user = User.objects.get(email='test@example.com') user.account = None user.save() - Try to login with that user
Expected Results:
- Backend logs show:
[AUTO-LOGOUT] ACCOUNT_MISSING - Console shows:
🚨 LOGOUT TRIGGERED - Alert shows: "Account not configured for this user"
- Technical details show:
- Code:
ACCOUNT_MISSING - Source:
backend_middlewareorrefresh_user_validation
- Code:
Test 5: Inactive Plan
Steps:
- In Django admin, deactivate user's plan:
plan = Plan.objects.get(slug='starter') plan.is_active = False plan.save() - User makes an API call or refreshes page
Expected Results:
- Backend logs show:
[AUTO-LOGOUT] PLAN_INACTIVE - Console shows:
🚨 LOGOUT TRIGGERED - Alert shows: "Subscription plan is inactive"
- Technical details show:
- Code:
PLAN_INACTIVE - HTTP status 402 in context
- Code:
Test 6: Suspended Account
Steps:
- In Django admin, suspend an account:
account = Account.objects.get(id=1) account.status = 'suspended' account.save() - User tries to access protected page
Expected Results:
- Backend logs show:
[AUTO-LOGOUT] ACCOUNT_SUSPENDED - Alert shows: "Account is suspended"
- Technical details show:
- Code:
ACCOUNT_SUSPENDED - HTTP status 403
- Code:
Test 7: 403 Auth Credentials Error
Steps:
- Login to the app
- In browser console, corrupt the token:
localStorage.setItem('access_token', 'Bearer corrupted') - Make an API call
Expected Results:
- Console shows:
🚨 LOGOUT TRIGGERED - Authentication Credentials Missing - Alert shows authentication credentials error
- Technical details show:
- Code:
AUTH_CREDENTIALS_MISSING - Source:
api_403_auth_error
- Code:
Test 8: Page Path Accuracy
Steps:
- Login and navigate through multiple pages
- Trigger logout from different pages:
- From
/dashboard→ Check logout shows/dashboard - From
/planner/keywords→ Check logout shows/planner/keywords - From
/writer/articles→ Check logout shows/writer/articles
- From
Expected Results:
- Every logout shows exact page where logout occurred
- Never shows
/signinas logout path - Path captured BEFORE redirect
Test 9: Console Logging Format
Expected in Browser Console:
- 🚨 emoji for automatic logouts
- 🚪 emoji for manual logout
- Grouped logs with expandable details
- Full JSON context logged
- Timestamps present
- Error codes visible
Expected in Backend Logs:
[AUTO-LOGOUT] ERROR_CODE: Message. User=123, Account=456, Path=/page, IP=..., Timestamp=...
[AUTO-LOGOUT]prefix present- Error code included
- All context fields present
- Grep-friendly format
Test 10: Alert Box UI
Visual Checks:
- Yellow background (not red)
- Clear heading: "Session Ended"
- User-friendly message displayed
- Original page path shown (if not /signin)
- Info icon (ℹ️) present
- Click info icon expands technical details
- Technical details show:
- Error code
- Source
- Timestamp (formatted)
- Context JSON (formatted with indentation)
- Click info icon again collapses details
- Alert disappears after page refresh
Test 11: Multiple Logouts
Steps:
- Trigger logout (any method)
- See alert on signin page
- Login again
- Trigger different logout (different error)
- Return to signin page
Expected Results:
- First logout reason cleared after first display
- Second logout shows new reason (not old one)
- No accumulation of old logout reasons
- Each logout tracked separately
Test 12: Edge Cases
No Logout Reason
Steps: Navigate directly to /signin without logout
Expected:
- No alert box shown
- No console errors
- No localStorage pollution
localStorage Disabled
Steps: Disable localStorage in browser, trigger logout
Expected:
- Console warning about failed storage
- App still functions
- No crash
Malformed Logout Reason
Steps: Manually corrupt logout_reason in localStorage
localStorage.setItem('logout_reason', 'invalid json')
Expected:
- Console warning about parsing failure
- No alert shown
- No crash
Test 13: Cross-Browser Testing
Test in multiple browsers:
- Chrome
- Firefox
- Safari
- Edge
All features should work identically
Test 14: Mobile Responsiveness
Test on mobile devices/emulator:
- Alert box displays correctly
- Technical details expand/collapse works
- Text is readable
- No horizontal scroll
Success Criteria
✅ All tests pass
✅ Every logout has visible reason
✅ Exact page tracking works
✅ Console logs are clear
✅ Backend logs are searchable
✅ User sees helpful message
✅ Developers can debug easily
Troubleshooting
Alert not showing
- Check browser console for logout reason object
- Check if localStorage.getItem('logout_reason') returns data
- Verify SignInForm component mounted
Wrong page shown
- Verify
window.location.pathnamecaptured BEFORE redirect - Check logout trigger happens before navigation
- Ensure logout_reason stored BEFORE logout() call
Backend logs missing
- Check logger level is WARNING or INFO
- Verify logger name: 'auth.middleware'
- Check LOGGING config in settings.py
Console logs missing
- Check browser console filters (show all levels)
- Verify emoji not filtered out
- Check if code throwing before log statement
Maintenance
When adding new logout causes:
- Add error code to
LOGOUT_REASONSdict - Update logout trigger to create structured reason
- Store in localStorage before logout
- Log to console with 🚨
- Update this testing checklist
- Update LOGOUT-CAUSES-COMPLETE-REFERENCE.md
Keep documentation in sync with implementation!