Files
template-app/modules/account/__tests__/migration.test.ts
T

50 lines
2.7 KiB
TypeScript

// The module's migrations are its own files, each exactly `schemaStatements()` over the entities it
// added (decision AT-D20: the entity definition is the one source of a column). Forward-only: the
// first file stays the ledger's as first shipped, the revocation outbox is the second, and the
// ledger's step record (`steps`, `provider`) is the third, two added columns. All global tables: an
// account and an app session belong to no organization, so they carry no tenant column and no policy.
import { readFileSync } from "node:fs"
import { schemaStatements } from "@conusai-kit/data-kysely"
import { describe, expect, it } from "vitest"
import { ACCOUNT_ENTITIES, accountDeletions, accountModule, accountSessionRevocations } from "../index.js"
function tablesOf(entities: Parameters<typeof schemaStatements>[0]): string {
const kernel = schemaStatements([]).length
return `${schemaStatements(entities)
.slice(kernel)
.map((statement) => `${statement};`)
.join("\n\n")}\n`
}
describe("the migration of the account module", () => {
const migration = (name: string) => readFileSync(new URL(`../migrations/${name}`, import.meta.url), "utf8")
// A migration that has run is never edited: the columns added since are a file of their own, and
// the files together are exactly the entity.
it("is its own file, the ledger table as first shipped, and a third file adds the step record", () => {
const added = ',\n "steps" jsonb,\n "provider" text\n'
const generated = tablesOf([accountDeletions])
expect(generated).toContain(added)
expect(generated.replace(added, "\n")).toBe(migration("0001_account.sql"))
expect(migration("0003_deletion_steps.sql")).toBe(
'alter table "account_deletion" add column "steps" jsonb;\n\nalter table "account_deletion" add column "provider" text;\n',
)
})
it("adds the revocation outbox in a second file, exactly its table", async () => {
await expect(tablesOf([accountSessionRevocations])).toMatchFileSnapshot("../migrations/0002_session_revocation.sql")
expect(ACCOUNT_ENTITIES).toEqual([accountDeletions, accountSessionRevocations])
const sql = readFileSync(new URL("../migrations/0002_session_revocation.sql", import.meta.url), "utf8")
expect(sql).not.toContain("org_id")
})
it("is declared by the manifest for Postgres; on Convex the schema comes from the same entities", () => {
expect(accountModule.migrations).toEqual({ postgres: "migrations" })
expect(accountModule.profiles).toEqual(["postgres", "convex"])
const sql = readFileSync(new URL("../migrations/0001_account.sql", import.meta.url), "utf8")
expect(sql).toContain('create table "account_deletion"')
expect(sql).not.toContain("org_id")
})
})