# Testing Guide - Job Info Application ## Phase 8: End-to-End Testing This guide covers comprehensive testing of the Job Info application including OAuth2 flow, token management, error handling, and offline capabilities. --- ## 1. Environment Setup ### Prerequisites - Bun runtime installed - Node.js 18+ (for development) - Two terminals ready (one for backend, one for frontend) - Microsoft OAuth app registered (credentials in `.env`) ### Configuration Files ``` Mode3Test/.env - Backend OAuth credentials frontend/.env.local - Frontend environment variables ``` ### Start Services **Terminal 1 - Backend (Hono + OAuth)** ```bash cd /home/admin/Job-Info-Test/Mode3Test bun install # if needed bun run dev # Starts on http://localhost:3005 ``` **Terminal 2 - Frontend (Vite + Svelte)** ```bash cd /home/admin/Job-Info-Test/frontend bun install # if needed bun run dev # Starts on http://localhost:5173 ``` --- ## 2. OAuth2 Flow Testing ### Test 2.1: Sign In Flow **Objective**: Verify complete OAuth2 PKCE flow with Microsoft **Steps**: 1. Navigate to http://localhost:5173/#/signin 2. Click "Sign In with Microsoft" 3. Verify redirect to Microsoft login 4. Enter Microsoft credentials 5. Grant permissions on consent screen 6. Verify redirect back to http://localhost:5173/#/callback 7. Verify redirect to http://localhost:5173/#/ (home) **Expected Results**: - ✅ User profile displayed in navigation (name, avatar) - ✅ Jobs list loaded and displayed - ✅ No console errors - ✅ Access token stored in sessionStorage - ✅ User profile stored in IndexedDB **Validation Commands** (in browser console): ```javascript // Check sessionStorage sessionStorage.getItem('access_token'); // Should return token string // Check IndexedDB const db = await window.openDatabase(); const user = await db.getFromStore('userProfile'); console.log(user); // Should show user data // Check store values window.store?.subscribe(v => console.log('Auth:', v)); ``` --- ### Test 2.2: PKCE Code Verification **Objective**: Verify PKCE security flow **Tools**: Browser DevTools Network tab **Steps**: 1. Open DevTools → Network tab 2. Click "Sign In with Microsoft" 3. Check the request to `/api/auth/authorize` 4. Verify request body contains: - `code` - Authorization code from Microsoft - `code_verifier` - PKCE code verifier - `state` - CSRF token (should match state from redirect) **Expected Results**: - ✅ Request uses POST method - ✅ Request includes CORS headers - ✅ Response contains `access_token`, `expires_in`, `user` - ✅ Status code 200 OK --- ## 3. Token Management Testing ### Test 3.1: Token Storage Security **Objective**: Verify tokens stored securely **Steps**: 1. After sign in, check browser storage: - Open DevTools → Application → Cookies - Open DevTools → Application → Local Storage - Open DevTools → Application → Session Storage **Expected Results**: - ✅ `access_token` in sessionStorage (NOT localStorage) - ✅ No tokens in cookies - ✅ No tokens in localStorage - ✅ Token expires in ~1 hour (check `token_expiry`) **Why This Matters**: - SessionStorage lost on browser close (prevents token theft) - Can't be accessed by XSS attacks in other tabs - Service Worker has separate access for refresh --- ### Test 3.2: Token Refresh **Objective**: Verify Service Worker automatically refreshes token **Steps**: 1. Sign in successfully 2. Wait 55+ seconds (Service Worker polls every 60 seconds) 3. Check DevTools → Application → Service Workers 4. Verify Service Worker status shows "activated" 5. Monitor Console for refresh logs **Expected Results**: - ✅ Service Worker shows "activated and running" - ✅ No manual action needed - ✅ Can continue using app without re-login - ✅ Token refreshes 5 minutes before expiry **Debug Commands**: ```javascript // Check Service Worker registration navigator.serviceWorker.getRegistrations().then(regs => { regs.forEach(reg => console.log('SW:', reg.scope, reg.active?.state)); }); // Send refresh command to Service Worker if (navigator.serviceWorker.controller) { navigator.serviceWorker.controller.postMessage({ type: 'REFRESH_TOKEN' }); } ``` --- ## 4. API Error Handling Testing ### Test 4.1: Network Error Handling **Objective**: Verify graceful handling of network failures **Steps**: 1. Sign in successfully 2. Open DevTools → Network tab 3. Check "Offline" checkbox (simulates no network) 4. Try to perform action (search, load jobs) 5. Verify error message displayed 6. Uncheck "Offline" 7. Verify app recovers automatically **Expected Results**: - ✅ Error message shown: "Network error - please check your connection" - ✅ Retry button appears - ✅ App recovers when network restored - ✅ No unhandled exceptions in console - ✅ Error logged to structured logger --- ### Test 4.2: API Error Responses **Objective**: Verify handling of HTTP error responses **Steps**: 1. Use DevTools → Network → Throttle to simulate slow network 2. Open DevTools → Network → Response headers 3. Modify response (requires proxy like Charles/Fiddler): - Change 200 to 401 (Unauthorized) - Change 200 to 403 (Forbidden) - Change 200 to 500 (Server Error) **Expected Results** (per error type): **401 Unauthorized**: - ✅ "Session expired" message shown - ✅ Redirect to sign in page - ✅ Error logged with context **403 Forbidden**: - ✅ "You don't have permission" message shown - ✅ Retry option disabled - ✅ Contact admin message shown **500 Server Error**: - ✅ "Server error" message shown - ✅ Retry button enabled - ✅ Auto-retry happens 2-3 times --- ### Test 4.3: Request Timeout **Objective**: Verify timeout handling **Steps**: 1. Use DevTools → Network → Throttle to "Slow 3G" 2. Trigger API call (load jobs) 3. Wait for 30+ seconds **Expected Results**: - ✅ Request times out after 30 seconds - ✅ Error message: "Request timeout - please try again" - ✅ Retry automatically attempted - ✅ No hung requests in Network tab --- ## 5. Data Storage Testing ### Test 5.1: IndexedDB Jobs Cache **Objective**: Verify jobs cached locally **Steps**: 1. Sign in and load jobs 2. Open DevTools → Application → IndexedDB → job-info-db 3. Check `jobs` object store 4. Sign out 5. Go back to sign in page 6. Turn off network ("Offline" in DevTools) 7. Sign in again (offline) 8. Check if previous jobs available **Expected Results**: - ✅ Jobs loaded from IndexedDB when offline - ✅ Jobs display without network - ✅ Database shows ~50-100 jobs - ✅ Each job has: id, title, description, location, salary --- ### Test 5.2: Cache Invalidation **Objective**: Verify old data cleaned up **Steps**: 1. Sign in and load jobs 2. Note timestamp in IndexedDB 3. Wait 1 hour (or modify cache expiry in constants) 4. Refresh page 5. Check if cache refreshed from API **Expected Results**: - ✅ Fresh jobs fetched from API - ✅ Cache timestamp updated - ✅ Stale data not used - ✅ No cache inconsistencies --- ## 6. UI Component Testing ### Test 6.1: Responsive Design **Objectives**: Verify layout works on all screen sizes **Steps**: 1. Open DevTools → Responsive Design Mode 2. Test on: - Mobile (375px - iPhone SE) - Tablet (768px - iPad) - Desktop (1920px - 4K) 3. Verify: - Navigation stays accessible - Job list responsive - Search bar functional - No horizontal scroll **Expected Results**: - ✅ All sizes readable and usable - ✅ TailwindCSS classes applied correctly - ✅ Touch targets ≥ 44x44 pixels on mobile - ✅ No overflow or layout shifts --- ### Test 6.2: Error Boundary Display **Objective**: Verify error UI works **Steps**: 1. Sign in 2. Open DevTools → Console 3. Manually throw error in component: ```javascript throw new Error('Test error for ErrorBoundary'); ``` 4. Verify error displayed gracefully **Expected Results**: - ✅ Error Boundary component displays - ✅ User-friendly message shown - ✅ Development details (stack) available - ✅ Recovery suggestions shown - ✅ Retry button works --- ## 7. Logging & Debugging ### Test 7.1: Structured Logging **Objective**: Verify comprehensive logging **Steps**: 1. Sign in 2. Load jobs 3. Perform search 4. Open DevTools → Console 5. Check for log messages with format: ``` [module] message {context} ``` **Expected Log Entries**: - `[OAuth] Token refreshed successfully` - `[API] GET /api/graph/me - 200` - `[Jobs] Loaded X jobs from cache` - `[Search] Searching for: term` --- ### Test 7.2: Log Export **Objective**: Verify log export for debugging **Steps**: 1. Sign in and perform actions 2. In Console, run: ```javascript window.logger.exportLogs(); ``` 3. Check Downloads folder 4. Verify JSON file contains: - Timestamps - Log levels - Module names - Context data **Expected Results**: - ✅ JSON file downloads - ✅ Contains 100+ log entries - ✅ Properly formatted - ✅ Includes error context --- ## 8. Performance Testing ### Test 8.1: Build Size **Objective**: Verify production build is optimized **Command**: ```bash cd /home/admin/Job-Info-Test/frontend bun run build ``` **Expected Results**: - ✅ Total JS: < 50 kB (gzip) - ✅ CSS: < 5 kB (gzip) - ✅ HTML: < 1 kB - ✅ Build time: < 5 seconds **Current Metrics**: ``` JS: 42.56 kB (gzip) CSS: 3.96 kB (gzip) HTML: 0.32 kB Build: 2.68s Modules: 51 ``` --- ### Test 8.2: Load Time **Objective**: Verify fast initial load **Steps**: 1. Clear browser cache 2. Open DevTools → Network tab 3. Navigate to http://localhost:5173 4. Check timing breakdown: - Time to First Byte (TTFB) - First Contentful Paint (FCP) - Largest Contentful Paint (LCP) **Expected Results**: - ✅ TTFB: < 100ms - ✅ FCP: < 1s - ✅ LCP: < 2.5s (Core Web Vitals target) - ✅ Total load: < 3s --- ## 9. Security Testing ### Test 9.1: XSS Protection **Objective**: Verify no XSS vulnerabilities **Steps**: 1. Try to inject script in search: ``` ``` 2. Check if alert fires (it shouldn't) 3. Check rendered HTML 4. Verify script treated as text **Expected Results**: - ✅ No alert shown - ✅ Input rendered as plain text - ✅ Script tags escaped - ✅ Content Security Policy working --- ### Test 9.2: CSRF Protection **Objective**: Verify CSRF token handling **Steps**: 1. In Network tab, check requests to backend 2. Verify state parameter in OAuth flow 3. Check CORS headers are set correctly 4. Try to call API from different origin (if possible) **Expected Results**: - ✅ State token matches request/response - ✅ CORS prevents cross-origin requests - ✅ SameSite cookie policy enforced - ✅ No state token reuse --- ## 10. Accessibility Testing ### Test 10.1: Keyboard Navigation **Steps**: 1. Sign in to app 2. Press Tab repeatedly 3. Navigate through: - Navigation menu - Search input - Job list items - Buttons 4. Verify focus visible on all elements 5. Press Enter on buttons to activate 6. Verify Esc closes modals **Expected Results**: - ✅ All interactive elements reachable via keyboard - ✅ Focus indicator clearly visible - ✅ Tab order logical - ✅ Enter activates buttons - ✅ Esc closes overlays --- ### Test 10.2: Screen Reader **Steps**: 1. Enable screen reader: - macOS: Cmd+F5 (VoiceOver) - Windows: Windows+Enter (Narrator) - Linux: NVDA (free) 2. Navigate through app 3. Check that: - Page title announced - Headings identified - Links have labels - Form inputs have labels - Errors announced **Expected Results**: - ✅ Navigation menu announced correctly - ✅ Page sections identified - ✅ Buttons have accessible labels - ✅ Form inputs labeled - ✅ Errors announced to screen reader --- ## 11. Regression Testing Checklist Use this checklist before each release: ### Authentication - [ ] Sign in flow completes successfully - [ ] Token stored securely in sessionStorage - [ ] User profile displayed in navigation - [ ] Sign out clears auth state - [ ] Protected pages redirect to sign in when logged out ### Data Loading - [ ] Jobs list loads on home page - [ ] Search filters jobs correctly - [ ] Pagination works (if implemented) - [ ] Job details display when clicked - [ ] Loading state shows spinner ### Error Handling - [ ] Network errors show user message - [ ] API errors handled gracefully - [ ] No unhandled exceptions in console - [ ] Error recovery buttons work - [ ] Errors logged with context ### Token Refresh - [ ] Service Worker registers successfully - [ ] Token refreshes before expiry - [ ] App continues working after refresh - [ ] No authentication prompts during normal use ### UI/UX - [ ] Navigation responsive on all sizes - [ ] Colors have sufficient contrast - [ ] Font sizes readable on mobile - [ ] Buttons easily tappable (44x44px min) - [ ] Forms accessible via keyboard ### Performance - [ ] Build size within limits - [ ] No console errors or warnings - [ ] Page loads in < 3 seconds - [ ] Interactions respond immediately - [ ] No memory leaks (check DevTools) --- ## 12. Known Limitations & Workarounds ### Issue 1: Token Expiry During Long Session **Symptom**: Suddenly get 401 errors after 1 hour **Cause**: Token expires, Service Worker refresh fails **Workaround**: Service Worker auto-refreshes at 55 min mark (before 1hr expiry) **Fix**: Already implemented in Service Worker ### Issue 2: IndexedDB Not Available **Symptom**: Jobs don't persist offline **Cause**: Incognito/Private mode disables IndexedDB **Workaround**: Use normal browser mode **Fix**: Graceful fallback to in-memory cache (already implemented) ### Issue 3: CORS Errors **Symptom**: "CORS policy: No 'Access-Control-Allow-Origin'" **Cause**: API doesn't allow requests from localhost:5173 **Fix**: Ensure vite.config.ts has correct proxy: ```typescript proxy: { '/api': 'http://localhost:3005' } ``` --- ## 13. Testing Automation ### Unit Test Example (Optional - Future) ```typescript import { describe, it, expect } from 'bun:test'; import { classifyError } from '../services/errorHandler'; describe('errorHandler', () => { it('should classify network error', () => { const error = new Error('Network error'); const classified = classifyError(error); expect(classified.type).toBe('network'); }); it('should classify auth error', () => { const error = new Error('401 Unauthorized'); const classified = classifyError(error); expect(classified.type).toBe('auth'); }); }); ``` --- ## 14. Test Results Template **Date**: ___________ **Tester**: ___________ **Environment**: - Browser: ___________ - OS: ___________ - Build: ___________ **Test Results**: - [ ] OAuth2 Flow: PASS / FAIL - [ ] Token Management: PASS / FAIL - [ ] Error Handling: PASS / FAIL - [ ] Data Storage: PASS / FAIL - [ ] UI Components: PASS / FAIL - [ ] Performance: PASS / FAIL - [ ] Accessibility: PASS / FAIL **Issues Found**: 1. ___________ 2. ___________ 3. ___________ **Notes**: ___________________________________________ --- ## Summary This testing guide ensures comprehensive validation of: ✅ OAuth2 security flow ✅ Token management and refresh ✅ Error handling and recovery ✅ Data persistence ✅ UI/UX across devices ✅ Performance benchmarks ✅ Accessibility compliance ✅ Security best practices **Next Steps**: 1. Execute tests in order (sections 2-7) 2. Document any failures 3. Fix issues using logger insights 4. Re-run failed tests 5. Move to deployment when all pass