154 lines
5.7 KiB
JavaScript
154 lines
5.7 KiB
JavaScript
require('dotenv').config();
|
|
const db = require('../models');
|
|
const { User } = db;
|
|
|
|
async function testUserModel() {
|
|
console.log('\n🧪 Testing User Model...\n');
|
|
|
|
try {
|
|
// Test 1: Create a test user
|
|
console.log('Test 1: Creating a test user...');
|
|
const testUser = await User.create({
|
|
username: 'testuser',
|
|
email: 'test@example.com',
|
|
password: 'password123',
|
|
role: 'user'
|
|
});
|
|
console.log('✅ User created successfully');
|
|
console.log(' - ID:', testUser.id);
|
|
console.log(' - Username:', testUser.username);
|
|
console.log(' - Email:', testUser.email);
|
|
console.log(' - Role:', testUser.role);
|
|
console.log(' - Password hashed:', testUser.password.substring(0, 20) + '...');
|
|
console.log(' - Password length:', testUser.password.length);
|
|
|
|
// Test 2: Verify password hashing
|
|
console.log('\nTest 2: Testing password hashing...');
|
|
const isPasswordHashed = testUser.password !== 'password123';
|
|
console.log('✅ Password is hashed:', isPasswordHashed);
|
|
console.log(' - Original: password123');
|
|
console.log(' - Hashed:', testUser.password.substring(0, 30) + '...');
|
|
|
|
// Test 3: Test password comparison
|
|
console.log('\nTest 3: Testing password comparison...');
|
|
const isCorrectPassword = await testUser.comparePassword('password123');
|
|
const isWrongPassword = await testUser.comparePassword('wrongpassword');
|
|
console.log('✅ Correct password:', isCorrectPassword);
|
|
console.log('✅ Wrong password rejected:', !isWrongPassword);
|
|
|
|
// Test 4: Test toJSON (password should be excluded)
|
|
console.log('\nTest 4: Testing toJSON (password exclusion)...');
|
|
const userJSON = testUser.toJSON();
|
|
const hasPassword = 'password' in userJSON;
|
|
console.log('✅ Password excluded from JSON:', !hasPassword);
|
|
console.log(' JSON keys:', Object.keys(userJSON).join(', '));
|
|
|
|
// Test 5: Test findByEmail
|
|
console.log('\nTest 5: Testing findByEmail...');
|
|
const foundUser = await User.findByEmail('test@example.com');
|
|
console.log('✅ User found by email:', foundUser ? 'Yes' : 'No');
|
|
console.log(' - Username:', foundUser.username);
|
|
|
|
// Test 6: Test findByUsername
|
|
console.log('\nTest 6: Testing findByUsername...');
|
|
const foundByUsername = await User.findByUsername('testuser');
|
|
console.log('✅ User found by username:', foundByUsername ? 'Yes' : 'No');
|
|
|
|
// Test 7: Test streak calculation
|
|
console.log('\nTest 7: Testing streak calculation...');
|
|
testUser.updateStreak();
|
|
console.log('✅ Streak updated');
|
|
console.log(' - Current streak:', testUser.currentStreak);
|
|
console.log(' - Longest streak:', testUser.longestStreak);
|
|
console.log(' - Last quiz date:', testUser.lastQuizDate);
|
|
|
|
// Test 8: Test accuracy calculation
|
|
console.log('\nTest 8: Testing accuracy calculation...');
|
|
testUser.totalQuestionsAnswered = 10;
|
|
testUser.correctAnswers = 8;
|
|
const accuracy = testUser.calculateAccuracy();
|
|
console.log('✅ Accuracy calculated:', accuracy + '%');
|
|
|
|
// Test 9: Test pass rate calculation
|
|
console.log('\nTest 9: Testing pass rate calculation...');
|
|
testUser.totalQuizzes = 5;
|
|
testUser.quizzesPassed = 4;
|
|
const passRate = testUser.getPassRate();
|
|
console.log('✅ Pass rate calculated:', passRate + '%');
|
|
|
|
// Test 10: Test unique constraints
|
|
console.log('\nTest 10: Testing unique constraints...');
|
|
try {
|
|
await User.create({
|
|
username: 'testuser', // Duplicate username
|
|
email: 'another@example.com',
|
|
password: 'password123'
|
|
});
|
|
console.log('❌ Unique constraint not working');
|
|
} catch (error) {
|
|
if (error.name === 'SequelizeUniqueConstraintError') {
|
|
console.log('✅ Unique username constraint working');
|
|
}
|
|
}
|
|
|
|
// Test 11: Test email validation
|
|
console.log('\nTest 11: Testing email validation...');
|
|
try {
|
|
await User.create({
|
|
username: 'invaliduser',
|
|
email: 'not-an-email', // Invalid email
|
|
password: 'password123'
|
|
});
|
|
console.log('❌ Email validation not working');
|
|
} catch (error) {
|
|
if (error.name === 'SequelizeValidationError') {
|
|
console.log('✅ Email validation working');
|
|
}
|
|
}
|
|
|
|
// Test 12: Test password update
|
|
console.log('\nTest 12: Testing password update...');
|
|
const oldPassword = testUser.password;
|
|
testUser.password = 'newpassword456';
|
|
await testUser.save();
|
|
const passwordChanged = oldPassword !== testUser.password;
|
|
console.log('✅ Password re-hashed on update:', passwordChanged);
|
|
const newPasswordWorks = await testUser.comparePassword('newpassword456');
|
|
console.log('✅ New password works:', newPasswordWorks);
|
|
|
|
// Cleanup
|
|
console.log('\n🧹 Cleaning up test data...');
|
|
await testUser.destroy();
|
|
console.log('✅ Test user deleted');
|
|
|
|
console.log('\n' + '='.repeat(60));
|
|
console.log('✅ ALL TESTS PASSED!');
|
|
console.log('='.repeat(60));
|
|
console.log('\nUser Model Summary:');
|
|
console.log('- ✅ User creation with UUID');
|
|
console.log('- ✅ Password hashing (bcrypt)');
|
|
console.log('- ✅ Password comparison');
|
|
console.log('- ✅ toJSON excludes password');
|
|
console.log('- ✅ Find by email/username');
|
|
console.log('- ✅ Streak calculation');
|
|
console.log('- ✅ Accuracy/pass rate calculation');
|
|
console.log('- ✅ Unique constraints');
|
|
console.log('- ✅ Email validation');
|
|
console.log('- ✅ Password update & re-hash');
|
|
console.log('\n');
|
|
|
|
process.exit(0);
|
|
} catch (error) {
|
|
console.error('\n❌ Test failed:', error.message);
|
|
if (error.errors) {
|
|
error.errors.forEach(err => {
|
|
console.error(' -', err.message);
|
|
});
|
|
}
|
|
console.error('\nStack:', error.stack);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
testUserModel();
|