src/lib/db/migrations.test.ts
Linked repository file from this build.
import { expect, test } from "bun:test";
import { resolveDatabaseTarget, errorDetails, redact } from "../../../scripts/db/target";
import { migrationPlan, type Migration } from "../../../scripts/db/migrations";
const local = "postgres://local:local-password@localhost/app";
const production =
"postgresql://prod:private-password@ep-demo-pooler.us-east-1.aws.neon.tech/app?sslmode=require";
test("database targets are explicit and production never falls back to development", () => {
expect(
resolveDatabaseTarget("development", { DATABASE_URL: local, PROD_DATABASE_URL: production }, {})
.variable,
).toBe("DATABASE_URL");
const selected = resolveDatabaseTarget(
"production",
{ DATABASE_URL: local, PROD_DATABASE_URL: production },
{},
);
expect(selected.variable).toBe("PROD_DATABASE_URL");
expect(new URL(selected.url).hostname).toBe("ep-demo.us-east-1.aws.neon.tech");
expect(new URL(selected.url).searchParams.get("sslmode")).toBe("verify-full");
expect(selected.label).not.toContain("private-password");
expect(() => resolveDatabaseTarget("production", { DATABASE_URL: local }, {})).toThrow(
"PROD_DATABASE_URL",
);
expect(() => resolveDatabaseTarget("typo", {}, {})).toThrow("target");
expect(resolveDatabaseTarget("production", {}, { PROD_DATABASE_URL: production }).variable).toBe(
"PROD_DATABASE_URL",
);
});
test("database diagnostics preserve nested SQLSTATE details without exposing credentials", () => {
const cause = Object.assign(new Error(`connection ${production} password private-password`), {
code: "42703",
detail: "Missing column",
hint: "Apply migration",
column: "review_key",
});
const errors = errorDetails(new Error("Failed query", { cause }), [production]);
expect(errors[1]).toMatchObject({
code: "42703",
detail: "Missing column",
hint: "Apply migration",
column: "review_key",
});
expect(JSON.stringify(errors)).not.toContain("private-password");
expect(redact("postgres://other:secret@host/db")).not.toContain("secret");
const encoded = "postgres://user:a%40password@localhost/db";
expect(redact("a@password a%40password", [encoded])).toBe("[redacted] [redacted]");
});
const files: Migration[] = [1, 2, 3].map((n) => ({
tag: `000${n}`,
folderMillis: n,
hash: `hash-${n}`,
sql: ["select 1"],
bps: true,
}));
test("status identifies pending migrations and skipped history gaps", () => {
expect(migrationPlan(files, [{ created_at: "1", hash: "hash-1" }])).toMatchObject({
pending: ["0002", "0003"],
issues: [],
});
expect(migrationPlan(files, [{ created_at: "2", hash: "hash-2" }]).issues[0]).toContain(
"skipped",
);
expect(migrationPlan(files, [{ created_at: "4", hash: "unknown" }]).issues[0]).toContain(
"unknown",
);
});
test("edited applied migrations warn without rewriting or replaying their history", () => {
const plan = migrationPlan(files, [{ created_at: "1", hash: "previous-version" }]);
expect(plan.issues).toEqual([]);
expect(plan.warnings[0]).toContain("will not rerun");
expect(plan.pending).toEqual(["0002", "0003"]);
});