afterEach (()</font> ⇒ server . resetHandlers ()) ;
afterAll (()</font> ⇒ server . close ()) ; ==== Integration Test ==== src/tests/integration/InventoryPage.test.tsx</font>
import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import InventoryPage from '@/pages/Inventory/InventoryPage';
it('renders inventory data from API', async () ⇒ {
render(<InventoryPage />);
await waitFor(() ⇒ {</font>
expect(screen.getByText('Item A')).toBeInTheDocument();
});
});
===== 10. Final Recommendation =====
|
Choice
|
|
Vite
|
|
Vitest
|
|
MSW
|
|
RTL
|
|
Playwright
|
|
Shared Token
|
===== 11. API Client with Token Interceptor ===== Centralized API client ensures consistent auth handling, easy mocking, and reuse across Unit, Integration, and E2E tests. CKGE_TMP_i src/services/apiClient.ts CKGE_TMP_i</font>
import axios from 'axios' ;
const apiClient = axios . create ({
baseURL : import . meta . env . VITE_API_BASE_URL ,
}) ;
apiClient . interceptors . request . use ((config)</font> ⇒ {
const token = sessionStorage . getItem ( 'auth_token' ) ;
if (token) {
config . headers . Authorization = `Bearer ${ token } ` ;
}
return config ;
}) ;
export default apiClient ; CKGE_TMP_i src/services/inventoryService.ts CKGE_TMP_i</font>
import apiClient from './apiClient' ;
export const fetchInventory = async () ⇒ {
const response = await apiClient . get ( '/inventory' ) ;
return response . data ;
} ; —- ===== 12. Playwright Global Auth + Hybrid MSW E2E ===== ==== Global Authentication Setup ==== CKGE_TMP_i e2e/playwright/global-setup.ts CKGE_TMP_i</font>
import { chromium } from '@playwright/test' ;
export default async () ⇒ {
const browser = await chromium . launch () ;
const page = await browser . newPage () ;
await page . goto ( process . env . AUTH_URL ! ) ;
await page . fill ( '#username' , process . env . E2E_USER ! ) ;
await page . fill ( '#password' , process . env . E2E_PASSWORD ! ) ;
await page . click ( 'button[type=submit]' ) ;
await page . waitForURL ( '/home'</font> ) ;
await page . context () . storageState ({ path : 'e2e/auth.json' }) ;
await browser . close () ;
} ; CKGE_TMP_i e2e/playwright.config.ts CKGE_TMP_i</font>
import { defineConfig } from '@playwright/test' ;
export default defineConfig ({
globalSetup : './e2e/playwright/global-setup.ts' ,
use : {
storageState : 'e2e/auth.json' ,
} ,
}) ; ==== Hybrid E2E Test ==== CKGE_TMP_i e2e/inventory.hybrid.spec.ts CKGE_TMP_i</font>
import { test , expect } from '@playwright/test' ;
test ( 'inventory loads with mocked API' , async ({ page }) ⇒ {
await page . route ( '**/api/inventory' , async (route) ⇒ {
await route . fulfill ({
status : 200 ,
contentType : 'application/json' ,
body : JSON . stringify ([{ id : 1 , name : 'Mock Item' }]) ,
}) ;
}) ;
await page . goto ( '/inventory' ) ;
await expect (page . getByText ( 'Mock Item' )) . toBeVisible () ;
}) ; —- ===== 13. CI/CD Pipeline Snippets ===== ==== GitHub Actions ==== CKGE_TMP_i # .github/workflows/frontend-ci.yml CKGE_TMP_i
name : Frontend CI
on : [ push , pull_request ]
jobs :
test :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v3
- uses : actions/setup-node@v3
with :
node-version : 18
- run : npm ci
- run : npm run test:unit
- run : npm run test:integration
- run : npx playwright install –with-deps
- run : npm run test:e2e ==== GitLab CI ==== frontend_tests :
image : node:18
stage : test
script :
- npm ci
- npm run test:unit
- npm run test:integration
- npx playwright install –with-deps
- npm run test:e2e
artifacts :
when : always
paths :
- playwright-report/ —- ===== 14. Token Refresh & Expiry Handling ===== ==== Design Principles ==== * Never refresh tokens inside UI components * Centralize refresh logic in API client * Retry failed requests transparently CKGE_TMP_i src/services/apiClient.ts (extended) CKGE_TMP_i</font>
import axios from 'axios' ;
let isRefreshing = false ;
let queue : any [] = [] ;
const apiClient = axios . create ({
baseURL : import . meta . env . VITE_API_BASE_URL ,
}) ;
apiClient . interceptors . response . use (
(res) ⇒ res ,
async (error) ⇒ {
const originalRequest = error . config ;
if (error . response ?. status === 401 && ! originalRequest . _retry ) {
if (isRefreshing) {
return new Promise ((resolve)</font> ⇒ queue . push (resolve)) ;
}
originalRequest . _retry = true ;
isRefreshing = true ;
const refreshToken = sessionStorage . getItem ( 'refresh_token' ) ;
const response = await axios . post ( '/auth/refresh' , { refreshToken }) ;
sessionStorage . setItem ( 'auth_token' , response . data . accessToken ) ;
queue . forEach ((cb)</font> ⇒ cb ()) ;
queue = [] ;
isRefreshing = false ;
return apiClient (originalRequest) ;
}
return Promise . reject (error) ;
}
) ;
export default apiClient ;
===== 15. API Contract Versioning Strategy ===== ==== Versioning Rules ====
rest . get ( '/api/v1/inventory' , (req , res , ctx) ⇒ {
return res (ctx . json ([{ id : 1 , name : 'Item V1' }])) ;
}) ;
rest . get ( '/api/v2/inventory' , (req , res , ctx) ⇒ {
return res (ctx . json ([{ id : 1 , name : 'Item V2' , stock : 100 }])) ;
}) ; —- ===== 16. Performance Testing (Lighthouse + Playwright) ===== ==== Lighthouse CI ==== npm install -D @lhci/cli </font> lighthouserc.json
{
“ci” : {
“collect” : {
“url” : [ “http://localhost:5173” ] ,
“startServerCommand” : “npm run preview”
},
“assert” : {
“assertions” : {
“categories:performance” : [ “warn” , { “minScore” : 0.8 } ]
}
}
}
} ==== Playwright Performance Smoke ==== CKGE_TMP_i e2e/performance.spec.ts CKGE_TMP_i</font>
import { test } from '@playwright/test' ;
test ( 'home page loads under 2s' , async ({ page }) ⇒ {
const start = Date . now () ;
await page . goto ( '/' ) ;
const duration = Date . now () - start ;
expect (duration) . toBeLessThan ( 2000 ) ;
}) ; —- ===== 17. Starter Vite Repository Blueprint ===== ==== Scripts ==== {
“scripts” : {
“dev” : “vite” ,
“build” : “vite build” ,
“preview” : “vite preview” ,
“test:unit” : “vitest” ,
“test:integration” : “vitest run” ,
“test:e2e” : “playwright test” ,
“perf” : “lhci autorun”
}
} ==== Environment Files ==== .env
.env.test
.env.e2e ==== Ready-to-Use ==== * Vite + React + TS * Vitest + MSW * Playwright (auth + hybrid) * CI/CD ready * Performance gates included —-
