/** * One-shot: remove leaked test data from dev DB. * * Test runs that crashed before reaching `afterAll` left orphan test users + * programs. This mirrors `tests/helpers.ts#cleanupTestData` with the same * reverse-dependency order, applied to all programs whose name matches the * test patterns. * * Run: npx tsx scripts/cleanup-test-pollution.ts */ import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() const TEST_PROGRAM_PATTERNS = [ 'Test Program prog-%', 'getCandidates-%', 'bulk-%', 'source-flag-%', 'mentor-files-%', 'mentor-config-%', ] async function main() { const programs = await prisma.program.findMany({ where: { OR: TEST_PROGRAM_PATTERNS.map((p) => ({ name: { startsWith: p.replace('%', '') } })), }, select: { id: true, name: true }, }) console.log(`Found ${programs.length} test programs:`) programs.forEach((p) => console.log(` - ${p.id} ${p.name}`)) for (const program of programs) { const programId = program.id console.log(`\nCleaning ${program.name}...`) // MentorAssignment isn't in cleanupTestData — kill it first const ma = await prisma.mentorAssignment.deleteMany({ where: { project: { programId } }, }) if (ma.count > 0) console.log(` ${ma.count} MentorAssignment`) // Mirror tests/helpers.ts#cleanupTestData order await prisma.cohortProject.deleteMany({ where: { cohort: { round: { competition: { programId } } } } }) await prisma.cohort.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.liveProgressCursor.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.filteringResult.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.filteringRule.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.filteringJob.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.assignmentJob.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.conflictOfInterest.deleteMany({ where: { assignment: { round: { competition: { programId } } } } }) await prisma.evaluation.deleteMany({ where: { assignment: { round: { competition: { programId } } } } }) await prisma.assignment.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.evaluationForm.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.fileRequirement.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.gracePeriod.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.reminderLog.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.evaluationSummary.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.evaluationDiscussion.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.projectRoundState.deleteMany({ where: { round: { competition: { programId } } } }) await prisma.awardEligibility.deleteMany({ where: { award: { program: { id: programId } } } }) await prisma.awardVote.deleteMany({ where: { award: { program: { id: programId } } } }) await prisma.awardJuror.deleteMany({ where: { award: { program: { id: programId } } } }) await prisma.specialAward.deleteMany({ where: { programId } }) await prisma.round.deleteMany({ where: { competition: { programId } } }) await prisma.competition.deleteMany({ where: { programId } }) await prisma.projectStatusHistory.deleteMany({ where: { project: { programId } } }) await prisma.projectFile.deleteMany({ where: { project: { programId } } }) await prisma.projectTag.deleteMany({ where: { project: { programId } } }) await prisma.project.deleteMany({ where: { programId } }) await prisma.program.deleteMany({ where: { id: programId } }) console.log(' cascade complete') } // Delete test users (@test.local). Catch any audit-log refs first. const testUsers = await prisma.user.findMany({ where: { email: { endsWith: '@test.local' } }, select: { id: true }, }) const testUserIds = testUsers.map((u) => u.id) console.log(`\nDeleting ${testUserIds.length} @test.local users...`) if (testUserIds.length > 0) { await prisma.decisionAuditLog.deleteMany({ where: { actorId: { in: testUserIds } } }) await prisma.auditLog.deleteMany({ where: { userId: { in: testUserIds } } }) // Any remaining MentorAssignments referencing these users (e.g., from other tests) await prisma.mentorAssignment.deleteMany({ where: { mentorId: { in: testUserIds } } }) await prisma.user.deleteMany({ where: { id: { in: testUserIds } } }) } console.log('\nDone.') } main() .then(() => prisma.$disconnect()) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) })