import { describe, expect, test } from "bun:test"; import type { ComposeSpecification, Service } from "../../schema/docker.d"; import { buildDatabaseUrl, getComposePostgresClaims, getServicePostgresClaim, isPostgresVolumeEntry, } from "../../lib/database"; describe("managed PostgreSQL claims", () => { test("supports short and explicit syntax", () => { expect( getServicePostgresClaim("app", { volumes: ["postgresql:app"], } as Service), ).toEqual({ service: "app", username: "app", database: "app", secretName: "postgres-app", }); expect( getServicePostgresClaim("app", { volumes: ["postgresql:user/database"], } as Service), ).toEqual({ service: "app", username: "user", database: "database", secretName: "postgres-user", }); }); test.each([ "postgresql:", "postgresql:user/", "postgresql:/database", "postgresql:user/database/extra", "postgresql:user:database", ])("rejects malformed declaration %s", (entry) => { expect(() => getServicePostgresClaim("app", { volumes: [entry] } as Service), ).toThrow("Use postgresql: or postgresql:/"); }); test("ignores unrelated entries and rejects duplicate declarations", () => { expect( getServicePostgresClaim("app", { volumes: ["cache:/cache"], } as Service), ).toBeUndefined(); expect(isPostgresVolumeEntry("cache:/cache")).toBe(false); expect(() => getServicePostgresClaim("app", { volumes: ["postgresql:one", "postgresql:two"], } as Service), ).toThrow("declares multiple postgres volumes"); }); test("allows one owner to share a database", () => { const compose = { services: { app: { volumes: ["postgresql:user/database"] }, worker: { volumes: ["postgresql:user/database"] }, }, } as ComposeSpecification; expect(getComposePostgresClaims(compose)).toHaveLength(2); }); test("rejects conflicting database owners", () => { const compose = { services: { app: { volumes: ["postgresql:one/shared"] }, worker: { volumes: ["postgresql:two/shared"] }, }, } as ComposeSpecification; expect(() => getComposePostgresClaims(compose)).toThrow( "Database shared is claimed by both one and two", ); }); test("escapes every connection URL component", () => { expect( buildDatabaseUrl( { service: "app", username: "user@host", database: "my/database", secretName: "postgres-user", }, { username: "user@host", password: "p:a/ss?#" }, ), ).toBe( "postgresql://user%40host:p%3Aa%2Fss%3F%23@c.database.svc.cluster.local:5432/my%2Fdatabase", ); }); });