import { describe, it, expect } from "vitest"; import { isTransientError } from "../utils/errors.js"; /** Create an Error with a `.code` property (like Node/pg errors) */ function makeError(opts: { code?: string; message?: string }): Error { const err = new Error(opts.message || ""); if (opts.code) (err as Error & { code: string }).code = opts.code; return err; } describe("isTransientError", () => { describe("transient error codes", () => { for (const code of ["ECONNRESET", "ECONNREFUSED", "EPIPE", "ETIMEDOUT", "CONNECTION_LOST", "57P01", "57P02", "57P03", "08006", "08003", "08001"]) { it(`detects code ${code}`, () => { expect(isTransientError(makeError({ code }))).toBe(true); }); } }); describe("message-based matches", () => { it("detects 'no available server'", () => expect(isTransientError(new Error("no available server found"))).toBe(true)); it("detects 'connection terminated'", () => expect(isTransientError(new Error("connection terminated unexpectedly"))).toBe(true)); it("detects 'connection refused'", () => expect(isTransientError(new Error("connection refused by host"))).toBe(true)); it("detects 'server closed the connection'", () => expect(isTransientError(new Error("server closed the connection"))).toBe(true)); it("detects 'timeout expired'", () => expect(isTransientError(new Error("timeout expired waiting"))).toBe(true)); }); describe("non-transient errors", () => { it("rejects generic error", () => expect(isTransientError(new Error("something broke"))).toBe(false)); it("rejects SQL syntax error", () => expect(isTransientError(makeError({ code: "42601", message: "syntax error" }))).toBe(false)); }); describe("null/undefined input", () => { it("returns false for null", () => expect(isTransientError(null)).toBe(false)); it("returns false for undefined", () => expect(isTransientError(undefined)).toBe(false)); }); describe("partial error objects", () => { it("handles Error with code but no message", () => expect(isTransientError(makeError({ code: "ECONNRESET" }))).toBe(true)); it("handles Error with message but no code", () => expect(isTransientError(new Error("connection terminated"))).toBe(true)); it("rejects Error with unrelated code and no message", () => expect(isTransientError(makeError({ code: "UNKNOWN" }))).toBe(false)); it("rejects plain object (not an Error instance)", () => expect(isTransientError({ code: "ECONNRESET" })).toBe(false)); }); });