gongxiangp2/lib/__tests__/performance-survey-position-admin.test.ts

152 lines
4.8 KiB
TypeScript

/** @jest-environment node */
import { prisma } from '@/lib/prisma'
import {
assertPerformanceSurveyPositionPlanPreviewMatches,
savePerformanceSurveyPositionGroupDraft,
} from '@/lib/performance-survey-position-config'
jest.mock('@/lib/prisma', () => ({
prisma: {
performanceSurveyPositionGroup: {
findUnique: jest.fn(),
update: jest.fn(),
},
performanceSurveyPositionRule: {
deleteMany: jest.fn(),
createMany: jest.fn(),
update: jest.fn(),
},
performanceSurveyTemplateVersion: {
findMany: jest.fn(),
},
$transaction: jest.fn(),
},
}))
describe('performance survey position admin', () => {
beforeEach(() => {
jest.clearAllMocks()
})
test('保存岗位组草稿只更新方案草稿,不改线上岗位组和匹配规则', async () => {
const liveGroup = {
id: 'group-1',
code: 'brand_designer',
name: '线上岗位名',
sortOrder: 10,
isActive: true,
isSystem: true,
archivedAt: null,
}
const existingDraft = {
id: 'draft-1',
positionGroupId: liveGroup.id,
version: 2,
status: 'draft',
effectiveMonth: '2026-08',
matchRules: [{ positionTitle: '线上规则' }],
groupConfig: {
name: liveGroup.name,
sortOrder: liveGroup.sortOrder,
isActive: liveGroup.isActive,
},
items: [],
}
const updatedDraft = {
...existingDraft,
matchRules: [{ positionTitle: '草稿规则' }],
groupConfig: {
name: '草稿岗位名',
sortOrder: 20,
isActive: false,
},
}
const tx = {
performanceSurveyPositionPlan: {
findFirst: jest.fn().mockResolvedValue(existingDraft),
update: jest.fn().mockResolvedValue(updatedDraft),
findUnique: jest.fn().mockResolvedValue(updatedDraft),
},
performanceSurveyPositionPlanItem: {
deleteMany: jest.fn(),
createMany: jest.fn(),
},
performanceSurveyPositionGroup: {
findUnique: jest.fn().mockResolvedValue(liveGroup),
update: jest.fn(),
},
performanceSurveyPositionRule: {
deleteMany: jest.fn(),
createMany: jest.fn(),
update: jest.fn(),
},
performanceSurveyConfigAuditLog: {
create: jest.fn().mockResolvedValue({ id: 'audit-1' }),
},
$queryRawUnsafe: jest.fn().mockResolvedValue([{ locked: '1' }]),
}
;(prisma.performanceSurveyPositionGroup.findUnique as jest.Mock).mockResolvedValue(liveGroup)
;(prisma.$transaction as jest.Mock).mockImplementation(async (callback) => callback(tx))
await expect(savePerformanceSurveyPositionGroupDraft({
groupId: liveGroup.id,
name: '草稿岗位名',
sortOrder: 20,
isActive: false,
rules: [{ positionTitle: '草稿规则' }],
effectiveMonth: '2026-08',
reason: '配置调整',
actorUserId: 'admin-1',
actorName: '管理员',
})).resolves.toMatchObject({
groupId: liveGroup.id,
draftPlanId: existingDraft.id,
version: existingDraft.version,
})
expect(tx.performanceSurveyPositionPlan.update).toHaveBeenCalledWith(expect.objectContaining({
where: { id: existingDraft.id },
data: expect.objectContaining({
matchRules: [{ positionTitle: '草稿规则', departmentPathPrefix: null }],
groupConfig: {
name: '草稿岗位名',
sortOrder: 20,
isActive: false,
},
}),
}))
expect(tx.performanceSurveyConfigAuditLog.create).toHaveBeenCalledTimes(1)
expect(prisma.performanceSurveyPositionGroup.update).not.toHaveBeenCalled()
expect(prisma.performanceSurveyPositionRule.deleteMany).not.toHaveBeenCalled()
expect(prisma.performanceSurveyPositionRule.createMany).not.toHaveBeenCalled()
expect(tx.performanceSurveyPositionGroup.update).not.toHaveBeenCalled()
expect(tx.performanceSurveyPositionRule.deleteMany).not.toHaveBeenCalled()
expect(tx.performanceSurveyPositionRule.createMany).not.toHaveBeenCalled()
expect(tx.$queryRawUnsafe).toHaveBeenCalledWith(
expect.stringContaining('pg_advisory_xact_lock'),
`performance-survey-position-group:${liveGroup.id}`,
)
})
test('发布只能使用发布前检查确认过的同一份草稿', () => {
const draft = {
id: 'draft-1',
version: 3,
updatedAt: new Date('2026-07-23T10:00:00.000Z'),
}
expect(() => assertPerformanceSurveyPositionPlanPreviewMatches(draft, {
draftPlanId: draft.id,
draftVersion: draft.version,
draftUpdatedAt: '2026-07-23T10:00:00.000Z',
})).not.toThrow()
expect(() => assertPerformanceSurveyPositionPlanPreviewMatches(draft, {
draftPlanId: draft.id,
draftVersion: draft.version,
draftUpdatedAt: '2026-07-23T10:00:01.000Z',
})).toThrow('岗位方案草稿已发生变化,请重新执行发布前检查')
})
})