browserMocks.ts
1 // Mock browser APIs needed by @statsig/js-client in Node.js environment 2 3 // Document mock with visibility state tracking 4 const mockDocument = { 5 visibilityState: 'visible' as const, 6 documentElement: { 7 lang: 'en', 8 }, 9 addEventListener: ( 10 _event: string, 11 _handler: EventListenerOrEventListenerObject, 12 ) => { 13 // Visibility change events are handled through window.document reference 14 }, 15 } as const 16 17 // Window mock with focus/blur and beforeunload handling 18 export const mockWindow = { 19 document: mockDocument, 20 location: { 21 href: 'node://localhost', 22 pathname: '/', 23 }, 24 addEventListener: ( 25 event: string, 26 handler: EventListenerOrEventListenerObject, 27 ) => { 28 if (event === 'beforeunload') { 29 // Capture beforeunload handlers and run them on process exit 30 process.on('exit', () => { 31 if (typeof handler === 'function') { 32 handler({} as Event) 33 } else { 34 handler.handleEvent({} as Event) 35 } 36 }) 37 } 38 // Other events (focus/blur) are not critically needed in Node.js 39 }, 40 focus: () => { 41 // Focus is a no-op in Node.js 42 }, 43 innerHeight: 768, 44 innerWidth: 1024, 45 } as const 46 47 // Navigator mock with minimal beacon support 48 export const mockNavigator = { 49 sendBeacon: (_url: string, _data: string | Blob): boolean => { 50 // Beacons are used for analytics - return success but don't actually send 51 return true 52 }, 53 userAgent: 54 'Mozilla/5.0 (Node.js) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0', 55 language: 'en-US', 56 } as const 57 58 // Only assign mocks if running in Node.js environment 59 if (typeof window === 'undefined') { 60 // @ts-expect-error: intentionally applying partial mocks for Node.js environment 61 global.window = mockWindow 62 } 63 if (typeof navigator === 'undefined') { 64 // @ts-expect-error: intentionally applying partial mocks for Node.js environment 65 global.navigator = mockNavigator 66 }