UNPKG

murmuraba

Version:

Real-time audio noise reduction with advanced chunked processing for web applications

182 lines (181 loc) 5.7 kB
import { vi } from 'vitest'; // Mock WASM Module export const mockWasmModule = { _rnnoise_create: vi.fn().mockReturnValue(123), _rnnoise_destroy: vi.fn(), _rnnoise_process_frame: vi.fn().mockReturnValue(1), _malloc: vi.fn().mockReturnValue(1000), _free: vi.fn(), HEAPF32: new Float32Array(10000), HEAP32: new Int32Array(10000), HEAPU8: new Uint8Array(10000) }; // Mock AudioContext export const createMockAudioContext = () => ({ sampleRate: 48000, createMediaStreamSource: vi.fn().mockReturnValue({ connect: vi.fn(), disconnect: vi.fn() }), createScriptProcessor: vi.fn().mockReturnValue({ connect: vi.fn(), disconnect: vi.fn(), addEventListener: vi.fn(), removeEventListener: vi.fn(), onaudioprocess: null }), createAnalyser: vi.fn().mockReturnValue({ connect: vi.fn(), disconnect: vi.fn(), fftSize: 2048, getByteTimeDomainData: vi.fn(), getFloatTimeDomainData: vi.fn() }), createGain: vi.fn().mockReturnValue({ connect: vi.fn(), disconnect: vi.fn(), gain: { value: 1 } }), close: vi.fn().mockResolvedValue(undefined), state: 'running', suspend: vi.fn(), resume: vi.fn() }); // Mock MediaStream export const createMockMediaStream = () => { const tracks = [{ stop: vi.fn(), kind: 'audio', enabled: true }]; return { getTracks: vi.fn().mockReturnValue(tracks), getAudioTracks: vi.fn().mockReturnValue(tracks), addTrack: vi.fn(), removeTrack: vi.fn() }; }; // Mock getUserMedia export const setupMediaDevicesMock = () => { const mockStream = createMockMediaStream(); global.navigator = { ...global.navigator, mediaDevices: { getUserMedia: vi.fn().mockResolvedValue(mockStream), ondevicechange: null, enumerateDevices: vi.fn().mockResolvedValue([]), getDisplayMedia: vi.fn().mockResolvedValue(mockStream), getSupportedConstraints: vi.fn().mockReturnValue({}), addEventListener: vi.fn(), removeEventListener: vi.fn(), dispatchEvent: vi.fn().mockReturnValue(true) } }; }; // Mock HTMLAudioElement for AudioPlayer tests export const createMockAudio = () => { const eventListeners = {}; const mockAudio = { // Audio properties src: '', currentTime: 0, duration: 0, paused: true, volume: 1, muted: false, readyState: 0, error: null, preload: '', // DOM Element properties and methods setAttribute: vi.fn(), getAttribute: vi.fn(), removeAttribute: vi.fn(), hasAttribute: vi.fn(), tagName: 'AUDIO', nodeType: 1, nodeName: 'AUDIO', parentNode: null, childNodes: [], appendChild: vi.fn(), removeChild: vi.fn(), cloneNode: vi.fn(() => createMockAudio()), ownerDocument: document, // Audio methods play: vi.fn().mockResolvedValue(undefined), pause: vi.fn(), load: vi.fn(), // Event handling addEventListener: vi.fn((type, listener) => { if (!eventListeners[type]) { eventListeners[type] = []; } eventListeners[type].push(listener); }), removeEventListener: vi.fn((type, listener) => { if (eventListeners[type]) { const index = eventListeners[type].indexOf(listener); if (index > -1) { eventListeners[type].splice(index, 1); } } }), dispatchEvent: vi.fn(), // Helper to trigger events in tests _triggerEvent: (type, event = {}) => { if (eventListeners[type]) { eventListeners[type].forEach(listener => listener(event)); } } }; return mockAudio; }; // Setup HTMLAudioElement mock for tests export const setupAudioElementMock = () => { const mockAudio = createMockAudio(); // Mock HTMLAudioElement constructor const originalHTMLAudioElement = global.HTMLAudioElement; global.HTMLAudioElement = vi.fn(() => mockAudio); // Mock audio element creation in JSDOM Object.defineProperty(window, 'Audio', { writable: true, value: vi.fn(() => mockAudio) }); // Mock createElement to return our mock audio for audio elements const originalCreateElement = document.createElement.bind(document); vi.spyOn(document, 'createElement').mockImplementation((tagName) => { if (tagName.toLowerCase() === 'audio') { return mockAudio; } return originalCreateElement(tagName); }); // Mock getBoundingClientRect for seek functionality Element.prototype.getBoundingClientRect = vi.fn(() => ({ left: 0, top: 0, right: 200, bottom: 20, width: 200, height: 20, x: 0, y: 0, toJSON: () => { }, })); return { mockAudio, originalHTMLAudioElement }; }; // Common test utilities export const waitForAsync = () => new Promise(resolve => setTimeout(resolve, 0)); export const createTestConfig = (overrides = {}) => ({ bufferSize: 4096, sampleRate: 48000, channelCount: 1, enableAnalysis: true, enableNoiseSuppression: true, enableVAD: true, vadThreshold: 0.5, vadSensitivity: 0.5, enableAGC: false, agcTargetLevel: 0.7, agcCompressionRate: 0.8, workerProcessingEnabled: false, ...overrides });