renderWithProviders.tsx
1 import { render, RenderOptions } from '@testing-library/react'; 2 import React, { ReactElement } from 'react'; 3 import { BrowserRouter, MemoryRouter } from 'react-router-dom'; 4 import { AuthProvider } from '../../../src/web_terminal_client/src/AuthContext'; 5 6 interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> { 7 initialEntries?: string[]; 8 useMemoryRouter?: boolean; 9 } 10 11 /** 12 * Custom render function that wraps components with all necessary providers. 13 */ 14 export function renderWithProviders( 15 ui: ReactElement, 16 options: CustomRenderOptions = {} 17 ) { 18 const { initialEntries = ['/'], useMemoryRouter = false, ...renderOptions } = options; 19 20 function Wrapper({ children }: { children: React.ReactNode }) { 21 const Router = useMemoryRouter 22 ? ({ children }: { children: React.ReactNode }) => ( 23 <MemoryRouter initialEntries={initialEntries}>{children}</MemoryRouter> 24 ) 25 : BrowserRouter; 26 27 return ( 28 <Router> 29 <AuthProvider>{children}</AuthProvider> 30 </Router> 31 ); 32 } 33 34 return { 35 ...render(ui, { wrapper: Wrapper, ...renderOptions }), 36 }; 37 } 38 39 /** 40 * Render with just a router (no AuthProvider) for simpler component tests. 41 */ 42 export function renderWithRouter( 43 ui: ReactElement, 44 options: CustomRenderOptions = {} 45 ) { 46 const { initialEntries = ['/'], useMemoryRouter = true, ...renderOptions } = options; 47 48 function Wrapper({ children }: { children: React.ReactNode }) { 49 return useMemoryRouter ? ( 50 <MemoryRouter initialEntries={initialEntries}>{children}</MemoryRouter> 51 ) : ( 52 <BrowserRouter>{children}</BrowserRouter> 53 ); 54 } 55 56 return { 57 ...render(ui, { wrapper: Wrapper, ...renderOptions }), 58 }; 59 } 60 61 /** 62 * Wait for async operations to complete. 63 */ 64 export function waitForAsync(ms: number = 0): Promise<void> { 65 return new Promise((resolve) => setTimeout(resolve, ms)); 66 } 67 68 /** 69 * Create a deferred promise for testing async flows. 70 */ 71 export function createDeferred<T>() { 72 let resolve: (value: T) => void; 73 let reject: (reason?: unknown) => void; 74 75 const promise = new Promise<T>((res, rej) => { 76 resolve = res; 77 reject = rej; 78 }); 79 80 return { promise, resolve: resolve!, reject: reject! }; 81 }