Files
MindScope/lib/score-summary.test.ts

56 lines
2.3 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { buildScoreSummary } from '@/lib/score-summary';
describe('buildScoreSummary', () => {
it('applies PHQ-9 severity thresholds', () => {
const summary = buildScoreSummary('phq9', Array(9).fill('2'));
expect(summary.primary).toMatchObject({ value: 18, max: 27, level: '中重度' });
expect(summary).toMatchObject({
questionnaireVersion: 'phq-9-zh-v1',
scoreVersion: 'mindscope-phq9-v1',
scoringStatus: 'structured',
direction: 'risk',
});
});
it('converts WHO-5 raw scores to a percentage', () => {
const summary = buildScoreSummary('who5', Array(5).fill('5'));
expect(summary.primary).toMatchObject({ value: 100, max: 100 });
});
it('reverse scores the positive PSS-10 items', () => {
const summary = buildScoreSummary('pss10', Array(10).fill('0'));
expect(summary.primary).toMatchObject({ value: 16, max: 40, level: '中等' });
expect(summary.reverseItems).toEqual([4, 5, 7, 8]);
});
it('calculates all three DASS-21 dimensions independently', () => {
const summary = buildScoreSummary('dass21', Array(21).fill('1'));
expect(summary.metrics.map((item) => item.value)).toEqual([14, 14, 14]);
});
it('keeps neutral Big Five answers neutral after reverse scoring', () => {
const summary = buildScoreSummary('bigfive', Array(50).fill('3'));
expect(summary.metrics).toHaveLength(5);
expect(summary.metrics.every((item) => item.value === 30 && item.max === 50)).toBe(true);
});
it('keeps neutral HEXACO answers at the midpoint', () => {
const summary = buildScoreSummary('hexaco', Array(60).fill('3'));
expect(summary.metrics).toHaveLength(6);
expect(summary.metrics.every((item) => item.value === 3 && item.max === 5)).toBe(true);
});
it('applies SDS reverse scoring and standard-score conversion', () => {
const summary = buildScoreSummary('sds', Array(20).fill('1'));
expect(summary.primary).toMatchObject({ value: 63, max: 100, level: '中度' });
});
it('falls back to a clearly labelled raw answer sum', () => {
const summary = buildScoreSummary('unknown', ['1', '2', '3']);
expect(summary.primary).toMatchObject({ label: '原始作答总和', value: 6 });
expect(summary.note).toContain('不替代');
expect(summary.scoringStatus).toBe('raw');
});
});