Files
Job-Info/TESTING_GUIDE.md
T
aewing 42ff3e8f33
Build & Deploy / Test & Lint (push) Has been cancelled
Build & Deploy / Security Scan (push) Has been cancelled
Code Quality / Code Quality Checks (push) Has been cancelled
Code Quality / Dependency Vulnerabilities (push) Has been cancelled
Code Quality / Performance Testing (push) Has been cancelled
Build & Deploy / Build Docker Images (push) Has been cancelled
Build & Deploy / Deploy to Kubernetes (push) Has been cancelled
Add Mode6Test: copy of Mode5Test running on port 3000
2026-01-20 13:43:29 +00:00

656 lines
15 KiB
Markdown

# 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:
```
<script>alert('XSS')</script>
```
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