errors.test.ts
1 import { describe, expect, it } from 'vitest'; 2 3 import { classifyBrowserError, isTransientBrowserError } from './errors.js'; 4 5 describe('classifyBrowserError', () => { 6 it('classifies extension transient errors with 1500ms delay', () => { 7 for (const msg of [ 8 'Extension disconnected', 9 'Extension not connected', 10 'attach failed', 11 'no longer exists', 12 'CDP connection reset', 13 'Daemon command failed', 14 'No window with id: 123', 15 ]) { 16 const advice = classifyBrowserError(new Error(msg)); 17 expect(advice.kind, `expected "${msg}" → extension-transient`).toBe('extension-transient'); 18 expect(advice.retryable).toBe(true); 19 expect(advice.delayMs).toBe(1500); 20 } 21 }); 22 23 it('classifies CDP target navigation errors with 200ms delay', () => { 24 const advice = classifyBrowserError(new Error('Inspected target navigated or closed')); 25 expect(advice.kind).toBe('target-navigation'); 26 expect(advice.retryable).toBe(true); 27 expect(advice.delayMs).toBe(200); 28 }); 29 30 it('classifies CDP -32000 target errors with 200ms delay', () => { 31 const advice = classifyBrowserError(new Error('{"code":-32000,"message":"Target closed"}')); 32 expect(advice.kind).toBe('target-navigation'); 33 expect(advice.retryable).toBe(true); 34 expect(advice.delayMs).toBe(200); 35 }); 36 37 it('returns non-retryable for unrelated errors', () => { 38 for (const msg of ['Permission denied', 'malformed exec payload', 'SyntaxError']) { 39 const advice = classifyBrowserError(new Error(msg)); 40 expect(advice.kind).toBe('non-retryable'); 41 expect(advice.retryable).toBe(false); 42 } 43 }); 44 45 it('handles non-Error values', () => { 46 expect(classifyBrowserError('Extension disconnected').kind).toBe('extension-transient'); 47 expect(classifyBrowserError(42).kind).toBe('non-retryable'); 48 }); 49 }); 50 51 describe('isTransientBrowserError (convenience wrapper)', () => { 52 it('returns true for transient errors', () => { 53 expect(isTransientBrowserError(new Error('No window with id: 123'))).toBe(true); 54 }); 55 56 it('returns false for non-transient errors', () => { 57 expect(isTransientBrowserError(new Error('Permission denied'))).toBe(false); 58 }); 59 });