| |
| react [2025/12/30 11:10] – created pradnya | react [2025/12/30 11:10] (current) – Imported from DOCX pradnya |
|---|
| ====== Vite + Vitest Testing Strategy for React SPA ====== | ====== Vite + Vitest Testing Strategy for React SPA ====== |
| |
| ===== | ===== 1. Context & Goals ===== |
| <font 16pt/inherit;;#0f4761;;inherit>1. Context & Goals</font> ===== | |
| |
| This document defines **best practices for testing a React SPA built with Vite**. The application is UI-focused, API-driven, and optimized for fast rendering of large datasets (inventory-style screens). | This document defines **best practices for testing a React SPA built with Vite**. The application is UI-focused, API-driven, and optimized for fast rendering of large datasets (inventory-style screens). |
| |
| ==== | ==== Goals ==== |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Goals</font> ==== | |
| |
| * | Align testing with the Vite build ecosystem |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Align testing with the Vite build ecosystem</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Ensure fast, reliable, and deterministic tests</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Enable **auth token reuse** across Unit, Integration, and E2E tests</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Support CI/CD quality gates</font> | |
| |
| ---- | Ensure fast, reliable, and deterministic tests |
| |
| ===== 3. Recommended Testing Stack ===== | Enable **auth token reuse** across Unit, Integration, and E2E tests |
| <font 11pt/Consolas;;inherit;;inherit>React + TypeScript + Vite</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── Unit Tests → Vitest + React Testing Library</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── Integration Tests → Vitest + RTL + MSW</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── API Contract → MSW</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── Hybrid E2E → Playwright + MSW</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>└── Full E2E → Playwright (real backend)</font> | |
| |
| ---- | Support CI/CD quality gates |
| |
| ===== 4. Test Classification & Scope ===== | ===== 3. Recommended Testing Stack ===== |
| |
| ==== | React + TypeScript + Vite\\ │\\ ├── Unit Tests → Vitest + React Testing Library\\ ├── Integration Tests → Vitest + RTL + MSW\\ ├── API Contract → MSW\\ ├── Hybrid E2E → Playwright + MSW\\ └── Full E2E → Playwright (real backend) |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Example Code Snippets (Vite + Vitest + React)</font> ==== | |
| |
| === 4.0.1 Main App & Layout Wiring === | ===== 4. Test Classification & Scope ===== |
| <font 11pt/Consolas;;inherit;;inherit>// src/app/App.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { BrowserRouter } from 'react-router-dom';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import RoutesConfig from './routes';</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>export default function App() {</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>return (</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><BrowserRouter></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><RoutesConfig /></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit></BrowserRouter></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>);</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>}</font> | |
| <font 11pt/Consolas;;inherit;;inherit>// src/layouts/MainLayout/MainLayout.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { Outlet } from 'react-router-dom';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { Header } from '@/components/layout/Header';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { Footer } from '@/components/layout/Footer';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { Menu } from '@/components/layout/Navigation';</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>export const MainLayout = () => (</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><Header /></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><Menu /></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><main></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><Outlet /></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit></main></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><Footer /></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit></></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>);</font> | |
| <font 11pt/Consolas;;inherit;;inherit>// src/app/routes.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { Routes, Route } from 'react-router-dom';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { MainLayout } from '@/layouts/MainLayout';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import HomePage from '@/pages/Home/HomePage';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import InventoryPage from '@/pages/Inventory/InventoryPage';</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>export default function RoutesConfig() {</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>return (</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><Routes></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><Route element={<MainLayout />}></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><Route path="/" element={<HomePage />} /></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit><Route path="/inventory" element={<InventoryPage />} /></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit></Route></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit></Routes></font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>);</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>}</font> | |
| |
| ---- | ==== Example Code Snippets (Vite + Vitest + React) ==== |
| |
| ===== 4. Test Classification & Scope ===== | === 4.0.1 Main App & Layout Wiring === |
| |
| ==== | // src/app/App.tsx\\ import { BrowserRouter } from 'react-router-dom';\\ import RoutesConfig from './routes';\\ \\ export default function App() {\\ return (\\ <BrowserRouter>\\ <RoutesConfig />\\ </BrowserRouter>\\ );\\ } |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>4.1 Unit Tests</font> ==== | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**Purpose:** Validate isolated UI logic</font> | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**What to test** - Presentational components - Hooks - Utility functions</font> | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**What NOT to test** - API calls - Auth flows</font> | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**Tools** - Vitest - React Testing Library</font> | |
| |
| ---- | // src/layouts/MainLayout/MainLayout.tsx\\ import { Outlet } from 'react-router-dom';\\ import { Header } from '@/components/layout/Header';\\ import { Footer } from '@/components/layout/Footer';\\ import { Menu } from '@/components/layout/Navigation';\\ \\ export const MainLayout = () => (\\ <>\\ <Header />\\ <Menu />\\ <main>\\ <Outlet />\\ </main>\\ <Footer />\\ </>\\ ); |
| |
| ==== 4.2 Integration Tests ==== | // src/app/routes.tsx\\ import { Routes, Route } from 'react-router-dom';\\ import { MainLayout } from '@/layouts/MainLayout';\\ import HomePage from '@/pages/Home/HomePage';\\ import InventoryPage from '@/pages/Inventory/InventoryPage';\\ \\ export default function RoutesConfig() {\\ return (\\ <Routes>\\ <Route element={<MainLayout />}>\\ <Route path="/" element={<HomePage />} />\\ <Route path="/inventory" element={<InventoryPage />} />\\ </Route>\\ </Routes>\\ );\\ } |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**Purpose:** Validate UI + API interaction</font> | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**What to test** - API data rendering - Error states - Token attached to requests</font> | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**Tools** - Vitest - RTL - MSW (Mock Service Worker)</font> | |
| |
| ---- | ===== 4. Test Classification & Scope ===== |
| |
| ==== 4.3 API Contract Tests (via MSW) ==== | ==== 4.1 Unit Tests ==== |
| |
| * | **Purpose:** Validate isolated UI logic |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Validate request headers, query params, payloads</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Ensure frontend-backend contract stability</font> | |
| |
| ---- | **What to test** - Presentational components - Hooks - Utility functions |
| |
| ==== 4.4 Hybrid E2E Tests ==== | **What NOT to test** - API calls - Auth flows |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**Purpose:** Fast, stable E2E without backend dependency</font> | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**Characteristics** - Real browser (Playwright) - Real authentication token - Business APIs mocked via MSW</font> | |
| |
| ---- | **Tools** - Vitest - React Testing Library |
| |
| ==== 4.5 Full E2E Tests ==== | ==== 4.2 Integration Tests ==== |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**Purpose:** Validate critical production flows</font> | |
| |
| * | **Purpose:** Validate UI + API interaction |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Real backend</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Real authentication</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Minimal coverage (smoke tests only)</font> | |
| |
| ---- | **What to test** - API data rendering - Error states - Token attached to requests |
| |
| ===== 5. Authentication Token Strategy (Single Source of Truth) ===== | **Tools** - Vitest - RTL - MSW (Mock Service Worker) |
| |
| ==== | ==== 4.3 API Contract Tests (via MSW) ==== |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Design Principles</font> ==== | |
| |
| * | Validate request headers, query params, payloads |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Fetch auth token **once**</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Reuse across all test layers</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>No hardcoding inside tests</font> | |
| |
| ==== Flow ==== | Ensure frontend-backend contract stability |
| <font 11pt/Consolas;;inherit;;inherit>Auth Token</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├─ Generated via Playwright global setup</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├─ Stored in env / storageState</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├─ Consumed by MSW handlers</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>└─ Used by Vitest integration tests</font> | |
| |
| ==== Benefits ==== | ==== 4.4 Hybrid E2E Tests ==== |
| |
| * | **Purpose:** Fast, stable E2E without backend dependency |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Consistent auth behavior</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Faster test execution</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Reduced flakiness</font> | |
| |
| ---- | **Characteristics** - Real browser (Playwright) - Real authentication token - Business APIs mocked via MSW |
| |
| ===== 6. Project Directory Structure ===== | ==== 4.5 Full E2E Tests ==== |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>The following directory structure is the **recommended standard** for this React + TypeScript + Vite SPA. It cleanly separates **app bootstrapping**, **layouts**, **pages**, **features**, **services**, and **tests**, and scales well for large inventory-style applications.</font> | |
| <font 11pt/Consolas;;inherit;;inherit>src/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── app/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── App.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── routes.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── providers.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── layouts/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── MainLayout/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── MainLayout.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── index.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── components/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── layout/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ ├── Header/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ │ ├── Header.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ │ └── index.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ ├── Footer/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ │ ├── Footer.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ │ └── index.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ └── Navigation/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ ├── Menu.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ └── index.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── common/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── Button/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── Input/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── Loader/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── Modal/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── pages/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── Home/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ ├── HomePage.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ └── index.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── Inventory/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ ├── InventoryPage.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ ├── InventoryTable.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │ └── index.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ │</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── NotFound/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── NotFoundPage.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── features/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── inventory/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── components/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── hooks/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── services/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── types.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── services/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── apiClient.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── inventoryService.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── hooks/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── useDebounce.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── types/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── common.types.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── utils/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── formatters.ts</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── styles/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── global.css</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── tests/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── unit/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ ├── integration/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│ └── msw/</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>│</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>├── main.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>└── vite-env.d.ts</font> | |
| |
| ==== Structural Guidelines ==== | **Purpose:** Validate critical production flows |
| |
| * | Real backend |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**app/** – Application bootstrap, routing, and providers</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**layouts/** – Shared page layouts (Header, Footer, Navigation)</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**components/** – Reusable UI components</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**pages/** – Route-level components</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**features/** – Feature-scoped logic for scalability</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**services/** – API and backend interaction layer</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>**tests/** – Unit, integration, and MSW setup</font> | |
| |
| ---- | Real authentication |
| |
| ===== 7. CI/CD Best Practices ===== | Minimal coverage (smoke tests only) |
| |
| ==== | ===== 5. Authentication Token Strategy (Single Source of Truth) ===== |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Pipeline Order</font> ==== | |
| |
| - | ==== Design Principles ==== |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Lint + Type Check</font> | |
| - | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Unit Tests (Vitest)</font> | |
| - | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Integration Tests (Vitest + MSW)</font> | |
| - | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Hybrid E2E (Playwright)</font> | |
| - | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Optional Full E2E (nightly)</font> | |
| |
| ==== Failure Handling ==== | Fetch auth token **once** |
| |
| * | Reuse across all test layers |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Fail pipeline on any test failure</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Upload Playwright traces/screenshots</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Publish test reports</font> | |
| |
| ---- | No hardcoding inside tests |
| |
| ===== 8. Performance Considerations ===== | ==== Flow ==== |
| |
| * | Auth Token\\ │\\ ├─ Generated via Playwright global setup\\ ├─ Stored in env / storageState\\ ├─ Consumed by MSW handlers\\ └─ Used by Vitest integration tests |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Prefer **client-side rendering (SPA)**</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Use virtualization for large datasets</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Avoid SSR unless SEO is required</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Testing should not depend on real backend performance</font> | |
| |
| ---- | ==== Benefits ==== |
| |
| ===== 10. Tooling Configuration (Vitest + RTL) ===== | Consistent auth behavior |
| |
| ==== | Faster test execution |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Vitest Configuration</font> ==== | |
| |
| CKGE_TMP_i // vitest.config.ts CKGE_TMP_i \\ import { defineConfig } from 'vitest/config' ; \\ import react from '@vitejs/plugin-react' ; \\ \\ export default defineConfig ({ \\ plugins : [ react ()] , \\ test : { \\ environment : 'jsdom' , \\ setupFiles : './src/tests/setupTests.ts' , \\ globals : true , \\ css : true , \\ coverage : { \\ reporter : [ 'text' , 'html' ] , \\ } , \\ } , \\ }) ; | Reduced flakiness |
| |
| ==== | ===== 6. Project Directory Structure ===== |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Test Setup</font> ==== | |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // src/tests/setupTests.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'@testing-library/jest-dom'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| |
| ---- | The following directory structure is the **recommended standard** for this React + TypeScript + Vite SPA. It cleanly separates **app bootstrapping**, **layouts**, **pages**, **features**, **services**, and **tests**, and scales well for large inventory-style applications. |
| |
| ===== 11. Unit Test Example (Vitest + RTL) ===== | src/\\ ├── app/\\ │ ├── App.tsx\\ │ ├── routes.tsx\\ │ └── providers.tsx\\ │\\ ├── layouts/\\ │ └── MainLayout/\\ │ ├── MainLayout.tsx\\ │ └── index.ts\\ │\\ ├── components/\\ │ ├── layout/\\ │ │ ├── Header/\\ │ │ │ ├── Header.tsx\\ │ │ │ └── index.ts\\ │ │ ├── Footer/\\ │ │ │ ├── Footer.tsx\\ │ │ │ └── index.ts\\ │ │ └── Navigation/\\ │ │ ├── Menu.tsx\\ │ │ └── index.ts\\ │ │\\ │ └── common/\\ │ ├── Button/\\ │ ├── Input/\\ │ ├── Loader/\\ │ └── Modal/\\ │\\ ├── pages/\\ │ ├── Home/\\ │ │ ├── HomePage.tsx\\ │ │ └── index.ts\\ │ │\\ │ ├── Inventory/\\ │ │ ├── InventoryPage.tsx\\ │ │ ├── InventoryTable.tsx\\ │ │ └── index.ts\\ │ │\\ │ └── NotFound/\\ │ └── NotFoundPage.tsx\\ │\\ ├── features/\\ │ └── inventory/\\ │ ├── components/\\ │ ├── hooks/\\ │ ├── services/\\ │ └── types.ts\\ │\\ ├── services/\\ │ ├── apiClient.ts\\ │ └── inventoryService.ts\\ │\\ ├── hooks/\\ │ └── useDebounce.ts\\ │\\ ├── types/\\ │ └── common.types.ts\\ │\\ ├── utils/\\ │ └── formatters.ts\\ │\\ ├── styles/\\ │ └── global.css\\ │\\ ├── tests/\\ │ ├── unit/\\ │ ├── integration/\\ │ └── msw/\\ │\\ ├── main.tsx\\ └── vite-env.d.ts |
| <font 11pt/Consolas;;inherit;;inherit>// src/tests/unit/Header.test.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { render, screen } from '@testing-library/react';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { describe, it, expect } from 'vitest';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { Header } from '@/components/layout/Header';</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>describe('Header', () => {</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>it('renders application title', () => {</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>render(<Header />);</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>expect(screen.getByText(/inventory/i)).toBeInTheDocument();</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>});</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>});</font> | |
| |
| ---- | ==== Structural Guidelines ==== |
| |
| ===== 12. Integration Test Example (Vitest + RTL + MSW) ===== | **app/** – Application bootstrap, routing, and providers |
| |
| ==== | **layouts/** – Shared page layouts (Header, Footer, Navigation) |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>MSW Handler</font> ==== | |
| |
| CKGE_TMP_i // src/tests/msw/handlers.ts CKGE_TMP_i \\ import { rest } from 'msw' ; \\ \\ export const handlers = [ \\ rest . get ( '/api/inventory' , (req , res , ctx) => { \\ const token = req . headers . get ( 'Authorization' ) ; \\ if ( ! token) return res (ctx . status ( 401 )) ; \\ \\ return res ( \\ ctx . status ( 200 ) , \\ ctx . json ([{ id : 1 , name : 'Item A' }]) \\ ) ; \\ }) , \\ ] ; | **components/** – Reusable UI components |
| |
| ==== | **pages/** – Route-level components |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>MSW Server Setup</font> ==== | |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // src/tests/msw/server.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>{ setupServer }</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'msw/node'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>{ handlers }</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'./handlers'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;green;;inherit>export</font> | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>server</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#06287e;;inherit>setupServer</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#666666;;inherit>...</font> | |
| <font inherit/Consolas;;inherit;;inherit>handlers)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // src/tests/setupTests.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'@testing-library/jest-dom'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>{ server }</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'./msw/server'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#06287e;;inherit>beforeAll</font> | |
| <font inherit/Consolas;;inherit;;inherit>(()</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>server</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>listen</font> | |
| <font inherit/Consolas;;inherit;;inherit>())</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>afterEach</font> | |
| <font inherit/Consolas;;inherit;;inherit>(()</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>server</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>resetHandlers</font> | |
| <font inherit/Consolas;;inherit;;inherit>())</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>afterAll</font> | |
| <font inherit/Consolas;;inherit;;inherit>(()</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>server</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>close</font> | |
| <font inherit/Consolas;;inherit;;inherit>())</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| |
| ==== Integration Test ==== | **features/** – Feature-scoped logic for scalability |
| <font 11pt/Consolas;;inherit;;inherit>// src/tests/integration/InventoryPage.test.tsx</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { render, screen, waitFor } from '@testing-library/react';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import { describe, it, expect } from 'vitest';</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>import InventoryPage from '@/pages/Inventory/InventoryPage';</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>it('renders inventory data from API', async () => {</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>render(<InventoryPage />);</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>await waitFor(() => {</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>expect(screen.getByText('Item A')).toBeInTheDocument();</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>});</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>});</font> | |
| |
| ---- | **services/** – API and backend interaction layer |
| |
| ===== 10. Final Recommendation ===== | **tests/** – Unit, integration, and MSW setup |
| |
| | \\ | ===== 7. CI/CD Best Practices ===== |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Area</font> \\ | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Choice</font> \\ | | |
| | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Build Tool</font> \\ | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Vite</font> \\ | | |
| | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Unit Tests</font> \\ | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Vitest</font> \\ | | |
| | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>API Mocking</font> \\ | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>MSW</font> \\ | | |
| | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>UI Testing</font> \\ | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>RTL</font> \\ | | |
| | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>E2E</font> \\ | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Playwright</font> \\ | | |
| | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Auth Strategy</font> \\ | \\ | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Shared Token</font> \\ | | |
| |
| ---- | ==== Pipeline Order ==== |
| |
| ===== 11. API Client with Token Interceptor ===== | Lint + Type Check |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Centralized API client ensures **consistent auth handling**, easy mocking, and reuse across Unit, Integration, and E2E tests.</font> | |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // src/services/apiClient.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>axios</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'axios'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>apiClient</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;inherit;;inherit>axios</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>create</font> | |
| <font inherit/Consolas;;inherit;;inherit>({</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>baseURL</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;inherit;;inherit>import</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>meta</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>env</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>VITE_API_BASE_URL</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>apiClient</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>interceptors</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>request</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>use</font> | |
| <font inherit/Consolas;;inherit;;inherit>((config)</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>token</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;inherit;;inherit>sessionStorage</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>getItem</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'auth_token'</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>if</font> | |
| <font inherit/Consolas;;inherit;;inherit>(token) {</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>config</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>headers</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>Authorization</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>`Bearer</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>${</font> | |
| <font inherit/Consolas;;inherit;;inherit>token</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>}</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>`</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>}</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>return</font> | |
| <font inherit/Consolas;;inherit;;inherit>config</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;green;;inherit>export</font> | |
| <font inherit/Consolas;;green;;inherit>default</font> | |
| <font inherit/Consolas;;inherit;;inherit>apiClient</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // src/services/inventoryService.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>apiClient</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'./apiClient'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;green;;inherit>export</font> | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>fetchInventory</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#007020;;inherit>async</font> | |
| <font inherit/Consolas;;inherit;;inherit>()</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>response</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>apiClient</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>get</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'/inventory'</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>return</font> | |
| <font inherit/Consolas;;inherit;;inherit>response</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>data</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>}</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| |
| ---- | Unit Tests (Vitest) |
| |
| ===== 12. Playwright Global Auth + Hybrid MSW E2E ===== | Integration Tests (Vitest + MSW) |
| |
| ==== | Hybrid E2E (Playwright) |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Global Authentication Setup</font> ==== | |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // e2e/playwright/global-setup.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>{ chromium }</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'@playwright/test'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;green;;inherit>export</font> | |
| <font inherit/Consolas;;green;;inherit>default</font> | |
| <font inherit/Consolas;;#007020;;inherit>async</font> | |
| <font inherit/Consolas;;inherit;;inherit>()</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>browser</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>chromium</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>launch</font> | |
| <font inherit/Consolas;;inherit;;inherit>()</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>browser</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>newPage</font> | |
| <font inherit/Consolas;;inherit;;inherit>()</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>goto</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;green;;inherit>process</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>env</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>AUTH_URL</font> | |
| <font inherit/Consolas;;#666666;;inherit>!</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>fill</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'#username'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;green;;inherit>process</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>env</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>E2E_USER</font> | |
| <font inherit/Consolas;;#666666;;inherit>!</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>fill</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'#password'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;green;;inherit>process</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>env</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>E2E_PASSWORD</font> | |
| <font inherit/Consolas;;#666666;;inherit>!</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>click</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'button[type=submit]'</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>waitForURL</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'**/home'</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>context</font> | |
| <font inherit/Consolas;;inherit;;inherit>()</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>storageState</font> | |
| <font inherit/Consolas;;inherit;;inherit>({ path</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'e2e/auth.json'</font> | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>browser</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>close</font> | |
| <font inherit/Consolas;;inherit;;inherit>()</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>}</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // e2e/playwright.config.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>{ defineConfig }</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'@playwright/test'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;green;;inherit>export</font> | |
| <font inherit/Consolas;;green;;inherit>default</font> | |
| <font inherit/Consolas;;#06287e;;inherit>defineConfig</font> | |
| <font inherit/Consolas;;inherit;;inherit>({</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>globalSetup</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'./e2e/playwright/global-setup.ts'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>use</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>storageState</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'e2e/auth.json'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>}</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| |
| ==== Hybrid E2E Test ==== | Optional Full E2E (nightly) |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // e2e/inventory.hybrid.spec.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>{ test</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>expect }</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'@playwright/test'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#06287e;;inherit>test</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'inventory loads with mocked API'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;#007020;;inherit>async</font> | |
| <font inherit/Consolas;;inherit;;inherit>({ page })</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>route</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'**/api/inventory'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;#007020;;inherit>async</font> | |
| <font inherit/Consolas;;inherit;;inherit>(route)</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>route</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>fulfill</font> | |
| <font inherit/Consolas;;inherit;;inherit>({</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>status</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#40a070;;inherit>200</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>contentType</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'application/json'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>body</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;green;;inherit>JSON</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>stringify</font> | |
| <font inherit/Consolas;;inherit;;inherit>([{ id</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#40a070;;inherit>1</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>name</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'Mock Item'</font> | |
| <font inherit/Consolas;;inherit;;inherit>}])</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>goto</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'/inventory'</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;#06287e;;inherit>expect</font> | |
| <font inherit/Consolas;;inherit;;inherit>(page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>getByText</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'Mock Item'</font> | |
| <font inherit/Consolas;;inherit;;inherit>))</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>toBeVisible</font> | |
| <font inherit/Consolas;;inherit;;inherit>()</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| |
| ---- | ==== Failure Handling ==== |
| |
| ===== 13. CI/CD Pipeline Snippets ===== | Fail pipeline on any test failure |
| |
| ==== | Upload Playwright traces/screenshots |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>GitHub Actions</font> ==== | |
| |
| 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 | Publish test reports |
| |
| ==== | ===== 8. Performance Considerations ===== |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>GitLab CI</font> ==== | |
| <font 11pt/Consolas;;#06287e;;inherit>frontend_tests</font> | |
| <font inherit/Consolas;;#007020;;inherit>:</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>image</font> | |
| <font inherit/Consolas;;#007020;;inherit>:</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>node:18</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>stage</font> | |
| <font inherit/Consolas;;#007020;;inherit>:</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>test</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>script</font> | |
| <font inherit/Consolas;;#007020;;inherit>:</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>-</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>npm ci</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>-</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>npm run test:unit</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>-</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>npm run test:integration</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>-</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>npx playwright install --with-deps</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>-</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>npm run test:e2e</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>artifacts</font> | |
| <font inherit/Consolas;;#007020;;inherit>:</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>when</font> | |
| <font inherit/Consolas;;#007020;;inherit>:</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>always</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>paths</font> | |
| <font inherit/Consolas;;#007020;;inherit>:</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>-</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>playwright-report/</font> | |
| |
| ---- | Prefer **client-side rendering (SPA)** |
| |
| ===== 14. Token Refresh & Expiry Handling ===== | Use virtualization for large datasets |
| |
| ==== | Avoid SSR unless SEO is required |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Design Principles</font> ==== | |
| |
| * | Testing should not depend on real backend performance |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Never refresh tokens inside UI components</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Centralize refresh logic in API client</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Retry failed requests transparently</font> | |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // src/services/apiClient.ts (extended) CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>axios</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'axios'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>let</font> | |
| <font inherit/Consolas;;inherit;;inherit>isRefreshing</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#007020;;inherit>false</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>let</font> | |
| <font inherit/Consolas;;inherit;;inherit>queue</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#902000;;inherit>any</font> | |
| <font inherit/Consolas;;inherit;;inherit>[]</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;inherit;;inherit>[]</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>apiClient</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;inherit;;inherit>axios</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>create</font> | |
| <font inherit/Consolas;;inherit;;inherit>({</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>baseURL</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;inherit;;inherit>import</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>meta</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>env</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>VITE_API_BASE_URL</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>apiClient</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>interceptors</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>response</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>use</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>(res)</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>res</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>async</font> | |
| <font inherit/Consolas;;inherit;;inherit>(error)</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>originalRequest</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;inherit;;inherit>error</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>config</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>if</font> | |
| <font inherit/Consolas;;inherit;;inherit>(error</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>response</font> | |
| <font inherit/Consolas;;#666666;;inherit>?.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>status</font> | |
| <font inherit/Consolas;;#666666;;inherit>===</font> | |
| <font inherit/Consolas;;#40a070;;inherit>401</font> | |
| <font inherit/Consolas;;#666666;;inherit>&&</font> | |
| <font inherit/Consolas;;#666666;;inherit>!</font> | |
| <font inherit/Consolas;;inherit;;inherit>originalRequest</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>_retry</font> | |
| <font inherit/Consolas;;inherit;;inherit>) {</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>if</font> | |
| <font inherit/Consolas;;inherit;;inherit>(isRefreshing) {</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>return</font> | |
| <font inherit/Consolas;;#007020;;inherit>new</font> | |
| <font inherit/Consolas;;green;;inherit>Promise</font> | |
| <font inherit/Consolas;;inherit;;inherit>((resolve)</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>queue</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>push</font> | |
| <font inherit/Consolas;;inherit;;inherit>(resolve))</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>}</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>originalRequest</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>_retry</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#007020;;inherit>true</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>isRefreshing</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#007020;;inherit>true</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>refreshToken</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;inherit;;inherit>sessionStorage</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>getItem</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'refresh_token'</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>response</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>axios</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>post</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'/auth/refresh'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>{ refreshToken })</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>sessionStorage</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>setItem</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'auth_token'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>response</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>data</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>accessToken</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>queue</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>forEach</font> | |
| <font inherit/Consolas;;inherit;;inherit>((cb)</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;#06287e;;inherit>cb</font> | |
| <font inherit/Consolas;;inherit;;inherit>())</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>queue</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;inherit;;inherit>[]</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>isRefreshing</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;#007020;;inherit>false</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>return</font> | |
| <font inherit/Consolas;;#06287e;;inherit>apiClient</font> | |
| <font inherit/Consolas;;inherit;;inherit>(originalRequest)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>}</font> \\ \\ | |
| <font inherit/Consolas;;#007020;;inherit>return</font> | |
| <font inherit/Consolas;;green;;inherit>Promise</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>reject</font> | |
| <font inherit/Consolas;;inherit;;inherit>(error)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>}</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;green;;inherit>export</font> | |
| <font inherit/Consolas;;green;;inherit>default</font> | |
| <font inherit/Consolas;;inherit;;inherit>apiClient</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| |
| ---- | ===== 10. Tooling Configuration (Vitest + RTL) ===== |
| |
| ===== 15. API Contract Versioning Strategy ===== | ==== Vitest Configuration ==== |
| |
| ==== | // vitest.config.ts\\ import { defineConfig } from 'vitest/config';\\ import react from '@vitejs/plugin-react';\\ \\ export default defineConfig({\\ plugins: [react()],\\ test: {\\ environment: 'jsdom',\\ setupFiles: './src/tests/setupTests.ts',\\ globals: true,\\ css: true,\\ coverage: {\\ reporter: ['text', 'html'],\\ },\\ },\\ }); |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Versioning Rules</font> ==== | |
| |
| * | ==== Test Setup ==== |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>APIs must be versioned (URI or header based)</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Breaking changes require new version</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>MSW enforces contract compatibility</font> | |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // src/tests/msw/handlers.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>rest</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>get</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'/api/v1/inventory'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>(req</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>res</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>ctx)</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>return</font> | |
| <font inherit/Consolas;;#06287e;;inherit>res</font> | |
| <font inherit/Consolas;;inherit;;inherit>(ctx</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>json</font> | |
| <font inherit/Consolas;;inherit;;inherit>([{ id</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#40a070;;inherit>1</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>name</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'Item V1'</font> | |
| <font inherit/Consolas;;inherit;;inherit>}]))</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;inherit;;inherit>rest</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>get</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'/api/v2/inventory'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>(req</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>res</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>ctx)</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>return</font> | |
| <font inherit/Consolas;;#06287e;;inherit>res</font> | |
| <font inherit/Consolas;;inherit;;inherit>(ctx</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>json</font> | |
| <font inherit/Consolas;;inherit;;inherit>([{ id</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#40a070;;inherit>1</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>name</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'Item V2'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;inherit;;inherit>stock</font> | |
| <font inherit/Consolas;;#666666;;inherit>:</font> | |
| <font inherit/Consolas;;#40a070;;inherit>100</font> | |
| <font inherit/Consolas;;inherit;;inherit>}]))</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| |
| ---- | // src/tests/setupTests.ts\\ import '@testing-library/jest-dom'; |
| |
| ===== 16. Performance Testing (Lighthouse + Playwright) ===== | ===== 11. Unit Test Example (Vitest + RTL) ===== |
| |
| ==== | // src/tests/unit/Header.test.tsx\\ import { render, screen } from '@testing-library/react';\\ import { describe, it, expect } from 'vitest';\\ import { Header } from '@/components/layout/Header';\\ \\ describe('Header', () => {\\ it('renders application title', () => {\\ render(<Header />);\\ expect(screen.getByText(/inventory/i)).toBeInTheDocument();\\ });\\ }); |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Lighthouse CI</font> ==== | |
| <font 11pt/Consolas;;inherit;;inherit>npm</font> | |
| <font inherit/Consolas;;inherit;;inherit>install</font> | |
| <font inherit/Consolas;;#7d9029;;inherit>-D</font> | |
| <font inherit/Consolas;;inherit;;inherit>@lhci/cli</font> | |
| <font 11pt/Consolas;;red;;inherit>//</font> | |
| <font inherit/Consolas;;red;;inherit>lighthouserc.json</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#902000;;inherit>"ci"</font> | |
| <font inherit/Consolas;;#06287e;;inherit>:</font> | |
| <font inherit/Consolas;;#06287e;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#902000;;inherit>"collect"</font> | |
| <font inherit/Consolas;;#06287e;;inherit>:</font> | |
| <font inherit/Consolas;;#06287e;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#902000;;inherit>"url"</font> | |
| <font inherit/Consolas;;#06287e;;inherit>:</font> | |
| <font inherit/Consolas;;#007020;;inherit>[</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>"http://localhost:5173"</font> | |
| <font inherit/Consolas;;#007020;;inherit>]</font> | |
| <font inherit/Consolas;;#06287e;;inherit>,</font> \\ | |
| <font inherit/Consolas;;#902000;;inherit>"startServerCommand"</font> | |
| <font inherit/Consolas;;#06287e;;inherit>:</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>"npm run preview"</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>},</font> \\ | |
| <font inherit/Consolas;;#902000;;inherit>"assert"</font> | |
| <font inherit/Consolas;;#06287e;;inherit>:</font> | |
| <font inherit/Consolas;;#06287e;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#902000;;inherit>"assertions"</font> | |
| <font inherit/Consolas;;#06287e;;inherit>:</font> | |
| <font inherit/Consolas;;#06287e;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#902000;;inherit>"categories:performance"</font> | |
| <font inherit/Consolas;;#06287e;;inherit>:</font> | |
| <font inherit/Consolas;;#007020;;inherit>[</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>"warn"</font> | |
| <font inherit/Consolas;;#007020;;inherit>,</font> | |
| <font inherit/Consolas;;#06287e;;inherit>{</font> | |
| <font inherit/Consolas;;#902000;;inherit>"minScore"</font> | |
| <font inherit/Consolas;;#06287e;;inherit>:</font> | |
| <font inherit/Consolas;;#40a070;;inherit>0.8</font> | |
| <font inherit/Consolas;;#06287e;;inherit>}</font> | |
| <font inherit/Consolas;;#007020;;inherit>]</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>}</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>}</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>}</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>}</font> | |
| |
| ==== Playwright Performance Smoke ==== | ===== 12. Integration Test Example (Vitest + RTL + MSW) ===== |
| <font 11pt/Consolas;;#60a0b0;;inherit>CKGE_TMP_i // e2e/performance.spec.ts CKGE_TMP_i</font> \\ | |
| <font inherit/Consolas;;green;;inherit>import</font> | |
| <font inherit/Consolas;;inherit;;inherit>{ test }</font> | |
| <font inherit/Consolas;;green;;inherit>from</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'@playwright/test'</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ \\ | |
| <font inherit/Consolas;;#06287e;;inherit>test</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'home page loads under 2s'</font> | |
| <font inherit/Consolas;;#666666;;inherit>,</font> | |
| <font inherit/Consolas;;#007020;;inherit>async</font> | |
| <font inherit/Consolas;;inherit;;inherit>({ page })</font> | |
| <font inherit/Consolas;;#007020;;inherit>=></font> | |
| <font inherit/Consolas;;inherit;;inherit>{</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>start</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;green;;inherit>Date</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>now</font> | |
| <font inherit/Consolas;;inherit;;inherit>()</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>await</font> | |
| <font inherit/Consolas;;inherit;;inherit>page</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>goto</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#4070a0;;inherit>'/'</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#007020;;inherit>const</font> | |
| <font inherit/Consolas;;inherit;;inherit>duration</font> | |
| <font inherit/Consolas;;#666666;;inherit>=</font> | |
| <font inherit/Consolas;;green;;inherit>Date</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>now</font> | |
| <font inherit/Consolas;;inherit;;inherit>()</font> | |
| <font inherit/Consolas;;#666666;;inherit>-</font> | |
| <font inherit/Consolas;;inherit;;inherit>start</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;#06287e;;inherit>expect</font> | |
| <font inherit/Consolas;;inherit;;inherit>(duration)</font> | |
| <font inherit/Consolas;;#666666;;inherit>.</font> | |
| <font inherit/Consolas;;#06287e;;inherit>toBeLessThan</font> | |
| <font inherit/Consolas;;inherit;;inherit>(</font> | |
| <font inherit/Consolas;;#40a070;;inherit>2000</font> | |
| <font inherit/Consolas;;inherit;;inherit>)</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> \\ | |
| <font inherit/Consolas;;inherit;;inherit>})</font> | |
| <font inherit/Consolas;;#666666;;inherit>;</font> | |
| |
| ---- | ==== MSW Handler ==== |
| |
| ===== 17. Starter Vite Repository Blueprint ===== | // src/tests/msw/handlers.ts\\ import { rest } from 'msw';\\ \\ export const handlers = [\\ rest.get('/api/inventory', (req, res, ctx) => {\\ const token = req.headers.get('Authorization');\\ if (!token) return res(ctx.status(401));\\ \\ return res(\\ ctx.status(200),\\ ctx.json([{ id: 1, name: 'Item A' }])\\ );\\ }),\\ ]; |
| |
| ==== | ==== MSW Server Setup ==== |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Scripts</font> ==== | |
| |
| { \\ "scripts" : { \\ "dev" : "vite" , \\ "build" : "vite build" , \\ "preview" : "vite preview" , \\ "test:unit" : "vitest" , \\ "test:integration" : "vitest run" , \\ "test:e2e" : "playwright test" , \\ "perf" : "lhci autorun" \\ } \\ } | // src/tests/msw/server.ts\\ import { setupServer } from 'msw/node';\\ import { handlers } from './handlers';\\ \\ export const server = setupServer(...handlers); |
| |
| ==== | // src/tests/setupTests.ts\\ import '@testing-library/jest-dom';\\ import { server } from './msw/server';\\ \\ beforeAll(() => server.listen());\\ afterEach(() => server.resetHandlers());\\ afterAll(() => server.close()); |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Environment Files</font> ==== | |
| |
| .env \\ .env.test \\ .env.e2e | ==== Integration Test ==== |
| |
| ==== | // src/tests/integration/InventoryPage.test.tsx\\ 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(() => {\\ expect(screen.getByText('Item A')).toBeInTheDocument();\\ });\\ }); |
| <font 14pt/Aptos,sans-serif;;#0f4761;;inherit>Ready-to-Use</font> ==== | |
| |
| * | ===== 10. Final Recommendation ===== |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Vite + React + TS</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Vitest + MSW</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Playwright (auth + hybrid)</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>CI/CD ready</font> | |
| * | |
| <font 12pt/Aptos,sans-serif;;inherit;;inherit>Performance gates included</font> | |
| |
| ---- | | Area | Choice | |
| | | Build Tool | Vite | |
| | | Unit Tests | Vitest | |
| | | API Mocking | MSW | |
| | | UI Testing | RTL | |
| | | E2E | Playwright | |
| | | Auth Strategy | 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. |
| | |
| | // src/services/apiClient.ts\\ import axios from 'axios';\\ \\ const apiClient = axios.create({\\ baseURL: import.meta.env.VITE_API_BASE_URL,\\ });\\ \\ apiClient.interceptors.request.use((config) => {\\ const token = sessionStorage.getItem('auth_token');\\ if (token) {\\ config.headers.Authorization = `Bearer ${token}`;\\ }\\ return config;\\ });\\ \\ export default apiClient; |
| | |
| | // src/services/inventoryService.ts\\ 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 ==== |
| | |
| | // e2e/playwright/global-setup.ts\\ 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');\\ await page.context().storageState({ path: 'e2e/auth.json' });\\ \\ await browser.close();\\ }; |
| | |
| | // e2e/playwright.config.ts\\ import { defineConfig } from '@playwright/test';\\ \\ export default defineConfig({\\ globalSetup: './e2e/playwright/global-setup.ts',\\ use: {\\ storageState: 'e2e/auth.json',\\ },\\ }); |
| | |
| | ==== Hybrid E2E Test ==== |
| | |
| | // e2e/inventory.hybrid.spec.ts\\ 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 ==== |
| | |
| | # .github/workflows/frontend-ci.yml\\ 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 |
| | |
| | // src/services/apiClient.ts (extended)\\ 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) => 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) => cb());\\ queue = [];\\ isRefreshing = false;\\ \\ return apiClient(originalRequest);\\ }\\ \\ return Promise.reject(error);\\ }\\ );\\ \\ export default apiClient; |
| | |
| | ===== 15. API Contract Versioning Strategy ===== |
| | |
| | ==== Versioning Rules ==== |
| | |
| | APIs must be versioned (URI or header based) |
| | |
| | Breaking changes require new version |
| | |
| | MSW enforces contract compatibility |
| | |
| | // src/tests/msw/handlers.ts\\ 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 |
| | |
| | // lighthouserc.json\\ {\\ "ci": {\\ "collect": {\\ "url": ["http://localhost:5173"],\\ "startServerCommand": "npm run preview"\\ },\\ "assert": {\\ "assertions": {\\ "categories:performance": ["warn", { "minScore": 0.8 }]\\ }\\ }\\ }\\ } |
| | |
| | ==== Playwright Performance Smoke ==== |
| | |
| | // e2e/performance.spec.ts\\ 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 |
| |