98 lines
2.8 KiB
TypeScript
98 lines
2.8 KiB
TypeScript
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:<name> or postgresql:<user>/<database>");
|
|
});
|
|
|
|
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%[email protected]:5432/my%2Fdatabase",
|
|
);
|
|
});
|
|
});
|