15 KiB
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)
cd /home/admin/Job-Info-Test/Mode3Test
bun install # if needed
bun run dev # Starts on http://localhost:3005
Terminal 2 - Frontend (Vite + Svelte)
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:
- Navigate to http://localhost:5173/#/signin
- Click "Sign In with Microsoft"
- Verify redirect to Microsoft login
- Enter Microsoft credentials
- Grant permissions on consent screen
- Verify redirect back to http://localhost:5173/#/callback
- 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):
// 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:
- Open DevTools → Network tab
- Click "Sign In with Microsoft"
- Check the request to
/api/auth/authorize - Verify request body contains:
code- Authorization code from Microsoftcode_verifier- PKCE code verifierstate- 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:
- After sign in, check browser storage:
- Open DevTools → Application → Cookies
- Open DevTools → Application → Local Storage
- Open DevTools → Application → Session Storage
Expected Results:
- ✅
access_tokenin 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:
- Sign in successfully
- Wait 55+ seconds (Service Worker polls every 60 seconds)
- Check DevTools → Application → Service Workers
- Verify Service Worker status shows "activated"
- 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:
// 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:
- Sign in successfully
- Open DevTools → Network tab
- Check "Offline" checkbox (simulates no network)
- Try to perform action (search, load jobs)
- Verify error message displayed
- Uncheck "Offline"
- 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:
- Use DevTools → Network → Throttle to simulate slow network
- Open DevTools → Network → Response headers
- 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:
- Use DevTools → Network → Throttle to "Slow 3G"
- Trigger API call (load jobs)
- 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:
- Sign in and load jobs
- Open DevTools → Application → IndexedDB → job-info-db
- Check
jobsobject store - Sign out
- Go back to sign in page
- Turn off network ("Offline" in DevTools)
- Sign in again (offline)
- 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:
- Sign in and load jobs
- Note timestamp in IndexedDB
- Wait 1 hour (or modify cache expiry in constants)
- Refresh page
- 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:
- Open DevTools → Responsive Design Mode
- Test on:
- Mobile (375px - iPhone SE)
- Tablet (768px - iPad)
- Desktop (1920px - 4K)
- 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:
- Sign in
- Open DevTools → Console
- Manually throw error in component:
throw new Error('Test error for ErrorBoundary');
- 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:
- Sign in
- Load jobs
- Perform search
- Open DevTools → Console
- 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:
- Sign in and perform actions
- In Console, run:
window.logger.exportLogs();
- Check Downloads folder
- 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:
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:
- Clear browser cache
- Open DevTools → Network tab
- Navigate to http://localhost:5173
- 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:
- Try to inject script in search:
<script>alert('XSS')</script>
- Check if alert fires (it shouldn't)
- Check rendered HTML
- 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:
- In Network tab, check requests to backend
- Verify state parameter in OAuth flow
- Check CORS headers are set correctly
- 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:
- Sign in to app
- Press Tab repeatedly
- Navigate through:
- Navigation menu
- Search input
- Job list items
- Buttons
- Verify focus visible on all elements
- Press Enter on buttons to activate
- 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:
- Enable screen reader:
- macOS: Cmd+F5 (VoiceOver)
- Windows: Windows+Enter (Narrator)
- Linux: NVDA (free)
- Navigate through app
- 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:
proxy: {
'/api': 'http://localhost:3005'
}
13. Testing Automation
Unit Test Example (Optional - Future)
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:
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:
- Execute tests in order (sections 2-7)
- Document any failures
- Fix issues using logger insights
- Re-run failed tests
- Move to deployment when all pass