106 lines
3.7 KiB
TypeScript
106 lines
3.7 KiB
TypeScript
import assert from 'node:assert';
|
|
import test from 'node:test';
|
|
|
|
// Test grading utilities
|
|
function gradeQuestion(question: any, answer: any): number {
|
|
const answerValue = answer.value;
|
|
switch (question.type) {
|
|
case 'multiple_choice':
|
|
if (typeof answerValue === 'string' && question.correctAnswer) {
|
|
return answerValue === question.correctAnswer ? question.points : 0;
|
|
}
|
|
return 0;
|
|
case 'true_false':
|
|
if (typeof answerValue === 'string' && question.correctAnswer) {
|
|
return answerValue === question.correctAnswer ? question.points : 0;
|
|
}
|
|
return 0;
|
|
case 'fill_blank': {
|
|
if (typeof answerValue !== 'string' || !question.correctAnswer) return 0;
|
|
const correct = Array.isArray(question.correctAnswer)
|
|
? question.correctAnswer
|
|
: [question.correctAnswer];
|
|
const submitted = question.caseSensitive ? answerValue.trim() : answerValue.trim().toLowerCase();
|
|
for (const c of correct) {
|
|
const expected = question.caseSensitive ? c.trim() : c.trim().toLowerCase();
|
|
if (submitted === expected) return question.points;
|
|
}
|
|
return 0;
|
|
}
|
|
case 'short_answer':
|
|
case 'essay':
|
|
return -1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
test('grade multiple choice - correct', () => {
|
|
const q = { type: 'multiple_choice', points: 2, correctAnswer: '1', options: ['A', 'B', 'C'] };
|
|
const a = { questionId: '1', value: '1' };
|
|
assert.strictEqual(gradeQuestion(q, a), 2);
|
|
});
|
|
|
|
test('grade multiple choice - incorrect', () => {
|
|
const q = { type: 'multiple_choice', points: 2, correctAnswer: '1', options: ['A', 'B', 'C'] };
|
|
const a = { questionId: '1', value: '0' };
|
|
assert.strictEqual(gradeQuestion(q, a), 0);
|
|
});
|
|
|
|
test('grade true/false - correct', () => {
|
|
const q = { type: 'true_false', points: 1, correctAnswer: 'true' };
|
|
const a = { questionId: '1', value: 'true' };
|
|
assert.strictEqual(gradeQuestion(q, a), 1);
|
|
});
|
|
|
|
test('grade fill_blank - exact match', () => {
|
|
const q = { type: 'fill_blank', points: 3, correctAnswer: ['mitochondria'], caseSensitive: false };
|
|
const a = { questionId: '1', value: 'mitochondria' };
|
|
assert.strictEqual(gradeQuestion(q, a), 3);
|
|
});
|
|
|
|
test('grade fill_blank - case insensitive', () => {
|
|
const q = { type: 'fill_blank', points: 3, correctAnswer: ['mitochondria'], caseSensitive: false };
|
|
const a = { questionId: '1', value: 'Mitochondria' };
|
|
assert.strictEqual(gradeQuestion(q, a), 3);
|
|
});
|
|
|
|
test('grade fill_blank - multiple acceptable', () => {
|
|
const q = { type: 'fill_blank', points: 3, correctAnswer: ['mitochondria', 'Mitochondrion'], caseSensitive: false };
|
|
const a = { questionId: '1', value: 'Mitochondrion' };
|
|
assert.strictEqual(gradeQuestion(q, a), 3);
|
|
});
|
|
|
|
test('grade fill_blank - no match', () => {
|
|
const q = { type: 'fill_blank', points: 3, correctAnswer: ['mitochondria'], caseSensitive: false };
|
|
const a = { questionId: '1', value: 'nucleus' };
|
|
assert.strictEqual(gradeQuestion(q, a), 0);
|
|
});
|
|
|
|
test('grade essay - requires manual', () => {
|
|
const q = { type: 'essay', points: 10 };
|
|
const a = { questionId: '1', value: 'An essay...' };
|
|
assert.strictEqual(gradeQuestion(q, a), -1);
|
|
});
|
|
|
|
test('grade short_answer - requires manual', () => {
|
|
const q = { type: 'short_answer', points: 5 };
|
|
const a = { questionId: '1', value: 'Short answer' };
|
|
assert.strictEqual(gradeQuestion(q, a), -1);
|
|
});
|
|
|
|
// Test store utilities
|
|
function generateId(): string {
|
|
return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
}
|
|
|
|
test('generateId produces unique strings', () => {
|
|
const id1 = generateId();
|
|
const id2 = generateId();
|
|
assert.strictEqual(typeof id1, 'string');
|
|
assert.strictEqual(id1.length > 0, true);
|
|
assert.notStrictEqual(id1, id2);
|
|
});
|
|
|
|
console.log('All tests passed!');
|