gongxiangp2/lib/__tests__/performance-survey-sync-route.test.ts
2026-07-27 10:28:18 +08:00

101 lines
3.1 KiB
TypeScript

/** @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()
})
})