/** * The generated migration is schema-qualified to "payload" throughout but does * not create that schema — `schemaName` says where tables go, it does not * create anything. On staging and production, which have never run it, the * whole migration fails with `schema "payload" does not exist`. * * The CREATE SCHEMA is therefore hand-added, which makes it exactly the kind * of edit a regeneration silently discards. This is the guard. */ import fs from 'fs'; import path from 'path'; const DIR = path.join(__dirname, '..', '..', 'migrations'); function migrationFiles() { return fs .readdirSync(DIR) .filter((f) => f.endsWith('.ts') && f !== 'index.ts'); } describe('payload migrations', () => { it('ships at least one migration, so a container has tables to find', () => { expect(migrationFiles().length).toBeGreaterThan(0); }); it('creates the payload schema before creating anything in it', () => { const initial = migrationFiles().find((f) => f.includes('initial'))!; const sql = fs.readFileSync(path.join(DIR, initial), 'utf8'); expect(sql).toMatch(/CREATE SCHEMA IF NOT EXISTS "payload"/); // Ordering matters: the schema must be created before the first object // that lives in it, or the migration fails on its first statement. expect(sql.indexOf('CREATE SCHEMA IF NOT EXISTS "payload"')) .toBeLessThan(sql.indexOf('CREATE TABLE "payload"')); }); it('creates the tables the app queries on boot', () => { const initial = migrationFiles().find((f) => f.includes('initial'))!; const sql = fs.readFileSync(path.join(DIR, initial), 'utf8'); for (const table of ['users', 'posts', '_posts_v', 'media', 'payload_migrations']) { expect(sql).toContain(`CREATE TABLE "payload"."${table}"`); } }); it('is wired into the adapter, so it runs on server init', () => { const config = fs.readFileSync( path.join(__dirname, '..', '..', 'payload.config.ts'), 'utf8', ); expect(config).toMatch(/prodMigrations:\s*migrations/); }); });