import { describe, expect, it } from 'vitest' import { execFileSync } from 'node:child_process' import path from 'node:path' /** * Schema und Migrationen dürfen nicht auseinanderlaufen. * * Der Anlass war handfest: ein von Hand angelegter GIN-Index über den * Suchvektor stand in der Migration, aber nicht in `schema.prisma`. Prisma * hielt das für einen Rückstand und fragte bei jedem `migrate dev` nach einem * Namen für eine neue Migration - deren Inhalt gewesen wäre, **den Suchindex * zu löschen**. Wer die Frage in Eile beantwortet, verliert die gestufte * Volltextsuche und merkt es erst, wenn die Suche leer bleibt. * * Der Vergleich läuft gegen die Datenbank, auf die der Testlauf zeigt. Sie * trägt alle Migrationen, also ist ein Unterschied zum Schema genau der * Rückstand, den `migrate dev` sonst anbietet. * * `--exit-code`: 0 heisst kein Unterschied, 2 heisst Unterschied. */ const url = process.env.DIRECT_DATABASE_URL ?? process.env.DATABASE_URL const suite = url ? describe : describe.skip suite('Schema und Migrationen', () => { it('haben keinen Unterschied, den migrate dev anbieten würde', () => { const wurzel = path.resolve(__dirname, '..') let ausgabe = '' let code = 0 try { ausgabe = execFileSync( 'node', [ require.resolve('prisma/build/index.js', { paths: [wurzel] }), 'migrate', 'diff', '--from-config-datasource', '--to-schema', path.join('prisma', 'schema.prisma'), '--script', '--exit-code', ], { cwd: wurzel, encoding: 'utf8', env: { ...process.env }, timeout: 120_000 }, ) } catch (error) { const fehler = error as { status?: number; stdout?: string; stderr?: string } code = fehler.status ?? 1 ausgabe = `${fehler.stdout ?? ''}${fehler.stderr ?? ''}` } // Die Meldung nennt das fehlende Stück, damit man nicht suchen muss. expect(ausgabe.replace(/^Loaded Prisma config.*$/m, '').trim(), ausgabe).not.toMatch( /^--\s*(Create|Drop|Alter|Add)/m, ) expect(code, ausgabe).toBe(0) }, 130_000) })