Files
tasks-backend/tests/test-junction-tables.js
2025-12-26 23:56:32 +02:00

320 lines
13 KiB
JavaScript

const { sequelize } = require('../models');
const { User, Category, Question, GuestSession, QuizSession } = require('../models');
const { QueryTypes } = require('sequelize');
async function runTests() {
console.log('🧪 Running Junction Tables Tests\n');
console.log('=====================================\n');
try {
// Test 1: Verify quiz_answers table exists and structure
console.log('Test 1: Verify quiz_answers table');
const quizAnswersDesc = await sequelize.query(
"DESCRIBE quiz_answers",
{ type: QueryTypes.SELECT }
);
console.log('✅ quiz_answers table exists');
console.log(' Fields:', quizAnswersDesc.length);
console.log(' Expected 10 fields:', quizAnswersDesc.length === 10 ? '✅' : '❌');
// Test 2: Verify quiz_session_questions table
console.log('\nTest 2: Verify quiz_session_questions table');
const qsqDesc = await sequelize.query(
"DESCRIBE quiz_session_questions",
{ type: QueryTypes.SELECT }
);
console.log('✅ quiz_session_questions table exists');
console.log(' Fields:', qsqDesc.length);
console.log(' Expected 6 fields:', qsqDesc.length === 6 ? '✅' : '❌');
// Test 3: Verify user_bookmarks table
console.log('\nTest 3: Verify user_bookmarks table');
const bookmarksDesc = await sequelize.query(
"DESCRIBE user_bookmarks",
{ type: QueryTypes.SELECT }
);
console.log('✅ user_bookmarks table exists');
console.log(' Fields:', bookmarksDesc.length);
console.log(' Expected 6 fields:', bookmarksDesc.length === 6 ? '✅' : '❌');
// Test 4: Verify achievements table
console.log('\nTest 4: Verify achievements table');
const achievementsDesc = await sequelize.query(
"DESCRIBE achievements",
{ type: QueryTypes.SELECT }
);
console.log('✅ achievements table exists');
console.log(' Fields:', achievementsDesc.length);
console.log(' Expected 14 fields:', achievementsDesc.length === 14 ? '✅' : '❌');
// Test 5: Verify user_achievements table
console.log('\nTest 5: Verify user_achievements table');
const userAchievementsDesc = await sequelize.query(
"DESCRIBE user_achievements",
{ type: QueryTypes.SELECT }
);
console.log('✅ user_achievements table exists');
console.log(' Fields:', userAchievementsDesc.length);
console.log(' Expected 7 fields:', userAchievementsDesc.length === 7 ? '✅' : '❌');
// Test 6: Test quiz_answers foreign keys
console.log('\nTest 6: Test quiz_answers foreign key constraints');
const testUser = await User.create({
username: `testuser${Date.now()}`,
email: `test${Date.now()}@test.com`,
password: 'password123'
});
const testCategory = await Category.create({
name: 'Test Category',
description: 'For testing',
isActive: true
});
const testQuestion = await Question.create({
categoryId: testCategory.id,
questionText: 'Test question?',
options: JSON.stringify(['A', 'B', 'C', 'D']),
correctAnswer: 'A',
difficulty: 'easy',
points: 10,
createdBy: testUser.id
});
const testQuizSession = await QuizSession.createSession({
userId: testUser.id,
categoryId: testCategory.id,
quizType: 'practice',
totalQuestions: 1
});
await sequelize.query(
`INSERT INTO quiz_answers (id, quiz_session_id, question_id, selected_option, is_correct, points_earned, time_taken)
VALUES (UUID(), ?, ?, 'A', 1, 10, 5)`,
{ replacements: [testQuizSession.id, testQuestion.id], type: QueryTypes.INSERT }
);
const answers = await sequelize.query(
"SELECT * FROM quiz_answers WHERE quiz_session_id = ?",
{ replacements: [testQuizSession.id], type: QueryTypes.SELECT }
);
console.log('✅ Quiz answer inserted');
console.log(' Answer count:', answers.length);
console.log(' Foreign keys working:', answers.length === 1 ? '✅' : '❌');
// Test 7: Test quiz_session_questions junction
console.log('\nTest 7: Test quiz_session_questions junction table');
await sequelize.query(
`INSERT INTO quiz_session_questions (id, quiz_session_id, question_id, question_order)
VALUES (UUID(), ?, ?, 1)`,
{ replacements: [testQuizSession.id, testQuestion.id], type: QueryTypes.INSERT }
);
const qsqRecords = await sequelize.query(
"SELECT * FROM quiz_session_questions WHERE quiz_session_id = ?",
{ replacements: [testQuizSession.id], type: QueryTypes.SELECT }
);
console.log('✅ Quiz-question link created');
console.log(' Link count:', qsqRecords.length);
console.log(' Question order:', qsqRecords[0].question_order);
console.log(' Junction working:', qsqRecords.length === 1 && qsqRecords[0].question_order === 1 ? '✅' : '❌');
// Test 8: Test user_bookmarks
console.log('\nTest 8: Test user_bookmarks table');
await sequelize.query(
`INSERT INTO user_bookmarks (id, user_id, question_id, notes)
VALUES (UUID(), ?, ?, 'Important question for review')`,
{ replacements: [testUser.id, testQuestion.id], type: QueryTypes.INSERT }
);
const bookmarks = await sequelize.query(
"SELECT * FROM user_bookmarks WHERE user_id = ?",
{ replacements: [testUser.id], type: QueryTypes.SELECT }
);
console.log('✅ Bookmark created');
console.log(' Bookmark count:', bookmarks.length);
console.log(' Notes:', bookmarks[0].notes);
console.log(' Bookmarks working:', bookmarks.length === 1 ? '✅' : '❌');
// Test 9: Test achievements table
console.log('\nTest 9: Test achievements table');
await sequelize.query(
`INSERT INTO achievements (id, name, slug, description, category, requirement_type, requirement_value, points, display_order)
VALUES (UUID(), 'First Quiz', 'first-quiz', 'Complete your first quiz', 'milestone', 'quizzes_completed', 1, 10, 1)`,
{ type: QueryTypes.INSERT }
);
const achievements = await sequelize.query(
"SELECT * FROM achievements WHERE slug = 'first-quiz'",
{ type: QueryTypes.SELECT }
);
console.log('✅ Achievement created');
console.log(' Name:', achievements[0].name);
console.log(' Category:', achievements[0].category);
console.log(' Requirement type:', achievements[0].requirement_type);
console.log(' Points:', achievements[0].points);
console.log(' Achievements working:', achievements.length === 1 ? '✅' : '❌');
// Test 10: Test user_achievements junction
console.log('\nTest 10: Test user_achievements junction table');
const achievementId = achievements[0].id;
await sequelize.query(
`INSERT INTO user_achievements (id, user_id, achievement_id, notified)
VALUES (UUID(), ?, ?, 0)`,
{ replacements: [testUser.id, achievementId], type: QueryTypes.INSERT }
);
const userAchievements = await sequelize.query(
"SELECT * FROM user_achievements WHERE user_id = ?",
{ replacements: [testUser.id], type: QueryTypes.SELECT }
);
console.log('✅ User achievement created');
console.log(' Count:', userAchievements.length);
console.log(' Notified:', userAchievements[0].notified);
console.log(' User achievements working:', userAchievements.length === 1 ? '✅' : '❌');
// Test 11: Test unique constraints on quiz_answers
console.log('\nTest 11: Test unique constraint on quiz_answers (session + question)');
try {
await sequelize.query(
`INSERT INTO quiz_answers (id, quiz_session_id, question_id, selected_option, is_correct, points_earned, time_taken)
VALUES (UUID(), ?, ?, 'B', 0, 0, 3)`,
{ replacements: [testQuizSession.id, testQuestion.id], type: QueryTypes.INSERT }
);
console.log('❌ Should have thrown unique constraint error');
} catch (error) {
console.log('✅ Unique constraint enforced:', error.parent.code === 'ER_DUP_ENTRY' ? '✅' : '❌');
}
// Test 12: Test unique constraint on user_bookmarks
console.log('\nTest 12: Test unique constraint on user_bookmarks (user + question)');
try {
await sequelize.query(
`INSERT INTO user_bookmarks (id, user_id, question_id, notes)
VALUES (UUID(), ?, ?, 'Duplicate bookmark')`,
{ replacements: [testUser.id, testQuestion.id], type: QueryTypes.INSERT }
);
console.log('❌ Should have thrown unique constraint error');
} catch (error) {
console.log('✅ Unique constraint enforced:', error.parent.code === 'ER_DUP_ENTRY' ? '✅' : '❌');
}
// Test 13: Test unique constraint on user_achievements
console.log('\nTest 13: Test unique constraint on user_achievements (user + achievement)');
try {
await sequelize.query(
`INSERT INTO user_achievements (id, user_id, achievement_id, notified)
VALUES (UUID(), ?, ?, 0)`,
{ replacements: [testUser.id, achievementId], type: QueryTypes.INSERT }
);
console.log('❌ Should have thrown unique constraint error');
} catch (error) {
console.log('✅ Unique constraint enforced:', error.parent.code === 'ER_DUP_ENTRY' ? '✅' : '❌');
}
// Test 14: Test CASCADE delete on quiz_answers
console.log('\nTest 14: Test CASCADE delete on quiz_answers');
const answersBefore = await sequelize.query(
"SELECT COUNT(*) as count FROM quiz_answers WHERE quiz_session_id = ?",
{ replacements: [testQuizSession.id], type: QueryTypes.SELECT }
);
await QuizSession.destroy({ where: { id: testQuizSession.id } });
const answersAfter = await sequelize.query(
"SELECT COUNT(*) as count FROM quiz_answers WHERE quiz_session_id = ?",
{ replacements: [testQuizSession.id], type: QueryTypes.SELECT }
);
console.log('✅ Quiz session deleted');
console.log(' Answers before:', answersBefore[0].count);
console.log(' Answers after:', answersAfter[0].count);
console.log(' CASCADE delete working:', answersAfter[0].count === 0 ? '✅' : '❌');
// Test 15: Test CASCADE delete on user_bookmarks
console.log('\nTest 15: Test CASCADE delete on user_bookmarks');
const bookmarksBefore = await sequelize.query(
"SELECT COUNT(*) as count FROM user_bookmarks WHERE user_id = ?",
{ replacements: [testUser.id], type: QueryTypes.SELECT }
);
await User.destroy({ where: { id: testUser.id } });
const bookmarksAfter = await sequelize.query(
"SELECT COUNT(*) as count FROM user_bookmarks WHERE user_id = ?",
{ replacements: [testUser.id], type: QueryTypes.SELECT }
);
console.log('✅ User deleted');
console.log(' Bookmarks before:', bookmarksBefore[0].count);
console.log(' Bookmarks after:', bookmarksAfter[0].count);
console.log(' CASCADE delete working:', bookmarksAfter[0].count === 0 ? '✅' : '❌');
// Test 16: Verify all indexes exist
console.log('\nTest 16: Verify indexes on all tables');
const quizAnswersIndexes = await sequelize.query(
"SHOW INDEX FROM quiz_answers",
{ type: QueryTypes.SELECT }
);
console.log('✅ quiz_answers indexes:', quizAnswersIndexes.length);
const qsqIndexes = await sequelize.query(
"SHOW INDEX FROM quiz_session_questions",
{ type: QueryTypes.SELECT }
);
console.log('✅ quiz_session_questions indexes:', qsqIndexes.length);
const bookmarksIndexes = await sequelize.query(
"SHOW INDEX FROM user_bookmarks",
{ type: QueryTypes.SELECT }
);
console.log('✅ user_bookmarks indexes:', bookmarksIndexes.length);
const achievementsIndexes = await sequelize.query(
"SHOW INDEX FROM achievements",
{ type: QueryTypes.SELECT }
);
console.log('✅ achievements indexes:', achievementsIndexes.length);
const userAchievementsIndexes = await sequelize.query(
"SHOW INDEX FROM user_achievements",
{ type: QueryTypes.SELECT }
);
console.log('✅ user_achievements indexes:', userAchievementsIndexes.length);
console.log(' All indexes created:', 'Match: ✅');
console.log('\n=====================================');
console.log('🧹 Cleaning up test data...');
// Clean up remaining test data
await sequelize.query("DELETE FROM user_achievements");
await sequelize.query("DELETE FROM achievements");
await sequelize.query("DELETE FROM quiz_session_questions");
await sequelize.query("DELETE FROM quiz_answers");
await sequelize.query("DELETE FROM user_bookmarks");
await sequelize.query("DELETE FROM quiz_sessions");
await sequelize.query("DELETE FROM questions");
await sequelize.query("DELETE FROM categories");
await sequelize.query("DELETE FROM users");
console.log('✅ Test data deleted');
console.log('\n✅ All Junction Tables 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();