import { describe, it, expect, vi } from 'vitest' import { SttError, createErrorHandler, ErrorRecovery } from '../../src/core/stt-error' describe('SttError', () => { describe('constructor', () => { it('should create error with code and message', () => { const error = new SttError('NOT_INITIALIZED', 'SDK not initialized') expect(error).toBeInstanceOf(SttError) expect(error.name).toBe('SttError') expect(error.code).toBe('NOT_INITIALIZED') expect(error.message).toBe('SDK not initialized') expect(error.timestamp).toBeGreaterThan(0) expect(error.details).toBeUndefined() }) it('should create error with details', () => { const details = { userId: 'test-user', channel: 'test-channel' } const error = new SttError('INVALID_CONFIG', 'Invalid configuration', details) expect(error.details).toEqual(details) }) }) describe('fromError', () => { it('should return SttError instance if already SttError', () => { const originalError = new SttError('NETWORK_ERROR', 'Network failed') const result = SttError.fromError(originalError) expect(result).toBe(originalError) }) it('should convert Error to SttError', () => { const originalError = new Error('Something went wrong') const result = SttError.fromError(originalError, 'UNKNOWN_ERROR') expect(result).toBeInstanceOf(SttError) expect(result.code).toBe('UNKNOWN_ERROR') expect(result.message).toBe('Something went wrong') expect(result.details?.originalError).toBe(originalError) }) it('should handle non-Error objects', () => { const result = SttError.fromError('String error', 'NETWORK_ERROR') expect(result).toBeInstanceOf(SttError) expect(result.code).toBe('NETWORK_ERROR') expect(result.message).toBe('String error') }) }) describe('toJSON', () => { it('should serialize error to JSON', () => { const error = new SttError('NOT_INITIALIZED', 'SDK not initialized') const json = error.toJSON() expect(json).toEqual({ name: 'SttError', code: 'NOT_INITIALIZED', message: 'SDK not initialized', timestamp: error.timestamp, details: undefined, stack: error.stack, }) }) }) describe('toString', () => { it('should return formatted string', () => { const error = new SttError('NOT_INITIALIZED', 'SDK not initialized') const str = error.toString() expect(str).toBe('[NOT_INITIALIZED] SDK not initialized') }) }) }) describe('createErrorHandler', () => { it('should create error handler without emitter', () => { const handler = createErrorHandler() const error = new Error('Test error') const result = handler(error) expect(result).toBeInstanceOf(SttError) }) it('should create error handler with emitter', () => { const emitter = { emit: vi.fn(), } const handler = createErrorHandler(emitter) const error = new Error('Test error') const result = handler(error) expect(result).toBeInstanceOf(SttError) expect(emitter.emit).toHaveBeenCalledWith('error', result) }) it('should include context in details', () => { const handler = createErrorHandler() const error = new Error('Test error') const result = handler(error, 'test-context') expect(result.details?.context).toBe('test-context') }) }) describe('ErrorRecovery', () => { describe('retry', () => { it('should succeed on first attempt', async () => { const recovery = new ErrorRecovery() const operation = vi.fn().mockResolvedValue('success') const result = await recovery.retry(operation) expect(result).toBe('success') expect(operation).toHaveBeenCalledTimes(1) }) it('should retry and succeed', async () => { const recovery = new ErrorRecovery() const operation = vi .fn() .mockRejectedValueOnce(new Error('First attempt failed')) .mockResolvedValueOnce('success') const result = await recovery.retry(operation) expect(result).toBe('success') expect(operation).toHaveBeenCalledTimes(2) }) it('should fail after max retries', async () => { const recovery = new ErrorRecovery(2, 10) const operation = vi.fn().mockRejectedValue(new Error('Always fails')) await expect(recovery.retry(operation)).rejects.toThrow('Always fails') expect(operation).toHaveBeenCalledTimes(2) // Initial + 1 retry (maxRetries=2 means 2 total attempts) }) it('should respect shouldRetry function', async () => { const recovery = new ErrorRecovery() const operation = vi.fn().mockRejectedValue(new SttError('NETWORK_ERROR', 'Network failed')) const shouldRetry = vi.fn().mockReturnValue(false) await expect(recovery.retry(operation, shouldRetry)).rejects.toThrow(SttError) expect(operation).toHaveBeenCalledTimes(1) expect(shouldRetry).toHaveBeenCalledTimes(1) }) }) })