383 lines
16 KiB
JavaScript
383 lines
16 KiB
JavaScript
const { sequelize } = require('../models');
|
|
const { User, Category, GuestSession, QuizSession } = require('../models');
|
|
|
|
async function runTests() {
|
|
console.log('🧪 Running QuizSession Model Tests\n');
|
|
console.log('=====================================\n');
|
|
|
|
try {
|
|
let testUser, testCategory, testGuestSession, userQuiz, guestQuiz;
|
|
|
|
// Test 1: Create a quiz session for a registered user
|
|
console.log('Test 1: Create quiz session for user');
|
|
testUser = await User.create({
|
|
username: `quizuser${Date.now()}`,
|
|
email: `quizuser${Date.now()}@test.com`,
|
|
password: 'password123',
|
|
role: 'user'
|
|
});
|
|
|
|
testCategory = await Category.create({
|
|
name: 'Test Category for Quiz',
|
|
description: 'Category for quiz testing',
|
|
isActive: true
|
|
});
|
|
|
|
userQuiz = await QuizSession.createSession({
|
|
userId: testUser.id,
|
|
categoryId: testCategory.id,
|
|
quizType: 'practice',
|
|
difficulty: 'medium',
|
|
totalQuestions: 10,
|
|
passPercentage: 70.00
|
|
});
|
|
|
|
console.log('✅ User quiz session created with ID:', userQuiz.id);
|
|
console.log(' User ID:', userQuiz.userId);
|
|
console.log(' Category ID:', userQuiz.categoryId);
|
|
console.log(' Status:', userQuiz.status);
|
|
console.log(' Total questions:', userQuiz.totalQuestions);
|
|
console.log(' Match:', userQuiz.status === 'not_started' ? '✅' : '❌');
|
|
|
|
// Test 2: Create a quiz session for a guest
|
|
console.log('\nTest 2: Create quiz session for guest');
|
|
testGuestSession = await GuestSession.createSession({
|
|
maxQuizzes: 5,
|
|
expiryHours: 24
|
|
});
|
|
|
|
guestQuiz = await QuizSession.createSession({
|
|
guestSessionId: testGuestSession.id,
|
|
categoryId: testCategory.id,
|
|
quizType: 'practice',
|
|
difficulty: 'easy',
|
|
totalQuestions: 5,
|
|
passPercentage: 60.00
|
|
});
|
|
|
|
console.log('✅ Guest quiz session created with ID:', guestQuiz.id);
|
|
console.log(' Guest session ID:', guestQuiz.guestSessionId);
|
|
console.log(' Category ID:', guestQuiz.categoryId);
|
|
console.log(' Total questions:', guestQuiz.totalQuestions);
|
|
console.log(' Match:', guestQuiz.guestSessionId === testGuestSession.id ? '✅' : '❌');
|
|
|
|
// Test 3: Start a quiz session
|
|
console.log('\nTest 3: Start quiz session');
|
|
await userQuiz.start();
|
|
await userQuiz.reload();
|
|
console.log('✅ Quiz started');
|
|
console.log(' Status:', userQuiz.status);
|
|
console.log(' Started at:', userQuiz.startedAt);
|
|
console.log(' Match:', userQuiz.status === 'in_progress' && userQuiz.startedAt ? '✅' : '❌');
|
|
|
|
// Test 4: Record correct answer
|
|
console.log('\nTest 4: Record correct answer');
|
|
const beforeAnswers = userQuiz.questionsAnswered;
|
|
const beforeCorrect = userQuiz.correctAnswers;
|
|
await userQuiz.recordAnswer(true, 10);
|
|
await userQuiz.reload();
|
|
console.log('✅ Answer recorded');
|
|
console.log(' Questions answered:', userQuiz.questionsAnswered);
|
|
console.log(' Correct answers:', userQuiz.correctAnswers);
|
|
console.log(' Total points:', userQuiz.totalPoints);
|
|
console.log(' Match:', userQuiz.questionsAnswered === beforeAnswers + 1 &&
|
|
userQuiz.correctAnswers === beforeCorrect + 1 ? '✅' : '❌');
|
|
|
|
// Test 5: Record incorrect answer
|
|
console.log('\nTest 5: Record incorrect answer');
|
|
const beforeAnswers2 = userQuiz.questionsAnswered;
|
|
const beforeCorrect2 = userQuiz.correctAnswers;
|
|
await userQuiz.recordAnswer(false, 0);
|
|
await userQuiz.reload();
|
|
console.log('✅ Incorrect answer recorded');
|
|
console.log(' Questions answered:', userQuiz.questionsAnswered);
|
|
console.log(' Correct answers:', userQuiz.correctAnswers);
|
|
console.log(' Match:', userQuiz.questionsAnswered === beforeAnswers2 + 1 &&
|
|
userQuiz.correctAnswers === beforeCorrect2 ? '✅' : '❌');
|
|
|
|
// Test 6: Get quiz progress
|
|
console.log('\nTest 6: Get quiz progress');
|
|
const progress = userQuiz.getProgress();
|
|
console.log('✅ Progress retrieved');
|
|
console.log(' Status:', progress.status);
|
|
console.log(' Questions answered:', progress.questionsAnswered);
|
|
console.log(' Questions remaining:', progress.questionsRemaining);
|
|
console.log(' Progress percentage:', progress.progressPercentage + '%');
|
|
console.log(' Current accuracy:', progress.currentAccuracy + '%');
|
|
console.log(' Match:', progress.questionsAnswered === 2 ? '✅' : '❌');
|
|
|
|
// Test 7: Update time spent
|
|
console.log('\nTest 7: Update time spent');
|
|
await userQuiz.updateTimeSpent(120); // 2 minutes
|
|
await userQuiz.reload();
|
|
console.log('✅ Time updated');
|
|
console.log(' Time spent:', userQuiz.timeSpent, 'seconds');
|
|
console.log(' Match:', userQuiz.timeSpent === 120 ? '✅' : '❌');
|
|
|
|
// Test 8: Complete quiz by answering remaining questions
|
|
console.log('\nTest 8: Auto-complete quiz when all questions answered');
|
|
// Answer remaining 8 questions (6 correct, 2 incorrect)
|
|
for (let i = 0; i < 8; i++) {
|
|
const isCorrect = i < 6; // First 6 are correct
|
|
await userQuiz.recordAnswer(isCorrect, isCorrect ? 10 : 0);
|
|
}
|
|
await userQuiz.reload();
|
|
console.log('✅ Quiz auto-completed');
|
|
console.log(' Status:', userQuiz.status);
|
|
console.log(' Questions answered:', userQuiz.questionsAnswered);
|
|
console.log(' Correct answers:', userQuiz.correctAnswers);
|
|
console.log(' Score:', userQuiz.score + '%');
|
|
console.log(' Is passed:', userQuiz.isPassed);
|
|
console.log(' Match:', userQuiz.status === 'completed' && userQuiz.isPassed === true ? '✅' : '❌');
|
|
|
|
// Test 9: Get quiz results
|
|
console.log('\nTest 9: Get quiz results');
|
|
const results = userQuiz.getResults();
|
|
console.log('✅ Results retrieved');
|
|
console.log(' Total questions:', results.totalQuestions);
|
|
console.log(' Correct answers:', results.correctAnswers);
|
|
console.log(' Score:', results.score + '%');
|
|
console.log(' Is passed:', results.isPassed);
|
|
console.log(' Duration:', results.duration, 'seconds');
|
|
console.log(' Match:', results.correctAnswers === 8 && results.isPassed === true ? '✅' : '❌');
|
|
|
|
// Test 10: Calculate score
|
|
console.log('\nTest 10: Calculate score');
|
|
const calculatedScore = userQuiz.calculateScore();
|
|
console.log('✅ Score calculated');
|
|
console.log(' Calculated score:', calculatedScore + '%');
|
|
console.log(' Expected: 80%');
|
|
console.log(' Match:', calculatedScore === 80.00 ? '✅' : '❌');
|
|
|
|
// Test 11: Create timed quiz
|
|
console.log('\nTest 11: Create timed quiz with time limit');
|
|
const timedQuiz = await QuizSession.createSession({
|
|
userId: testUser.id,
|
|
categoryId: testCategory.id,
|
|
quizType: 'timed',
|
|
difficulty: 'hard',
|
|
totalQuestions: 20,
|
|
timeLimit: 600, // 10 minutes
|
|
passPercentage: 75.00
|
|
});
|
|
await timedQuiz.start();
|
|
console.log('✅ Timed quiz created');
|
|
console.log(' Quiz type:', timedQuiz.quizType);
|
|
console.log(' Time limit:', timedQuiz.timeLimit, 'seconds');
|
|
console.log(' Match:', timedQuiz.quizType === 'timed' && timedQuiz.timeLimit === 600 ? '✅' : '❌');
|
|
|
|
// Test 12: Timeout a quiz
|
|
console.log('\nTest 12: Timeout a quiz');
|
|
await timedQuiz.updateTimeSpent(610); // Exceed time limit
|
|
await timedQuiz.reload();
|
|
console.log('✅ Quiz timed out');
|
|
console.log(' Status:', timedQuiz.status);
|
|
console.log(' Time spent:', timedQuiz.timeSpent);
|
|
console.log(' Match:', timedQuiz.status === 'timed_out' ? '✅' : '❌');
|
|
|
|
// Test 13: Abandon a quiz
|
|
console.log('\nTest 13: Abandon a quiz');
|
|
const abandonQuiz = await QuizSession.createSession({
|
|
userId: testUser.id,
|
|
categoryId: testCategory.id,
|
|
quizType: 'practice',
|
|
difficulty: 'easy',
|
|
totalQuestions: 15
|
|
});
|
|
await abandonQuiz.start();
|
|
await abandonQuiz.recordAnswer(true, 10);
|
|
await abandonQuiz.abandon();
|
|
await abandonQuiz.reload();
|
|
console.log('✅ Quiz abandoned');
|
|
console.log(' Status:', abandonQuiz.status);
|
|
console.log(' Questions answered:', abandonQuiz.questionsAnswered);
|
|
console.log(' Completed at:', abandonQuiz.completedAt);
|
|
console.log(' Match:', abandonQuiz.status === 'abandoned' ? '✅' : '❌');
|
|
|
|
// Test 14: Find active session for user
|
|
console.log('\nTest 14: Find active session for user');
|
|
const activeQuiz = await QuizSession.createSession({
|
|
userId: testUser.id,
|
|
categoryId: testCategory.id,
|
|
quizType: 'practice',
|
|
difficulty: 'medium',
|
|
totalQuestions: 10
|
|
});
|
|
await activeQuiz.start();
|
|
|
|
const foundActive = await QuizSession.findActiveForUser(testUser.id);
|
|
console.log('✅ Active session found');
|
|
console.log(' Found ID:', foundActive.id);
|
|
console.log(' Created ID:', activeQuiz.id);
|
|
console.log(' Match:', foundActive.id === activeQuiz.id ? '✅' : '❌');
|
|
|
|
// Test 15: Find active session for guest
|
|
console.log('\nTest 15: Find active session for guest');
|
|
await guestQuiz.start();
|
|
const foundGuestActive = await QuizSession.findActiveForGuest(testGuestSession.id);
|
|
console.log('✅ Active guest session found');
|
|
console.log(' Found ID:', foundGuestActive.id);
|
|
console.log(' Created ID:', guestQuiz.id);
|
|
console.log(' Match:', foundGuestActive.id === guestQuiz.id ? '✅' : '❌');
|
|
|
|
// Test 16: Get user quiz history
|
|
console.log('\nTest 16: Get user quiz history');
|
|
await activeQuiz.complete();
|
|
const history = await QuizSession.getUserHistory(testUser.id, 5);
|
|
console.log('✅ User history retrieved');
|
|
console.log(' History count:', history.length);
|
|
console.log(' Expected at least 3: ✅');
|
|
|
|
// Test 17: Get user statistics
|
|
console.log('\nTest 17: Get user statistics');
|
|
const stats = await QuizSession.getUserStats(testUser.id);
|
|
console.log('✅ User stats calculated');
|
|
console.log(' Total quizzes:', stats.totalQuizzes);
|
|
console.log(' Average score:', stats.averageScore + '%');
|
|
console.log(' Pass rate:', stats.passRate + '%');
|
|
console.log(' Total time spent:', stats.totalTimeSpent, 'seconds');
|
|
console.log(' Match:', stats.totalQuizzes >= 1 ? '✅' : '❌');
|
|
|
|
// Test 18: Get category statistics
|
|
console.log('\nTest 18: Get category statistics');
|
|
const categoryStats = await QuizSession.getCategoryStats(testCategory.id);
|
|
console.log('✅ Category stats calculated');
|
|
console.log(' Total attempts:', categoryStats.totalAttempts);
|
|
console.log(' Average score:', categoryStats.averageScore + '%');
|
|
console.log(' Pass rate:', categoryStats.passRate + '%');
|
|
console.log(' Match:', categoryStats.totalAttempts >= 1 ? '✅' : '❌');
|
|
|
|
// Test 19: Check isActive method
|
|
console.log('\nTest 19: Check isActive method');
|
|
const newQuiz = await QuizSession.createSession({
|
|
userId: testUser.id,
|
|
categoryId: testCategory.id,
|
|
quizType: 'practice',
|
|
totalQuestions: 5
|
|
});
|
|
const isActiveBeforeStart = newQuiz.isActive();
|
|
await newQuiz.start();
|
|
const isActiveAfterStart = newQuiz.isActive();
|
|
await newQuiz.complete();
|
|
const isActiveAfterComplete = newQuiz.isActive();
|
|
console.log('✅ Active status checked');
|
|
console.log(' Before start:', isActiveBeforeStart);
|
|
console.log(' After start:', isActiveAfterStart);
|
|
console.log(' After complete:', isActiveAfterComplete);
|
|
console.log(' Match:', !isActiveBeforeStart && isActiveAfterStart && !isActiveAfterComplete ? '✅' : '❌');
|
|
|
|
// Test 20: Check isCompleted method
|
|
console.log('\nTest 20: Check isCompleted method');
|
|
const completionQuiz = await QuizSession.createSession({
|
|
userId: testUser.id,
|
|
categoryId: testCategory.id,
|
|
quizType: 'practice',
|
|
totalQuestions: 3
|
|
});
|
|
const isCompletedBefore = completionQuiz.isCompleted();
|
|
await completionQuiz.start();
|
|
await completionQuiz.complete();
|
|
const isCompletedAfter = completionQuiz.isCompleted();
|
|
console.log('✅ Completion status checked');
|
|
console.log(' Before completion:', isCompletedBefore);
|
|
console.log(' After completion:', isCompletedAfter);
|
|
console.log(' Match:', !isCompletedBefore && isCompletedAfter ? '✅' : '❌');
|
|
|
|
// Test 21: Test validation - require either userId or guestSessionId
|
|
console.log('\nTest 21: Test validation - require userId or guestSessionId');
|
|
try {
|
|
await QuizSession.createSession({
|
|
categoryId: testCategory.id,
|
|
quizType: 'practice',
|
|
totalQuestions: 10
|
|
});
|
|
console.log('❌ Should have thrown validation error');
|
|
} catch (error) {
|
|
console.log('✅ Validation error caught:', error.message);
|
|
console.log(' Match:', error.message.includes('userId or guestSessionId') ? '✅' : '❌');
|
|
}
|
|
|
|
// Test 22: Test validation - cannot have both userId and guestSessionId
|
|
console.log('\nTest 22: Test validation - cannot have both userId and guestSessionId');
|
|
try {
|
|
await QuizSession.create({
|
|
userId: testUser.id,
|
|
guestSessionId: testGuestSession.id,
|
|
categoryId: testCategory.id,
|
|
quizType: 'practice',
|
|
totalQuestions: 10
|
|
});
|
|
console.log('❌ Should have thrown validation error');
|
|
} catch (error) {
|
|
console.log('✅ Validation error caught:', error.message);
|
|
console.log(' Match:', error.message.includes('Cannot have both') ? '✅' : '❌');
|
|
}
|
|
|
|
// Test 23: Test associations - load with user
|
|
console.log('\nTest 23: Load quiz session with user association');
|
|
const quizWithUser = await QuizSession.findOne({
|
|
where: { id: userQuiz.id },
|
|
include: [{ model: User, as: 'user' }]
|
|
});
|
|
console.log('✅ Quiz loaded with user');
|
|
console.log(' User username:', quizWithUser.user.username);
|
|
console.log(' Match:', quizWithUser.user.id === testUser.id ? '✅' : '❌');
|
|
|
|
// Test 24: Test associations - load with category
|
|
console.log('\nTest 24: Load quiz session with category association');
|
|
const quizWithCategory = await QuizSession.findOne({
|
|
where: { id: userQuiz.id },
|
|
include: [{ model: Category, as: 'category' }]
|
|
});
|
|
console.log('✅ Quiz loaded with category');
|
|
console.log(' Category name:', quizWithCategory.category.name);
|
|
console.log(' Match:', quizWithCategory.category.id === testCategory.id ? '✅' : '❌');
|
|
|
|
// Test 25: Test associations - load with guest session
|
|
console.log('\nTest 25: Load quiz session with guest session association');
|
|
const quizWithGuest = await QuizSession.findOne({
|
|
where: { id: guestQuiz.id },
|
|
include: [{ model: GuestSession, as: 'guestSession' }]
|
|
});
|
|
console.log('✅ Quiz loaded with guest session');
|
|
console.log(' Guest ID:', quizWithGuest.guestSession.guestId);
|
|
console.log(' Match:', quizWithGuest.guestSession.id === testGuestSession.id ? '✅' : '❌');
|
|
|
|
// Test 26: Clean up abandoned sessions
|
|
console.log('\nTest 26: Clean up abandoned sessions');
|
|
const oldQuiz = await QuizSession.create({
|
|
userId: testUser.id,
|
|
categoryId: testCategory.id,
|
|
quizType: 'practice',
|
|
totalQuestions: 10,
|
|
status: 'abandoned',
|
|
createdAt: new Date('2020-01-01')
|
|
});
|
|
const deletedCount = await QuizSession.cleanupAbandoned(7);
|
|
console.log('✅ Cleanup executed');
|
|
console.log(' Deleted count:', deletedCount);
|
|
console.log(' Expected at least 1:', deletedCount >= 1 ? '✅' : '❌');
|
|
|
|
console.log('\n=====================================');
|
|
console.log('🧹 Cleaning up test data...');
|
|
|
|
// Clean up test data
|
|
await QuizSession.destroy({ where: {} });
|
|
await GuestSession.destroy({ where: {} });
|
|
await Category.destroy({ where: {} });
|
|
await User.destroy({ where: {} });
|
|
|
|
console.log('✅ Test data deleted');
|
|
console.log('\n✅ All QuizSession Model Tests Completed!');
|
|
|
|
} catch (error) {
|
|
console.error('\n❌ Test failed with error:', error.message);
|
|
console.error('Error details:', error);
|
|
process.exit(1);
|
|
} finally {
|
|
await sequelize.close();
|
|
}
|
|
}
|
|
|
|
runTests();
|