gongxiangp2/lib/__tests__/performance-salary-calculation.test.ts

46 lines
3.0 KiB
TypeScript

import { averageSalaryScores, calculateSalaryPerformance, resolveSalarySourceMonth, salaryMetricForSurvey, salaryRoleForPosition } from '../performance-salary-calculation'
test.each([
['2026-10', 0, 'development', 'true', '2026-09'],
['2026-10', 1, 'development', 'true', '2026-10'],
['2026-10', 0, 'production', 'true', '2026-10'],
['2026-10', 0, 'test', 'true', '2026-10'],
['2026-10', 0, 'development', undefined, '2026-10'],
['2026-09', 0, 'development', 'true', '2026-09'],
['2027-10', 0, 'development', 'true', '2027-10'],
])('整页数据月份 %s %s %s %s → %s', (month, count, env, enabled, expected) => {
const result = resolveSalarySourceMonth(month as string, count as number, env as string, enabled as string | undefined)
expect(result).toEqual({ displayMonth: month, sourceMonth: expected, isFallback: expected !== month })
})
test.each([
['ai_planning_creative', 'ai-planning'], ['ai_planning_general', 'ai-planning'], ['ai_planning_future', 'ai-planning'],
['camera', 'photography'], ['editing', 'photography'], ['retouching', 'photography'],
['brand_designer', 'spatial-visual'], ['director', 'ai-planning'], ['ai_technical_designer', 'ai-technical'], ['position_custom', null],
])('岗位映射 %s', (code, expected) => expect(salaryRoleForPosition(code)).toBe(expected))
test('相同人员同指标全部有效响应取平均,零分有效,空值不冒充零', () => {
expect(averageSalaryScores([80, 100, 0, null, undefined, NaN])).toBe(60)
expect(averageSalaryScores([])).toBeNull()
expect(averageSalaryScores([null])).toBeNull()
})
test('先指标占比再分区权重;不提前四舍五入,零权重缺失不阻断总分', () => {
const result = calculateSalaryPerformance('ai-planning', { brandReview: 80, onTime: 90, marketValidation: 100, cooperation: 60, sharing: null, collaboration: null })
expect(result.weighted.onTime).toBe(81)
expect(result.totalScore).toBe(86.7) // 80*.25 + (100*.1+90*.9)*.7 +60*.05
expect(calculateSalaryPerformance('ai-planning', { brandReview: 80, onTime: 90, marketValidation: null, cooperation: 60 }).totalScore).toBeNull()
expect(calculateSalaryPerformance('management', { visualTone: 100, collaboration: 80, marketValidation: 70, onTime: 90, sharing: 60, cooperation: 100 }).totalScore).toBe(92.4)
expect(calculateSalaryPerformance('photography', {}).totalScore).toBeNull()
const spatial = calculateSalaryPerformance('spatial-visual', { aiTools: 100, collaboration: 100, onTime: 100, sharing: 100, cooperation: 100 })
expect(spatial.weighted.onTime).toBe(90)
expect(spatial.totalScore).toBeNull() // Original template has no quantitative section weight.
})
test('模板复制保留视觉评分语义,未知模板不自动映射', () => {
expect(salaryMetricForSurvey('copy-id', { surveyType: 'visual_case' })).toBe('visualTone')
expect(salaryMetricForSurvey('cross_department', {})).toBe('collaboration')
expect(salaryMetricForSurvey('project_result_validation', {})).toBe('marketValidation')
expect(salaryMetricForSurvey('unmapped', { name: '随意新指标' })).toBeNull()
})