320 lines
13 KiB
JavaScript
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();
|