Cesar Mendivil 8b458a3ddf feat: add initial LiveKit Meet integration with utility scripts, configs, and core components
- Add Next.js app structure with base configs, linting, and formatting
- Implement LiveKit Meet page, types, and utility functions
- Add Docker, Compose, and deployment scripts for backend and token server
- Provide E2E and smoke test scaffolding with Puppeteer and Playwright helpers
- Include CSS modules and global styles for UI
- Add postMessage and studio integration utilities
- Update package.json with dependencies and scripts for development and testing
2025-11-20 12:50:38 -07:00

88 lines
2.9 KiB
TypeScript

// 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) }