import { describe, it, expect } from 'vitest'; import { isConnectionError } from '@/lib/db-errors'; const err = (props: Record) => Object.assign(new Error(typeof props.message === 'string' ? props.message : 'boom'), props); describe('isConnectionError', () => { it('recognises Node socket errors', () => { expect(isConnectionError(err({ code: 'ECONNREFUSED', message: 'connect ECONNREFUSED 127.0.0.1:5433' }))).toBe(true); expect(isConnectionError(err({ code: 'ECONNRESET' }))).toBe(true); expect(isConnectionError(err({ code: 'ETIMEDOUT' }))).toBe(true); expect(isConnectionError(err({ errno: 'ENOTFOUND' }))).toBe(true); }); it('recognises postgres.js connection-level errors', () => { expect(isConnectionError(err({ code: 'CONNECT_TIMEOUT', message: 'write CONNECT_TIMEOUT 127.0.0.1:5433' }))).toBe(true); expect(isConnectionError(err({ code: 'CONNECTION_CLOSED' }))).toBe(true); expect(isConnectionError(err({ code: 'CONNECTION_ENDED' }))).toBe(true); }); it('recognises SQLSTATE classes for connection, auth, bad database, resources and shutdown', () => { expect(isConnectionError(err({ code: '08006' }))).toBe(true); expect(isConnectionError(err({ code: '28P01', message: 'password authentication failed' }))).toBe(true); expect(isConnectionError(err({ code: '3D000', message: 'database "nope" does not exist' }))).toBe(true); expect(isConnectionError(err({ code: '53300', message: 'too many connections' }))).toBe(true); expect(isConnectionError(err({ code: '57P01', message: 'terminating connection due to administrator command' }))).toBe(true); }); it('does NOT flag query-level errors (missing table / column / bad cast) — those become empty states', () => { expect(isConnectionError(err({ code: '42P01', message: 'relation "foo" does not exist' }))).toBe(false); expect(isConnectionError(err({ code: '42703', message: 'column "bar" does not exist' }))).toBe(false); expect(isConnectionError(err({ code: '22P02', message: 'invalid input syntax for type integer' }))).toBe(false); expect(isConnectionError(new Error('some application bug'))).toBe(false); }); it('looks through `cause` chains and message text', () => { expect(isConnectionError(err({ message: 'query failed', cause: err({ code: 'ECONNREFUSED' }) }))).toBe(true); expect(isConnectionError(err({ message: 'connection terminated unexpectedly' }))).toBe(true); }); it('ignores non-objects', () => { expect(isConnectionError(null)).toBe(false); expect(isConnectionError('ECONNREFUSED')).toBe(false); expect(isConnectionError(undefined)).toBe(false); }); });