/** @jest-environment node */ import type { Session } from 'next-auth' import { prisma } from '@/lib/prisma' import { getPerformanceSurveyContext } from '@/lib/performance-survey-service' import { getFirstPassReviewProjects } from '@/lib/work-review-service' jest.mock('@/lib/prisma', () => ({ prisma: { workReviewVersion: { groupBy: jest.fn() }, workReviewProject: { count: jest.fn(), findMany: jest.fn() }, }, })) jest.mock('@/lib/performance-survey-service', () => ({ getPerformanceSurveyContext: jest.fn(), })) jest.mock('@/lib/performance-survey-report-sync', () => ({ getPerformanceSurveyAccountProfileWhere: jest.fn(async () => ({})), })) jest.mock('@/lib/work-review-notifications', () => ({ ensureWorkReviewNotificationWorkerStarted: jest.fn(), queueWorkReviewNotification: jest.fn(async () => undefined), })) const session = { user: { id: 'manager-user' } } as Session describe('department dashboard first-pass review details', () => { beforeEach(() => { jest.clearAllMocks() ;(getPerformanceSurveyContext as jest.Mock).mockResolvedValue({ user: { id: 'manager-user', username: 'manager' }, employee: { id: 'manager-employee', displayName: '主管' }, scopeDepartmentPath: '江苏简尚品牌管理有限公司/品牌中心', isSystemAdmin: true, isDepartmentAdmin: true, isLeadership: true, }) ;(prisma.workReviewVersion.groupBy as jest.Mock).mockResolvedValue([ { status: 'approved', _count: { _all: 2 } }, { status: 'pending_review', _count: { _all: 1 } }, ]) ;(prisma.workReviewProject.count as jest.Mock).mockImplementation(({ where }) => ( JSON.stringify(where).includes('"status":"approved"') ? Promise.resolve(5) : Promise.resolve(1) )) ;(prisma.workReviewProject.findMany as jest.Mock).mockResolvedValue([{ id: 'project-1', title: '品牌主视觉', description: '第一版视觉作品', status: 'revision_required', latestVersion: 2, submitterName: '提交人', managerName: '主管', finalReviewerName: '元泽', workDate: new Date('2026-08-28T00:00:00.000Z'), createdAt: new Date('2026-08-28T01:00:00.000Z'), updatedAt: new Date('2026-08-30T01:00:00.000Z'), versions: [{ status: 'approved', submittedAt: new Date('2026-08-28T01:00:00.000Z'), completedAt: new Date('2026-08-28T03:00:00.000Z'), reviews: [{ reviewerRole: 'manager', reviewerName: '主管', decision: 'approved', reviewedAt: new Date('2026-08-28T02:00:00.000Z'), }], }], }]) }) test('summary keeps the full department V1 population while search narrows only detail rows', async () => { const result = await getFirstPassReviewProjects(session, { page: 2, pageSize: 10, query: '主视觉', }) expect(prisma.workReviewVersion.groupBy).toHaveBeenCalledWith({ by: ['status'], where: { version: 1, project: { is: { submitterEmployee: { is: expect.objectContaining({ OR: expect.any(Array) }), }, }, }, }, _count: { _all: true }, }) expect(prisma.workReviewProject.count).toHaveBeenCalledWith({ where: { AND: [ { submitterEmployee: { is: expect.objectContaining({ OR: expect.any(Array) }), }, }, { status: 'approved' }, ], }, }) expect(prisma.workReviewProject.count).toHaveBeenCalledWith({ where: expect.objectContaining({ AND: expect.arrayContaining([ expect.objectContaining({ AND: expect.arrayContaining([ expect.objectContaining({ submitterEmployee: { is: expect.objectContaining({ OR: expect.any(Array) }), }, }), { versions: { some: { version: 1 } } }, ]) }), expect.objectContaining({ OR: expect.any(Array) }), ]), }), }) expect(prisma.workReviewProject.findMany).toHaveBeenCalledWith(expect.objectContaining({ select: expect.objectContaining({ id: true, title: true, description: true, createdAt: true, versions: { where: { version: 1 }, select: { status: true, submittedAt: true, completedAt: true, reviews: { select: { reviewerRole: true, reviewerName: true, decision: true, reviewedAt: true, }, orderBy: [{ reviewedAt: 'asc' }, { reviewerRole: 'asc' }], }, }, take: 1, }, }), orderBy: [{ updatedAt: 'desc' }, { workDate: 'desc' }, { id: 'desc' }], skip: 10, take: 10, })) expect(prisma.workReviewProject.findMany).not.toHaveBeenCalledWith(expect.objectContaining({ select: expect.objectContaining({ imageUrls: true }), })) expect(result.summary).toMatchObject({ totalUploads: 3, totalApproved: 5, firstPassApproved: 2, rate: 40, }) expect(result.items).toEqual([{ id: 'project-1', title: '品牌主视觉', description: '第一版视觉作品', currentStatus: 'revision_required', latestVersion: 2, submitterName: '提交人', managerName: '主管', finalReviewerName: '元泽', workDate: '2026-08-28T00:00:00.000Z', createdAt: '2026-08-28T01:00:00.000Z', updatedAt: '2026-08-30T01:00:00.000Z', firstVersionStatus: 'approved', firstVersionSubmittedAt: '2026-08-28T01:00:00.000Z', firstVersionCompletedAt: '2026-08-28T03:00:00.000Z', firstVersionReviews: [{ reviewerRole: 'manager', reviewerName: '主管', decision: 'approved', reviewedAt: '2026-08-28T02:00:00.000Z', }], }]) expect(result.pagination).toEqual({ page: 2, pageSize: 10, total: 1, totalPages: 1 }) }) })