murmuraba
Version:
Real-time audio noise reduction with advanced chunked processing for web applications
168 lines (167 loc) • 4.84 kB
JavaScript
/**
* Main test utilities export file
* Import everything from here for a clean, organized test setup
*/
import { describe, afterEach, expect } from 'vitest';
// Re-export all utilities
export * from './audio-context-utils';
export * from './console-utils';
export * from './factories';
export * from './custom-matchers';
// Import for side effects (auto-setup custom matchers)
import './custom-matchers';
import { vi } from 'vitest';
import { setupAudioContextMock } from './audio-context-utils';
import { useConsoleMocks } from './console-utils';
/**
* Setup complete test environment with all common mocks
*/
export function setupTestEnvironment(options = {}) {
const env = {
audioContext: null,
consoleMocks: null,
cleanup: () => { },
};
// Setup console mocks
const getConsoleMocks = useConsoleMocks(options.console);
env.consoleMocks = getConsoleMocks;
// Setup AudioContext mock
const audioMock = setupAudioContextMock(options.audio);
env.audioContext = audioMock.context;
// Setup WASM mocks if needed
if (options.wasm) {
env.wasmModule = setupWASMMocks(options.wasm);
}
// Setup fetch mock if needed
if (options.fetch) {
setupFetchMock();
}
// Setup timers if needed
if (options.timers) {
vi.useFakeTimers();
}
// Cleanup function
env.cleanup = () => {
audioMock.restore();
vi.clearAllMocks();
if (options.timers) {
vi.useRealTimers();
}
};
return env;
}
/**
* Setup WASM module mocks
*/
function setupWASMMocks(options = {}) {
const { rnnoiseState = 12345, vadProbability = 0.7 } = options;
const mockModule = {
_rnnoise_create: vi.fn().mockReturnValue(rnnoiseState),
_rnnoise_destroy: vi.fn(),
_rnnoise_process_frame: vi.fn().mockReturnValue(vadProbability),
_malloc: vi.fn((size) => size),
_free: vi.fn(),
HEAPF32: new Float32Array(10000),
HEAP32: new Int32Array(10000),
HEAPU8: new Uint8Array(10000),
HEAPU32: new Uint32Array(10000),
};
// Mock the loader
vi.doMock('../../utils/rnnoise-loader', () => ({
loadRNNoiseModule: vi.fn().mockResolvedValue(mockModule),
}));
return mockModule;
}
/**
* Setup fetch mock for blob and WASM operations
*/
function setupFetchMock() {
global.fetch = vi.fn().mockImplementation((url) => {
if (url.startsWith('blob:')) {
return Promise.resolve({
ok: true,
blob: vi.fn().mockResolvedValue(new Blob(['mock audio data'], { type: 'audio/webm' })),
arrayBuffer: vi.fn().mockResolvedValue(new ArrayBuffer(1024)),
});
}
if (url.includes('.wasm')) {
const mockWasm = new ArrayBuffer(8);
new Uint8Array(mockWasm).set([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]);
return Promise.resolve({
ok: true,
arrayBuffer: vi.fn().mockResolvedValue(mockWasm),
});
}
return Promise.reject(new Error(`Fetch not mocked for URL: ${url}`));
});
}
/**
* Helper to wait for async operations
*/
export async function waitForAsync(ms = 0) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Helper to flush all promises
*/
export async function flushPromises() {
return new Promise(resolve => setImmediate(resolve));
}
/**
* Create a deferred promise for testing async operations
*/
export function createDeferred() {
let resolve;
let reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return {
promise,
resolve: resolve,
reject: reject,
};
}
/**
* Mock performance.now for consistent timing tests
*/
export function mockPerformanceNow(sequence) {
let index = 0;
vi.spyOn(performance, 'now').mockImplementation(() => {
const value = sequence[index % sequence.length];
index++;
return value;
});
}
/**
* Helper for testing error scenarios
*/
export async function expectAsyncError(fn, errorPattern) {
try {
await fn();
throw new Error('Expected function to throw');
}
catch (error) {
if (errorPattern) {
if (typeof errorPattern === 'string') {
expect(error.message).toContain(errorPattern);
}
else {
expect(error.message).toMatch(errorPattern);
}
}
}
}
/**
* Create a test suite with common setup
*/
export function createTestSuite(name, options = {}, tests) {
describe(name, () => {
const env = setupTestEnvironment(options);
afterEach(() => {
env.cleanup();
});
tests(env);
});
}