/** @jest-environment node */ import { getServerSession } from 'next-auth' import { POST } from '@/app/api/performance-survey/[...path]/route' import { previewPerformanceSurveyEmployeeProfiles, syncPerformanceSurveyEmployeeProfiles, } from '@/lib/performance-survey-service' jest.mock('next-auth', () => ({ getServerSession: jest.fn(), })) jest.mock('@/lib/auth', () => ({ authOptions: {}, })) jest.mock('@/lib/dingtalk-performance-session', () => ({ DINGTALK_PERFORMANCE_SESSION_HEADER: 'x-performance-token', verifyDingtalkPerformanceSessionToken: jest.fn(), })) jest.mock('@/lib/performance-survey-service', () => ({ PerformanceSurveyApiError: class PerformanceSurveyApiError extends Error { status: number constructor(message: string, status = 400) { super(message) this.status = status } }, previewPerformanceSurveyEmployeeProfiles: jest.fn(), syncPerformanceSurveyEmployeeProfiles: jest.fn(), })) describe('performance survey employee sync route', () => { beforeEach(() => { jest.clearAllMocks() ;(getServerSession as jest.Mock).mockResolvedValue({ user: { id: 'admin-1' }, expires: '2099-01-01T00:00:00.000Z', }) }) test('preview 子路径只执行只读预检', async () => { ;(previewPerformanceSurveyEmployeeProfiles as jest.Mock).mockResolvedValue({ mode: 'preview', dryRun: true, }) const response = await POST( new Request('https://example.test/api/performance-survey/admin/sync-employees/preview', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ limit: 200 }), }), { params: { path: ['admin', 'sync-employees', 'preview'] } }, ) const payload = await response.json() expect(response.status).toBe(200) expect(payload).toEqual({ success: true, data: { mode: 'preview', dryRun: true }, }) expect(previewPerformanceSurveyEmployeeProfiles).toHaveBeenCalledWith( expect.objectContaining({ user: expect.objectContaining({ id: 'admin-1' }) }), { limit: 200 }, ) expect(syncPerformanceSurveyEmployeeProfiles).not.toHaveBeenCalled() }) test('原同步路径继续执行正式同步,契约不变', async () => { ;(syncPerformanceSurveyEmployeeProfiles as jest.Mock).mockResolvedValue({ scannedAccounts: 10, upserted: 8, }) const response = await POST( new Request('https://example.test/api/performance-survey/admin/sync-employees', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ limit: 3000 }), }), { params: { path: ['admin', 'sync-employees'] } }, ) const payload = await response.json() expect(response.status).toBe(200) expect(payload).toEqual({ success: true, data: { scannedAccounts: 10, upserted: 8 }, }) expect(syncPerformanceSurveyEmployeeProfiles).toHaveBeenCalledWith( expect.objectContaining({ user: expect.objectContaining({ id: 'admin-1' }) }), { limit: 3000 }, ) expect(previewPerformanceSurveyEmployeeProfiles).not.toHaveBeenCalled() }) })