import { describe, expect, it, vi } from "vitest"; const clientConstructor = vi.hoisted(() => vi.fn()); vi.mock("pg", () => ({ Client: clientConstructor })); import { createPostgresMigrationDatabase, PostgresMigrationDatabaseError, } from "../src/migrations/postgres-database.js"; describe("PostgreSQL migration database composition", () => { it("does not construct a client or execute SQL merely because the adapter is imported", () => { expect(clientConstructor).not.toHaveBeenCalled(); }); it.each([ undefined, "", "not-a-database-url", "https://admin:do-not-log@db.example.test/database", ])("rejects missing or invalid configuration without exposing it (%s)", (databaseUrl) => { let captured: unknown; try { createPostgresMigrationDatabase(databaseUrl); } catch (error) { captured = error; } expect(captured).toBeInstanceOf(PostgresMigrationDatabaseError); expect(captured).toMatchObject({ code: "POSTGRES_MIGRATION_CONFIGURATION_INVALID" }); const publicText = `${String(captured)}\n${ captured instanceof Error ? (captured.stack ?? "") : "" }\n${JSON.stringify(captured)}`; if (databaseUrl) { expect(publicText).not.toContain(databaseUrl); } expect(clientConstructor).not.toHaveBeenCalled(); }); it("creates a lazy database composition without opening a connection", () => { const database = createPostgresMigrationDatabase( "postgresql://operator:do-not-log@example.test/ekklesia", ); expect(Object.isFrozen(database)).toBe(true); expect(clientConstructor).not.toHaveBeenCalled(); expect(JSON.stringify(database)).not.toContain("operator"); expect(JSON.stringify(database)).not.toContain("do-not-log"); expect(JSON.stringify(database)).not.toContain("example.test"); }); it.each([ ["connectionTimeoutMs", 0], ["connectionTimeoutMs", -1], ["connectionTimeoutMs", 1.5], ["connectionTimeoutMs", Number.NaN], ["connectionTimeoutMs", Number.POSITIVE_INFINITY], ["connectionTimeoutMs", 2_147_483_648], ["operationTimeoutMs", 0], ["operationTimeoutMs", -1], ["operationTimeoutMs", 1.5], ["operationTimeoutMs", Number.NaN], ["operationTimeoutMs", Number.POSITIVE_INFINITY], ["operationTimeoutMs", 2_147_483_648], ] as const)("rejects an invalid %s value without constructing a client", (name, value) => { let captured: unknown; try { createPostgresMigrationDatabase("postgresql://example.test/ekklesia", { [name]: value, }); } catch (error) { captured = error; } expect(captured).toBeInstanceOf(PostgresMigrationDatabaseError); expect(captured).toMatchObject({ code: "POSTGRES_MIGRATION_CONFIGURATION_INVALID" }); expect(clientConstructor).not.toHaveBeenCalled(); }); it("passes bounded connection and operation timeouts to the PostgreSQL client", async () => { const client = { connect: vi.fn().mockResolvedValue(undefined), end: vi.fn().mockResolvedValue(undefined), on: vi.fn(), }; const MockClient = class { readonly connect = client.connect; readonly end = client.end; readonly on = client.on; }; clientConstructor.mockImplementation(MockClient as unknown as () => typeof client); const database = createPostgresMigrationDatabase("postgresql://example.test/ekklesia", { connectionTimeoutMs: 10_000, operationTimeoutMs: 12_000, }); const session = await database.openSession(); expect(clientConstructor).toHaveBeenCalledWith({ connectionString: "postgresql://example.test/ekklesia", connectionTimeoutMillis: 10_000, query_timeout: 12_000, statement_timeout: 12_000, }); expect(client.on).toHaveBeenCalledWith("error", expect.any(Function)); expect(client.connect).toHaveBeenCalledOnce(); await session.close(); expect(client.end).toHaveBeenCalledOnce(); }); });