97 lines
3.1 KiB
TypeScript
97 lines
3.1 KiB
TypeScript
import { AudioService } from '../src/services/audioService';
|
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
|
|
describe('AudioService Audio Context Initialization', () => {
|
|
let audioService: AudioService;
|
|
|
|
beforeEach(() => {
|
|
// Reset the singleton instance before each test
|
|
AudioService.resetInstance();
|
|
audioService = AudioService.getInstance();
|
|
|
|
// Mock AudioContext for testing
|
|
global.window.AudioContext = vi.fn().mockImplementation(() => ({
|
|
state: 'suspended',
|
|
sampleRate: 44100,
|
|
resume: vi.fn().mockResolvedValue(undefined),
|
|
close: vi.fn().mockResolvedValue(undefined),
|
|
onstatechange: null,
|
|
suspend: vi.fn().mockResolvedValue(undefined)
|
|
})) as any;
|
|
});
|
|
|
|
afterEach(() => {
|
|
// Clean up any audio contexts
|
|
if (audioService['audioContext']) {
|
|
audioService['audioContext'].close?.().catch(() => {});
|
|
}
|
|
|
|
// Clean up mock
|
|
delete global.window.AudioContext;
|
|
});
|
|
|
|
it('should initialize audio context successfully', async () => {
|
|
const context = await audioService.initializeAudioContext();
|
|
expect(context).toBeDefined();
|
|
expect(context.state).toBe('suspended'); // Should start suspended
|
|
expect(audioService['audioContext']).toBe(context);
|
|
});
|
|
|
|
it('should handle audio context resume', async () => {
|
|
// Initialize context first
|
|
await audioService.initializeAudioContext();
|
|
|
|
// Mock user gesture by resuming
|
|
const resumeSpy = vi.spyOn(audioService['audioContext']!, 'resume');
|
|
|
|
// This should attempt to resume the context
|
|
await audioService['handleAudioContextResume']();
|
|
|
|
expect(resumeSpy).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should share audio context with WaveSurfer', async () => {
|
|
// Initialize audio context
|
|
await audioService.initializeAudioContext();
|
|
|
|
// Create mock WaveSurfer instance
|
|
const mockWaveSurfer = {
|
|
backend: {
|
|
audioContext: null
|
|
}
|
|
};
|
|
|
|
// Call the sharing method
|
|
audioService['shareAudioContextWithWaveSurfer'](mockWaveSurfer);
|
|
|
|
// Verify context was shared
|
|
expect(mockWaveSurfer.backend.audioContext).toBe(audioService['audioContext']);
|
|
});
|
|
|
|
it('should handle WaveSurfer without backend gracefully', async () => {
|
|
// Initialize audio context
|
|
await audioService.initializeAudioContext();
|
|
|
|
// Create mock WaveSurfer instance without backend
|
|
const mockWaveSurfer = {
|
|
getAudioContext: vi.fn()
|
|
};
|
|
|
|
// This should not throw
|
|
expect(() => {
|
|
audioService['shareAudioContextWithWaveSurfer'](mockWaveSurfer);
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('should check initialization state correctly', async () => {
|
|
// Initially should not be initialized
|
|
expect(audioService.isInitialized()).toBe(false);
|
|
|
|
// After audio context initialization, still not fully initialized
|
|
await audioService.initializeAudioContext();
|
|
expect(audioService.isInitialized()).toBe(false);
|
|
|
|
// Note: Full initialization would require WaveSurfer instance
|
|
// which we can't easily mock here without DOM
|
|
});
|
|
}); |