import { afterAll, beforeAll, describe, expect, it } from 'vitest' import { prisma, createCaller } from '../setup' import { createTestUser, createTestProgram, createTestProject, cleanupTestData, uid, } from '../helpers' import { logisticsRouter } from '../../src/server/routers/logistics' beforeAll(() => { process.env.NEXTAUTH_SECRET = 'test-secret-for-finalist-tokens' }) async function setupConfirmedFinalist(programName: string) { const program = await createTestProgram({ name: programName }) const lead = await prisma.user.create({ data: { id: uid('user'), email: `lead_${uid()}@test.local`, name: 'Test Lead', role: 'APPLICANT', roles: ['APPLICANT'], status: 'ACTIVE', }, }) const project = await createTestProject(program.id, { title: 'Confirmed Finalist', competitionCategory: 'STARTUP', }) await prisma.teamMember.create({ data: { projectId: project.id, userId: lead.id, role: 'LEAD' }, }) const confirmation = await prisma.finalistConfirmation.create({ data: { projectId: project.id, category: 'STARTUP', status: 'CONFIRMED', deadline: new Date(Date.now() + 86400000), token: `tok_${uid()}`, confirmedAt: new Date(), }, }) const attendingMember = await prisma.attendingMember.create({ data: { confirmationId: confirmation.id, userId: lead.id, needsVisa: false }, }) return { program, lead, project, confirmation, attendingMember } } describe('logistics flight detail procedures', () => { const programIds: string[] = [] const userIds: string[] = [] afterAll(async () => { for (const programId of programIds) { await prisma.flightDetail.deleteMany({ where: { attendingMember: { confirmation: { project: { programId } } } }, }) await prisma.attendingMember.deleteMany({ where: { confirmation: { project: { programId } } }, }) await prisma.finalistConfirmation.deleteMany({ where: { project: { programId } } }) await cleanupTestData(programId, []) } if (userIds.length > 0) { await prisma.user.deleteMany({ where: { id: { in: userIds } } }) } }) it('listFlightDetails returns one row per AttendingMember of CONFIRMED finalists', async () => { const admin = await createTestUser('SUPER_ADMIN') userIds.push(admin.id) const { program, lead, attendingMember } = await setupConfirmedFinalist( `flight-list-${uid()}`, ) programIds.push(program.id) userIds.push(lead.id) const caller = createCaller(logisticsRouter, { id: admin.id, email: admin.email, role: 'SUPER_ADMIN', }) const rows = await caller.listFlightDetails({ programId: program.id }) expect(rows).toHaveLength(1) expect(rows[0].id).toBe(attendingMember.id) expect(rows[0].flightDetail).toBeNull() // no flight detail yet expect(rows[0].user.email).toBe(lead.email) expect(rows[0].confirmation.project.title).toBe('Confirmed Finalist') }) it('listFlightDetails excludes attendees of PENDING / DECLINED confirmations', async () => { const admin = await createTestUser('SUPER_ADMIN') userIds.push(admin.id) const program = await createTestProgram({ name: `flight-exclude-${uid()}` }) programIds.push(program.id) const lead = await prisma.user.create({ data: { id: uid('user'), email: `pending_${uid()}@test.local`, name: 'Pending Lead', role: 'APPLICANT', roles: ['APPLICANT'], status: 'ACTIVE', }, }) userIds.push(lead.id) const project = await createTestProject(program.id, { title: 'Pending Project', competitionCategory: 'STARTUP', }) await prisma.teamMember.create({ data: { projectId: project.id, userId: lead.id, role: 'LEAD' }, }) const confirmation = await prisma.finalistConfirmation.create({ data: { projectId: project.id, category: 'STARTUP', status: 'PENDING', deadline: new Date(Date.now() + 86400000), token: `tok_${uid()}`, }, }) // Even though there's an AttendingMember, it shouldn't be returned because confirmation is PENDING await prisma.attendingMember.create({ data: { confirmationId: confirmation.id, userId: lead.id }, }) const caller = createCaller(logisticsRouter, { id: admin.id, email: admin.email, role: 'SUPER_ADMIN', }) const rows = await caller.listFlightDetails({ programId: program.id }) expect(rows).toHaveLength(0) }) it('upsertFlightDetail creates then updates', async () => { const admin = await createTestUser('SUPER_ADMIN') userIds.push(admin.id) const { program, lead, attendingMember } = await setupConfirmedFinalist( `flight-upsert-${uid()}`, ) programIds.push(program.id) userIds.push(lead.id) const caller = createCaller(logisticsRouter, { id: admin.id, email: admin.email, role: 'SUPER_ADMIN', }) const arrivalDate = new Date('2026-06-28T12:00:00Z') const created = await caller.upsertFlightDetail({ attendingMemberId: attendingMember.id, arrivalAt: arrivalDate, arrivalFlightNumber: 'AF7400', arrivalAirport: 'NCE', }) expect(created.arrivalFlightNumber).toBe('AF7400') expect(created.status).toBe('PENDING') const updated = await caller.upsertFlightDetail({ attendingMemberId: attendingMember.id, arrivalFlightNumber: 'AF7402', arrivalAirport: 'NCE', }) expect(updated.id).toBe(created.id) // same row expect(updated.arrivalFlightNumber).toBe('AF7402') // Still 1:1 const count = await prisma.flightDetail.count({ where: { attendingMemberId: attendingMember.id }, }) expect(count).toBe(1) }) it('setFlightStatus toggles PENDING ↔ CONFIRMED', async () => { const admin = await createTestUser('SUPER_ADMIN') userIds.push(admin.id) const { program, lead, attendingMember } = await setupConfirmedFinalist( `flight-status-${uid()}`, ) programIds.push(program.id) userIds.push(lead.id) const caller = createCaller(logisticsRouter, { id: admin.id, email: admin.email, role: 'SUPER_ADMIN', }) const detail = await caller.upsertFlightDetail({ attendingMemberId: attendingMember.id, arrivalFlightNumber: 'AF7400', }) expect(detail.status).toBe('PENDING') const confirmed = await caller.setFlightStatus({ flightDetailId: detail.id, status: 'CONFIRMED', }) expect(confirmed.status).toBe('CONFIRMED') const reverted = await caller.setFlightStatus({ flightDetailId: detail.id, status: 'PENDING', }) expect(reverted.status).toBe('PENDING') }) })