Files
bookmarksite/tests/test-resend-verification.js
2025-07-20 20:43:06 +02:00

414 lines
14 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Test script to verify resend verification email functionality
* This script tests the complete flow of resending verification emails
*/
const readline = require('readline');
const API_BASE_URL = 'http://localhost:3001/api';
// Colors for console output
const colors = {
green: '\x1b[32m',
red: '\x1b[31m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
reset: '\x1b[0m',
bold: '\x1b[1m'
};
function log(message, color = colors.reset) {
console.log(`${color}${message}${colors.reset}`);
}
function success(message) {
log(`${message}`, colors.green);
}
function error(message) {
log(`${message}`, colors.red);
}
function warning(message) {
log(`⚠️ ${message}`, colors.yellow);
}
function info(message) {
log(` ${message}`, colors.blue);
}
class ResendVerificationTester {
constructor() {
this.testEmail = `test-resend-${Date.now()}@example.com`;
this.testPassword = 'TestPassword123!';
}
/**
* Check if the server is running
*/
async checkServerHealth() {
try {
const response = await fetch(`${API_BASE_URL.replace('/api', '')}/health`);
if (response.ok) {
const data = await response.json();
success('Server is running and healthy');
return true;
} else {
error('Server health check failed');
return false;
}
} catch (err) {
error(`Server is not running: ${err.message}`);
return false;
}
}
/**
* Register a test user
*/
async registerTestUser() {
try {
info(`Registering test user: ${this.testEmail}`);
const response = await fetch(`${API_BASE_URL}/auth/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: this.testEmail,
password: this.testPassword
})
});
const data = await response.json();
if (response.ok) {
success('Test user registered successfully');
info(`User ID: ${data.user?.id}`);
return { success: true, user: data.user };
} else {
error(`Registration failed: ${data.error}`);
return { success: false, error: data.error };
}
} catch (err) {
error(`Registration error: ${err.message}`);
return { success: false, error: err.message };
}
}
/**
* Test resend verification email with valid email
*/
async testResendVerificationValid() {
try {
info('Testing resend verification with valid unverified email...');
const response = await fetch(`${API_BASE_URL}/auth/resend-verification`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: this.testEmail
})
});
const data = await response.json();
if (response.ok) {
success('Resend verification request successful');
info(`Message: ${data.message}`);
return { success: true, message: data.message };
} else {
error(`Resend verification failed: ${data.error}`);
return { success: false, error: data.error };
}
} catch (err) {
error(`Resend verification error: ${err.message}`);
return { success: false, error: err.message };
}
}
/**
* Test resend verification email with non-existent email
*/
async testResendVerificationNonExistent() {
try {
info('Testing resend verification with non-existent email...');
const nonExistentEmail = `nonexistent-${Date.now()}@example.com`;
const response = await fetch(`${API_BASE_URL}/auth/resend-verification`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: nonExistentEmail
})
});
const data = await response.json();
if (response.ok) {
success('Resend verification with non-existent email handled correctly');
info(`Message: ${data.message}`);
return { success: true, message: data.message };
} else {
warning(`Unexpected response for non-existent email: ${data.error}`);
return { success: false, error: data.error };
}
} catch (err) {
error(`Resend verification error: ${err.message}`);
return { success: false, error: err.message };
}
}
/**
* Test resend verification email with missing email
*/
async testResendVerificationMissingEmail() {
try {
info('Testing resend verification with missing email...');
const response = await fetch(`${API_BASE_URL}/auth/resend-verification`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({})
});
const data = await response.json();
if (response.status === 400) {
success('Missing email validation working correctly');
info(`Error: ${data.error}`);
return { success: true, error: data.error };
} else {
error(`Expected 400 status for missing email, got ${response.status}`);
return { success: false, error: 'Unexpected response status' };
}
} catch (err) {
error(`Resend verification error: ${err.message}`);
return { success: false, error: err.message };
}
}
/**
* Test resend verification email with invalid email format
*/
async testResendVerificationInvalidEmail() {
try {
info('Testing resend verification with invalid email format...');
const response = await fetch(`${API_BASE_URL}/auth/resend-verification`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'invalid-email-format'
})
});
const data = await response.json();
// The endpoint should still return success for security reasons
if (response.ok) {
success('Invalid email format handled correctly (security response)');
info(`Message: ${data.message}`);
return { success: true, message: data.message };
} else {
warning(`Unexpected response for invalid email: ${data.error}`);
return { success: false, error: data.error };
}
} catch (err) {
error(`Resend verification error: ${err.message}`);
return { success: false, error: err.message };
}
}
/**
* Test rate limiting on resend verification
*/
async testResendVerificationRateLimit() {
try {
info('Testing rate limiting on resend verification...');
const requests = [];
const maxRequests = 6; // Should exceed the rate limit
for (let i = 0; i < maxRequests; i++) {
requests.push(
fetch(`${API_BASE_URL}/auth/resend-verification`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: this.testEmail
})
})
);
}
const responses = await Promise.all(requests);
const rateLimitedResponses = responses.filter(r => r.status === 429);
if (rateLimitedResponses.length > 0) {
success(`Rate limiting working: ${rateLimitedResponses.length} requests were rate limited`);
return { success: true, rateLimited: rateLimitedResponses.length };
} else {
warning('Rate limiting may not be working as expected');
return { success: false, error: 'No rate limiting detected' };
}
} catch (err) {
error(`Rate limit test error: ${err.message}`);
return { success: false, error: err.message };
}
}
/**
* Check email service configuration
*/
async checkEmailServiceConfig() {
try {
info('Checking email service configuration...');
// This would require a dedicated endpoint to check email config
// For now, we'll just check if the service responds properly
const response = await fetch(`${API_BASE_URL}/auth/resend-verification`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'test@example.com'
})
});
if (response.ok || response.status === 400) {
success('Email service endpoint is accessible');
return { success: true };
} else {
error('Email service endpoint may have issues');
return { success: false };
}
} catch (err) {
error(`Email service check error: ${err.message}`);
return { success: false, error: err.message };
}
}
/**
* Clean up test data
*/
async cleanup() {
try {
info('Cleaning up test data...');
// Note: In a real scenario, you'd want to clean up the test user
// This would require a dedicated cleanup endpoint or direct database access
warning('Manual cleanup may be required for test user data');
return { success: true };
} catch (err) {
error(`Cleanup error: ${err.message}`);
return { success: false, error: err.message };
}
}
/**
* Run all tests
*/
async runAllTests() {
log('\n' + '='.repeat(60), colors.bold);
log('🧪 RESEND VERIFICATION EMAIL FUNCTIONALITY TEST', colors.bold);
log('='.repeat(60), colors.bold);
const results = {
total: 0,
passed: 0,
failed: 0
};
const tests = [
{ name: 'Server Health Check', fn: () => this.checkServerHealth() },
{ name: 'Email Service Configuration', fn: () => this.checkEmailServiceConfig() },
{ name: 'User Registration', fn: () => this.registerTestUser() },
{ name: 'Resend Verification (Valid Email)', fn: () => this.testResendVerificationValid() },
{ name: 'Resend Verification (Non-existent Email)', fn: () => this.testResendVerificationNonExistent() },
{ name: 'Resend Verification (Missing Email)', fn: () => this.testResendVerificationMissingEmail() },
{ name: 'Resend Verification (Invalid Email)', fn: () => this.testResendVerificationInvalidEmail() },
{ name: 'Rate Limiting Test', fn: () => this.testResendVerificationRateLimit() },
{ name: 'Cleanup', fn: () => this.cleanup() }
];
for (const test of tests) {
log(`\n📋 Running: ${test.name}`, colors.yellow);
log('-'.repeat(40));
try {
const result = await test.fn();
results.total++;
if (result.success) {
results.passed++;
success(`${test.name} - PASSED`);
} else {
results.failed++;
error(`${test.name} - FAILED: ${result.error || 'Unknown error'}`);
}
} catch (err) {
results.total++;
results.failed++;
error(`${test.name} - ERROR: ${err.message}`);
}
}
// Final results
log('\n' + '='.repeat(60), colors.bold);
log('📊 TEST RESULTS SUMMARY', colors.bold);
log('='.repeat(60), colors.bold);
log(`Total Tests: ${results.total}`);
success(`Passed: ${results.passed}`);
if (results.failed > 0) {
error(`Failed: ${results.failed}`);
} else {
log(`Failed: ${results.failed}`);
}
const successRate = ((results.passed / results.total) * 100).toFixed(1);
log(`Success Rate: ${successRate}%`);
if (results.failed === 0) {
success('\n🎉 All tests passed! Resend verification functionality is working correctly.');
} else {
warning('\n⚠ Some tests failed. Please review the issues above.');
}
return results;
}
}
// Main execution
async function main() {
const tester = new ResendVerificationTester();
try {
await tester.runAllTests();
} catch (err) {
error(`Test execution failed: ${err.message}`);
process.exit(1);
}
}
// Run if called directly
if (require.main === module) {
main().catch(console.error);
}
module.exports = ResendVerificationTester;