46 lines
3.0 KiB
TypeScript
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()
|
|
})
|