import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; import { PCQ_QUESTION_IDS, applyReverseScoring, isReverseScored, parseLikertValue, scoreAnswer, scoreAssessment, ScoringValidationError, validateAnswers, } from '../src/modules/assessments/scoring/index.js'; function answersWithValue(value: string | number) { return PCQ_QUESTION_IDS.map((questionId) => ({ questionId, selectedValue: value })); } describe('PCQ-24 scoring engine', () => { it('reverse-scores pcq_13, pcq_20, and pcq_23 with 7 - raw', () => { assert.equal(isReverseScored('pcq_13'), true); assert.equal(isReverseScored('pcq_20'), true); assert.equal(isReverseScored('pcq_23'), true); assert.equal(isReverseScored('pcq_01'), false); assert.equal(applyReverseScoring(1), 6); assert.equal(applyReverseScoring(6), 1); assert.equal(applyReverseScoring('4'), 3); }); it('keeps raw Likert and stores reverse-scored points separately', () => { const scored = scoreAnswer('pcq_13', '2'); assert.ok(scored); assert.equal(scored.selectedValue, 2); assert.equal(scored.rawScore, 5); assert.equal(scored.dimension, 'resilience'); assert.equal(scored.isReverseScored, true); }); it('scores a uniform Likert-4 attempt with known totals', () => { const result = scoreAssessment('pre', answersWithValue(4)); assert.equal(result.totalScore, 93); assert.equal(result.dimensions.efficacy, 24); assert.equal(result.dimensions.hope, 24); assert.equal(result.dimensions.resilience, 23); assert.equal(result.dimensions.optimism, 22); const reverse = result.answers.filter((answer) => answer.isReverseScored); assert.equal(reverse.length, 3); for (const answer of reverse) { assert.equal(answer.selectedValue, 4); assert.equal(answer.rawScore, 3); } }); it('rejects incomplete or out-of-range answers', () => { assert.equal(validateAnswers(answersWithValue(4).slice(0, 23)).isValid, false); assert.equal(parseLikertValue('7'), null); assert.throws( () => scoreAssessment('pre', answersWithValue(7)), (err: unknown) => err instanceof ScoringValidationError, ); }); });