import { readFile } from 'node:fs/promises'; import { resolve } from 'node:path'; import { describe, expect, it } from 'vitest'; import { databaseMigrations } from '../../server/postgres/migration-catalog'; const migrationPath = resolve( import.meta.dirname, '..', '..', 'server', 'postgres', 'migrations', '022_vulnerability_finding_result_type.sql' ); const backfillPath = resolve( import.meta.dirname, '..', '..', 'server', 'postgres', 'migrations', '023_defender_vulnerability_backfill.sql' ); describe('PostgreSQL vulnerability finding result type migration', () => { it('registers the immutable catalog extension before the Defender backfill', () => { expect(databaseMigrations.at(-2)).toMatchObject({ version: '022', name: 'vulnerability-finding-result-type' }); expect(databaseMigrations.at(-1)).toMatchObject({ version: '023', name: 'defender-vulnerability-backfill' }); }); it('keeps migration 022 limited to the closed result type constraint', async () => { const sql = await readFile(migrationPath, 'utf8'); expect(sql).toContain("'vulnerability_finding'"); expect(sql).toContain('assessor_occurrences_result_type_check'); expect(sql).not.toMatch(/UPDATE\s+assessor_finding_occurrences/i); }); it('backfills only derived Defender columns in migration 023', async () => { const sql = await readFile(backfillPath, 'utf8'); expect(sql).toMatch(/UPDATE\s+assessor_finding_occurrences/i); expect(sql).toContain("outcome_normalized = 'unknown' THEN 'warning'"); expect(sql).toContain("lower(btrim(tool_id)) = 'defender-for-iot-vulnerabilities'"); expect(sql).not.toMatch(/jsonb_set|\bdata\s*=/i); }); });