import { describe, expect, it, vi } from "vitest"; const poolConstructor = vi.hoisted(() => vi.fn()); vi.mock("pg", () => ({ Pool: poolConstructor })); import { createValidatedPostgresPool, PostgresPoolError } from "../src/database/pool.js"; describe("createValidatedPostgresPool", () => { it("does not construct a pool merely because the module is imported", () => { expect(poolConstructor).not.toHaveBeenCalled(); }); it.each([ "", " ", "not-a-database-url", "https://admin:do-not-log@db.example.test/database", ])("rejects an invalid connection string without exposing it (%s)", (connectionString) => { let captured: unknown; try { createValidatedPostgresPool(connectionString); } catch (error) { captured = error; } expect(captured).toBeInstanceOf(PostgresPoolError); expect(captured).toMatchObject({ code: "POSTGRES_POOL_CONFIGURATION_INVALID" }); const publicText = `${String(captured)}\n${ captured instanceof Error ? (captured.stack ?? "") : "" }`; if (connectionString) { expect(publicText).not.toContain(connectionString); } expect(poolConstructor).not.toHaveBeenCalled(); }); it("explicitly constructs the pool only when called", () => { poolConstructor.mockImplementation(function fakePool() { return { end: async () => undefined, on: vi.fn() }; }); const handle = createValidatedPostgresPool( "postgresql://operator:do-not-log@example.test/ekklesia", ); expect(poolConstructor).toHaveBeenCalledTimes(1); expect(handle.pool).toBeDefined(); expect(typeof handle.close).toBe("function"); expect(Object.isFrozen(handle)).toBe(true); }); it("passes the connection timeout through to the pool configuration", () => { poolConstructor.mockImplementation(function fakePool() { return { end: async () => undefined, on: vi.fn() }; }); poolConstructor.mockClear(); createValidatedPostgresPool("postgresql://example.test/ekklesia", { connectionTimeoutMs: 5_000, }); expect(poolConstructor).toHaveBeenCalledWith( expect.objectContaining({ connectionTimeoutMillis: 5_000 }), ); }); it("passes the operation timeout through as both query_timeout and statement_timeout", () => { poolConstructor.mockImplementation(function fakePool() { return { end: async () => undefined, on: vi.fn() }; }); poolConstructor.mockClear(); createValidatedPostgresPool("postgresql://example.test/ekklesia", { operationTimeoutMs: 7_500, }); expect(poolConstructor).toHaveBeenCalledWith( expect.objectContaining({ query_timeout: 7_500, statement_timeout: 7_500 }), ); }); it.each([ ["operationTimeoutMs", 0], ["operationTimeoutMs", -1], ["operationTimeoutMs", Number.NaN], ["connectionTimeoutMs", 0], ["connectionTimeoutMs", -1], ] as const)("rejects an invalid %s (%s) without constructing a pool and without leaking the value", (optionName, value) => { poolConstructor.mockClear(); let captured: unknown; try { createValidatedPostgresPool("postgresql://example.test/ekklesia", { [optionName]: value, }); } catch (error) { captured = error; } expect(captured).toBeInstanceOf(PostgresPoolError); expect(captured).toMatchObject({ code: "POSTGRES_POOL_CONFIGURATION_INVALID" }); expect(poolConstructor).not.toHaveBeenCalled(); }); it("registers a pool-level error listener so an idle client failure never becomes an uncaught exception", () => { const on = vi.fn(); poolConstructor.mockImplementation(function fakePool() { return { end: async () => undefined, on }; }); createValidatedPostgresPool("postgresql://example.test/ekklesia"); expect(on).toHaveBeenCalledWith("error", expect.any(Function)); const handler = on.mock.calls.find((call) => call[0] === "error")?.[1] as | ((error: unknown) => void) | undefined; expect(() => handler?.(new Error("terminating connection due to administrator command")), ).not.toThrow(); }); });