// Vitest setup for broadcast-panel tests import { vi } from 'vitest' // Ensure global window exists (jsdom may provide it, but be defensive) if (typeof (globalThis as any).window === 'undefined') { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore (globalThis as any).window = globalThis } // polyfill matchMedia for jsdom function makeMatchMedia() { return (query: string) => { return { matches: false, media: query, onchange: null, addListener: () => {}, removeListener: () => {}, addEventListener: () => {}, removeEventListener: () => {}, dispatchEvent: () => false, } } } ;(globalThis as any).matchMedia = makeMatchMedia(); if (typeof (globalThis as any).window !== 'undefined') { (globalThis as any).window.matchMedia = makeMatchMedia(); } // Minimal ResizeObserver polyfill for jsdom if (typeof (globalThis as any).ResizeObserver === 'undefined') { (globalThis as any).ResizeObserver = class { callback: Function; constructor(cb: Function) { this.callback = cb } observe(_target?: Element) { /* no-op */ } unobserve(_target?: Element) { /* no-op */ } disconnect() { /* no-op */ } } as any; } // Partially mock livekit-client to provide a constructible Room while keeping other exports vi.mock('livekit-client', () => { const instances: any[] = []; function Room(this: any, ..._args: any[]) { const connect = vi.fn(async (serverUrl?: string, token?: string) => { // emulate async connect return Promise.resolve(); }); const disconnect = vi.fn(() => {}); const localParticipant = { setCameraEnabled: vi.fn(() => Promise.resolve()), setMicrophoneEnabled: vi.fn(() => Promise.resolve()), }; const inst = { connect, disconnect, localParticipant, state: 'disconnected', isConnected: false }; instances.push(inst); return inst; } const Track = { Source: { Camera: 'camera', ScreenShare: 'screen' } }; return { Room: Room as any, Track, __mocks: { instances } }; }); // Minimal mocks for @livekit/components-react to avoid DOM APIs and hooks during tests vi.mock('@livekit/components-react', () => { const React = require('react'); const noop = () => React.createElement('div', null); return { GridLayout: noop, ParticipantTile: noop, ControlBar: noop, RoomAudioRenderer: noop, useTracks: () => [], RoomContext: { Provider: ({ children }: any) => children }, useRoom: () => ({ room: null }), useParticipant: () => ({ participant: null }), useLocalParticipant: () => ({ localParticipant: null }), usePrefetchRoom: () => ({}), // export anything else as noop so imports succeed }; }); // Mock styles import (no-op) vi.mock('@livekit/components-styles', () => ({})); // optional: silence console during tests // const orig = console.error; console.error = (...args) => { if (String(args[0]).includes('Warning')) return; orig(...args) }