302 lines
12 KiB
JavaScript
302 lines
12 KiB
JavaScript
const fs = require('fs');
|
||
const path = require('path');
|
||
const emailService = require('./src/services/EmailService');
|
||
const AuthService = require('./src/services/AuthService');
|
||
require('dotenv').config();
|
||
|
||
/**
|
||
* Verify that task 7 "Build email service integration" has been completed
|
||
* according to all the specified requirements
|
||
*/
|
||
async function verifyEmailTaskImplementation() {
|
||
console.log('🔍 Verifying Task 7: Build email service integration\n');
|
||
|
||
const results = {
|
||
passed: 0,
|
||
failed: 0,
|
||
details: []
|
||
};
|
||
|
||
function checkRequirement(description, condition, details = '') {
|
||
const status = condition ? '✅ PASS' : '❌ FAIL';
|
||
console.log(`${status}: ${description}`);
|
||
if (details) console.log(` ${details}`);
|
||
|
||
results.details.push({ description, passed: condition, details });
|
||
if (condition) results.passed++;
|
||
else results.failed++;
|
||
}
|
||
|
||
// Sub-task 1: Create email service module with nodemailer configuration
|
||
console.log('📋 Sub-task 1: Create email service module with nodemailer configuration');
|
||
|
||
const emailServiceExists = fs.existsSync('./src/services/EmailService.js');
|
||
checkRequirement(
|
||
'EmailService.js file exists',
|
||
emailServiceExists,
|
||
emailServiceExists ? 'File found at src/services/EmailService.js' : 'File not found'
|
||
);
|
||
|
||
if (emailServiceExists) {
|
||
const emailServiceContent = fs.readFileSync('./src/services/EmailService.js', 'utf8');
|
||
|
||
checkRequirement(
|
||
'Uses nodemailer for email transport',
|
||
emailServiceContent.includes('nodemailer') && emailServiceContent.includes('createTransport'),
|
||
'Nodemailer properly imported and configured'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Has proper configuration initialization',
|
||
emailServiceContent.includes('initializeTransporter') && emailServiceContent.includes('EMAIL_HOST'),
|
||
'Configuration reads from environment variables'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Has connection verification',
|
||
emailServiceContent.includes('verify') && emailServiceContent.includes('isConfigured'),
|
||
'Email service verifies connection and tracks configuration status'
|
||
);
|
||
}
|
||
|
||
// Sub-task 2: Implement email verification functionality with secure token generation
|
||
console.log('\n📋 Sub-task 2: Implement email verification functionality with secure token generation');
|
||
|
||
checkRequirement(
|
||
'Has secure token generation method',
|
||
typeof emailService.generateSecureToken === 'function',
|
||
'generateSecureToken method available'
|
||
);
|
||
|
||
if (typeof emailService.generateSecureToken === 'function') {
|
||
const token1 = emailService.generateSecureToken();
|
||
const token2 = emailService.generateSecureToken();
|
||
|
||
checkRequirement(
|
||
'Generates unique secure tokens',
|
||
token1 !== token2 && token1.length === 64,
|
||
`Token length: ${token1.length}, Unique: ${token1 !== token2}`
|
||
);
|
||
}
|
||
|
||
checkRequirement(
|
||
'Has email verification sending method',
|
||
typeof emailService.sendVerificationEmail === 'function',
|
||
'sendVerificationEmail method available'
|
||
);
|
||
|
||
// Sub-task 3: Build password reset email functionality with time-limited tokens
|
||
console.log('\n📋 Sub-task 3: Build password reset email functionality with time-limited tokens');
|
||
|
||
checkRequirement(
|
||
'Has reset token generation with expiration',
|
||
typeof emailService.generateResetToken === 'function',
|
||
'generateResetToken method available'
|
||
);
|
||
|
||
if (typeof emailService.generateResetToken === 'function') {
|
||
const resetData = emailService.generateResetToken(1);
|
||
|
||
checkRequirement(
|
||
'Reset token includes expiration time',
|
||
resetData.token && resetData.expires && resetData.expires instanceof Date,
|
||
`Token: ${!!resetData.token}, Expires: ${resetData.expires}`
|
||
);
|
||
|
||
checkRequirement(
|
||
'Reset token expires in future',
|
||
resetData.expires > new Date(),
|
||
`Expires at: ${resetData.expires}`
|
||
);
|
||
}
|
||
|
||
checkRequirement(
|
||
'Has password reset email sending method',
|
||
typeof emailService.sendPasswordResetEmail === 'function',
|
||
'sendPasswordResetEmail method available'
|
||
);
|
||
|
||
// Sub-task 4: Create email templates for verification and password reset
|
||
console.log('\n📋 Sub-task 4: Create email templates for verification and password reset');
|
||
|
||
checkRequirement(
|
||
'Has verification email template method',
|
||
typeof emailService.createVerificationEmailTemplate === 'function',
|
||
'createVerificationEmailTemplate method available'
|
||
);
|
||
|
||
if (typeof emailService.createVerificationEmailTemplate === 'function') {
|
||
const template = emailService.createVerificationEmailTemplate('test@example.com', 'test-token');
|
||
|
||
checkRequirement(
|
||
'Verification template has required components',
|
||
template.subject && template.html && template.text,
|
||
`Subject: ${!!template.subject}, HTML: ${!!template.html}, Text: ${!!template.text}`
|
||
);
|
||
|
||
checkRequirement(
|
||
'Verification template includes token in content',
|
||
template.html.includes('test-token') && template.text.includes('test-token'),
|
||
'Token properly embedded in both HTML and text versions'
|
||
);
|
||
}
|
||
|
||
checkRequirement(
|
||
'Has password reset email template method',
|
||
typeof emailService.createPasswordResetEmailTemplate === 'function',
|
||
'createPasswordResetEmailTemplate method available'
|
||
);
|
||
|
||
if (typeof emailService.createPasswordResetEmailTemplate === 'function') {
|
||
const template = emailService.createPasswordResetEmailTemplate('test@example.com', 'reset-token');
|
||
|
||
checkRequirement(
|
||
'Reset template has required components',
|
||
template.subject && template.html && template.text,
|
||
`Subject: ${!!template.subject}, HTML: ${!!template.html}, Text: ${!!template.text}`
|
||
);
|
||
|
||
checkRequirement(
|
||
'Reset template includes token in content',
|
||
template.html.includes('reset-token') && template.text.includes('reset-token'),
|
||
'Token properly embedded in both HTML and text versions'
|
||
);
|
||
}
|
||
|
||
// Sub-task 5: Add email sending error handling and retry logic
|
||
console.log('\n📋 Sub-task 5: Add email sending error handling and retry logic');
|
||
|
||
const emailServiceContent = fs.readFileSync('./src/services/EmailService.js', 'utf8');
|
||
|
||
checkRequirement(
|
||
'Has retry logic implementation',
|
||
emailServiceContent.includes('sendEmailWithRetry') && emailServiceContent.includes('retryAttempts'),
|
||
'sendEmailWithRetry method with configurable retry attempts'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Has exponential backoff for retries',
|
||
emailServiceContent.includes('Math.pow') && emailServiceContent.includes('retryDelay'),
|
||
'Exponential backoff implemented for retry delays'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Has comprehensive error handling',
|
||
emailServiceContent.includes('try') && emailServiceContent.includes('catch') && emailServiceContent.includes('throw'),
|
||
'Try-catch blocks and proper error propagation'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Has error logging',
|
||
emailServiceContent.includes('console.error') && emailServiceContent.includes('Failed to send'),
|
||
'Error logging for debugging and monitoring'
|
||
);
|
||
|
||
// Integration with AuthService
|
||
console.log('\n📋 Integration: AuthService updated to use new EmailService');
|
||
|
||
const authServiceContent = fs.readFileSync('./src/services/AuthService.js', 'utf8');
|
||
|
||
checkRequirement(
|
||
'AuthService imports EmailService',
|
||
authServiceContent.includes("require('./EmailService')"),
|
||
'EmailService properly imported in AuthService'
|
||
);
|
||
|
||
checkRequirement(
|
||
'AuthService uses EmailService for verification emails',
|
||
authServiceContent.includes('emailService.sendVerificationEmail'),
|
||
'Verification emails use new EmailService'
|
||
);
|
||
|
||
checkRequirement(
|
||
'AuthService uses EmailService for password reset emails',
|
||
authServiceContent.includes('emailService.sendPasswordResetEmail'),
|
||
'Password reset emails use new EmailService'
|
||
);
|
||
|
||
// Requirements verification
|
||
console.log('\n📋 Requirements Verification:');
|
||
|
||
checkRequirement(
|
||
'Requirement 1.5: Email verification functionality',
|
||
typeof emailService.sendVerificationEmail === 'function' &&
|
||
typeof AuthService.sendVerificationEmail === 'function',
|
||
'Email verification implemented in both services'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Requirement 1.7: Account activation via email',
|
||
emailServiceContent.includes('verification') && emailServiceContent.includes('activate'),
|
||
'Email templates support account activation flow'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Requirement 3.1: Password reset email functionality',
|
||
typeof emailService.sendPasswordResetEmail === 'function' &&
|
||
typeof AuthService.sendPasswordResetEmail === 'function',
|
||
'Password reset emails implemented in both services'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Requirement 3.7: Time-limited reset tokens',
|
||
typeof emailService.generateResetToken === 'function' &&
|
||
emailServiceContent.includes('expires'),
|
||
'Reset tokens have configurable expiration times'
|
||
);
|
||
|
||
// Additional functionality checks
|
||
console.log('\n📋 Additional Features:');
|
||
|
||
checkRequirement(
|
||
'Has service status checking',
|
||
typeof emailService.getStatus === 'function' && typeof emailService.testConfiguration === 'function',
|
||
'Service provides status and configuration testing'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Has generic notification email capability',
|
||
typeof emailService.sendNotificationEmail === 'function',
|
||
'Generic email sending for future extensibility'
|
||
);
|
||
|
||
checkRequirement(
|
||
'Professional email templates with styling',
|
||
emailServiceContent.includes('style') && emailServiceContent.includes('font-family'),
|
||
'Email templates include professional CSS styling'
|
||
);
|
||
|
||
// Summary
|
||
console.log('\n' + '='.repeat(60));
|
||
console.log('📊 TASK 7 VERIFICATION SUMMARY');
|
||
console.log('='.repeat(60));
|
||
console.log(`✅ Passed: ${results.passed}`);
|
||
console.log(`❌ Failed: ${results.failed}`);
|
||
console.log(`📈 Success Rate: ${Math.round((results.passed / (results.passed + results.failed)) * 100)}%`);
|
||
|
||
if (results.failed === 0) {
|
||
console.log('\n🎉 ALL REQUIREMENTS SATISFIED!');
|
||
console.log('Task 7: Build email service integration - COMPLETED ✅');
|
||
console.log('\n📋 Implementation includes:');
|
||
console.log('• Complete EmailService module with nodemailer configuration');
|
||
console.log('• Secure token generation for verification and password reset');
|
||
console.log('• Professional HTML and text email templates');
|
||
console.log('• Comprehensive error handling and retry logic');
|
||
console.log('• Full integration with existing AuthService');
|
||
console.log('• Support for all specified requirements (1.5, 1.7, 3.1, 3.7)');
|
||
} else {
|
||
console.log('\n⚠️ Some requirements need attention. See details above.');
|
||
}
|
||
|
||
return results.failed === 0;
|
||
}
|
||
|
||
// Run verification
|
||
verifyEmailTaskImplementation()
|
||
.then(success => {
|
||
process.exit(success ? 0 : 1);
|
||
})
|
||
.catch(error => {
|
||
console.error('Verification failed:', error);
|
||
process.exit(1);
|
||
}); |