import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('../lib/prisma', () => ({ prisma: { employee: { findFirst: vi.fn(), create: vi.fn(), }, company: { findUniqueOrThrow: vi.fn(), }, }, })) vi.mock('./notificationService', () => ({ sendTransactionalEmail: vi.fn().mockResolvedValue(undefined), })) import crypto from 'crypto' import { prisma } from '../lib/prisma' import { sendTransactionalEmail } from './notificationService' import { inviteEmployee } from './teamService' describe('teamService inviteEmployee', () => { const originalDashboardUrl = process.env.DASHBOARD_URL const originalPublicDashboardUrl = process.env.NEXT_PUBLIC_DASHBOARD_URL beforeEach(() => { vi.clearAllMocks() process.env.DASHBOARD_URL = 'http://localhost:3001' process.env.NEXT_PUBLIC_DASHBOARD_URL = '' vi.spyOn(crypto, 'randomBytes').mockReturnValue(Buffer.from('token-123')) vi.spyOn(crypto, 'randomUUID').mockReturnValue('uuid-123') vi.mocked(prisma.employee.findFirst).mockResolvedValue(null as any) vi.mocked(prisma.company.findUniqueOrThrow).mockResolvedValue({ name: 'Atlas Cars' } as any) vi.mocked(prisma.employee.create).mockResolvedValue({ id: 'emp_1', firstName: 'Aya', lastName: 'Benali', email: 'aya@example.com', role: 'AGENT', isActive: true, } as any) }) afterAll(() => { process.env.DASHBOARD_URL = originalDashboardUrl process.env.NEXT_PUBLIC_DASHBOARD_URL = originalPublicDashboardUrl vi.restoreAllMocks() }) it('builds invite reset links under the dashboard base path', async () => { await inviteEmployee('company_1', 'owner_1', { firstName: 'Aya', lastName: 'Benali', email: 'aya@example.com', role: 'AGENT', }) expect(sendTransactionalEmail).toHaveBeenCalledWith( expect.objectContaining({ to: 'aya@example.com', html: expect.stringContaining('http://localhost:3001/dashboard/reset-password?token=746f6b656e2d313233'), text: expect.stringContaining('http://localhost:3001/dashboard/reset-password?token=746f6b656e2d313233'), }), ) }) })