mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:43:06 +00:00
73 lines
2.9 KiB
TypeScript
73 lines
2.9 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { execFileSync } from 'node:child_process'
|
|
import { createHash } from 'node:crypto'
|
|
import { readFileSync } from 'node:fs'
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
const migrationSource = (name: string): string =>
|
|
readFileSync(new URL(`../../src/migrations/${name}.ts`, import.meta.url), 'utf8')
|
|
|
|
describe('campaign migration rollback safety', () => {
|
|
const consolidatedName = '20260718_010733_consolidate_campaign_schema'
|
|
|
|
it('keeps the committed campaign-user migration byte-identical to HEAD', () => {
|
|
const source = migrationSource('20260716_010420_add_campaign_user')
|
|
const headSource = execFileSync(
|
|
'git',
|
|
['show', 'HEAD:src/migrations/20260716_010420_add_campaign_user.ts'],
|
|
{ encoding: 'utf8' },
|
|
)
|
|
|
|
expect(createHash('sha256').update(source).digest('hex')).toBe(
|
|
'cb1e897e41ecb30145d2183b8153941fc747888cee0b296697854ba1aa48f14b',
|
|
)
|
|
expect(source).toBe(headSource)
|
|
})
|
|
|
|
it('validates an existing final schema and refuses every partial mismatch', () => {
|
|
const source = migrationSource(consolidatedName)
|
|
expect(source).toContain("('campaign_user', 'email')")
|
|
expect(source).toContain("('contact', 'email')")
|
|
expect(source).toContain("('contact', 'city')")
|
|
expect(source).toContain("'foreign-key|'")
|
|
expect(source).toContain('confupdtype')
|
|
expect(source).toContain('confdeltype')
|
|
expect(source).toContain('existingSchema.featureCount > 0')
|
|
expect(source).toContain('await assertFinalSchema(db)')
|
|
expect(source.indexOf('await assertFinalSchema(db)')).toBeLessThan(
|
|
source.indexOf('CREATE TYPE "public"."enum_campaign_user_role"'),
|
|
)
|
|
})
|
|
|
|
it('backfills committed campaign users before creating final auth indexes', () => {
|
|
const source = migrationSource(consolidatedName)
|
|
expect(source.indexOf('UPDATE "campaign_user" SET "role" = \'geral\'')).toBeLessThan(
|
|
source.indexOf('CREATE UNIQUE INDEX "campaign_user_username_idx"'),
|
|
)
|
|
})
|
|
|
|
it('guards the consolidated rollback before its first schema mutation', () => {
|
|
const source = migrationSource(consolidatedName)
|
|
const down = source.indexOf('export async function down')
|
|
const guard = source.indexOf('Refusing to roll back consolidated campaign schema', down)
|
|
const destructive = source.indexOf(
|
|
'DROP CONSTRAINT IF EXISTS "payload_locked_documents_rels_campaign_invite_fk"',
|
|
down,
|
|
)
|
|
|
|
expect(guard).toBeGreaterThan(down)
|
|
expect(destructive).toBeGreaterThan(guard)
|
|
})
|
|
|
|
it('leaves compatibility constraints for the immutable original rollback', () => {
|
|
const source = migrationSource(consolidatedName)
|
|
const down = source.indexOf('export async function down')
|
|
const compatibilityConstraint = source.indexOf(
|
|
'FOREIGN KEY ("campaign_user_id") REFERENCES "public"."users"("id")',
|
|
down,
|
|
)
|
|
|
|
expect(compatibilityConstraint).toBeGreaterThan(down)
|
|
})
|
|
})
|