80 lines
3.2 KiB
TypeScript
80 lines
3.2 KiB
TypeScript
import {
|
|
DEFAULT_PERFORMANCE_SURVEY_TEMPLATES,
|
|
calculateAggregateScore,
|
|
calculateResponseScores,
|
|
} from '@/lib/performance-survey-templates'
|
|
|
|
describe('performance survey templates', () => {
|
|
test('course share template uses the legacy 100-point and 30% weighted scoring rule', () => {
|
|
const template = DEFAULT_PERFORMANCE_SURVEY_TEMPLATES.find((item) => item.code === 'course_share')!
|
|
const scores = Object.fromEntries(template.questions.map((question) => [question.id, 20]))
|
|
|
|
const result = calculateResponseScores(template, scores)
|
|
|
|
expect(template.questions).toHaveLength(5)
|
|
expect(template.maxTotal).toBe(100)
|
|
expect(template.weight).toBe(0.3)
|
|
expect(template.itemName).toBe('课程')
|
|
expect(template.respondentNameFallback).toBe('匿名学员')
|
|
expect(template.belowBand).toBe('满意度不足 77%,此项考核为 0')
|
|
expect(result.totalScore).toBe(100)
|
|
expect(result.kpiScore).toBe(120)
|
|
expect(result.weightedScore).toBe(36)
|
|
})
|
|
|
|
test('person-period templates use the legacy 120-point and 20% weighted scoring rule', () => {
|
|
const template = DEFAULT_PERFORMANCE_SURVEY_TEMPLATES.find((item) => item.code === 'cross_department')!
|
|
const scores = Object.fromEntries(template.questions.map((question) => [question.id, 20]))
|
|
|
|
const result = calculateResponseScores(template, scores)
|
|
|
|
expect(template.questions).toHaveLength(6)
|
|
expect(template.maxTotal).toBe(120)
|
|
expect(template.weight).toBe(0.2)
|
|
expect(result.totalScore).toBe(120)
|
|
expect(result.kpiScore).toBe(120)
|
|
expect(result.weightedScore).toBe(24)
|
|
})
|
|
|
|
test('aggregate scoring drops one highest and one lowest response when there are at least three', () => {
|
|
const template = DEFAULT_PERFORMANCE_SURVEY_TEMPLATES.find((item) => item.code === 'cross_department')!
|
|
|
|
const result = calculateAggregateScore(
|
|
[
|
|
{
|
|
totalScore: 60,
|
|
createdAt: '2026-07-04T00:00:00.000Z',
|
|
scores: Object.fromEntries(template.questions.map((question) => [question.id, 10])),
|
|
respondentName: '最低分',
|
|
},
|
|
{
|
|
totalScore: 100,
|
|
createdAt: '2026-07-04T00:01:00.000Z',
|
|
scores: Object.fromEntries(template.questions.map((question) => [question.id, question.id === 'requirementClarity' ? 18 : 16])),
|
|
respondentName: '有效分',
|
|
},
|
|
{
|
|
totalScore: 120,
|
|
createdAt: '2026-07-04T00:02:00.000Z',
|
|
scores: Object.fromEntries(template.questions.map((question) => [question.id, 20])),
|
|
respondentName: '最高分',
|
|
},
|
|
],
|
|
template.scoreBands,
|
|
template.weight,
|
|
template,
|
|
)
|
|
|
|
expect(result.droppedHighestLowest).toBe(true)
|
|
expect(result.effectiveCount).toBe(1)
|
|
expect(result.rawAverage).toBe(93.33)
|
|
expect(result.trimNote).toBe('已剔除 1 个最高总分和 1 个最低总分')
|
|
expect(result.removedHigh?.respondentName).toBe('最高分')
|
|
expect(result.removedLow?.respondentName).toBe('最低分')
|
|
expect(result.dimensionAverages.requirementClarity).toBe(18)
|
|
expect(result.achievementScore).toBe(100)
|
|
expect(result.kpiScore).toBe(100)
|
|
expect(result.weightedScore).toBe(20)
|
|
})
|
|
})
|