- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
335 lines
12 KiB
PHP
335 lines
12 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
require_once __DIR__ . '/../bootstrap.php';
|
||
|
||
use App\Framework\Queue\Wrappers\EmailQueue;
|
||
use App\Framework\Queue\InMemoryQueue;
|
||
use App\Framework\Queue\ValueObjects\QueuePriority;
|
||
use App\Framework\Core\ValueObjects\Duration;
|
||
|
||
// Example Email Classes für Tests
|
||
class WelcomeEmail
|
||
{
|
||
public function __construct(
|
||
public string $recipient,
|
||
public string $userName
|
||
) {}
|
||
}
|
||
|
||
class TransactionalOrderConfirmationEmail
|
||
{
|
||
public function __construct(
|
||
public string $recipient,
|
||
public string $orderId,
|
||
public float $total
|
||
) {}
|
||
}
|
||
|
||
class MarketingNewsletterEmail
|
||
{
|
||
public function __construct(
|
||
public string $recipient,
|
||
public string $campaignId
|
||
) {}
|
||
}
|
||
|
||
class SystemAdminAlertEmail
|
||
{
|
||
public function __construct(
|
||
public string $recipient,
|
||
public string $alertMessage,
|
||
public string $severity
|
||
) {}
|
||
}
|
||
|
||
class BulkPromotionEmail
|
||
{
|
||
public function __construct(
|
||
public string $recipient,
|
||
public string $promoCode,
|
||
public float $discount
|
||
) {}
|
||
}
|
||
|
||
class CriticalSecurityNotificationEmail
|
||
{
|
||
public function __construct(
|
||
public string $recipient,
|
||
public string $securityIssue
|
||
) {}
|
||
}
|
||
|
||
class ReminderFollowUpEmail
|
||
{
|
||
public function __construct(
|
||
public string $recipient,
|
||
public string $taskId
|
||
) {}
|
||
}
|
||
|
||
class InvoiceEmail
|
||
{
|
||
public function __construct(
|
||
public string $recipient,
|
||
public string $invoiceNumber
|
||
) {}
|
||
}
|
||
|
||
echo "📧 Testing EmailQueue Implementation\n";
|
||
echo "====================================\n\n";
|
||
|
||
// Test 1: Basic Email Queue Operations
|
||
echo "1️⃣ Testing Basic Email Operations...\n";
|
||
|
||
$queue = new InMemoryQueue();
|
||
$emailQueue = new EmailQueue($queue);
|
||
|
||
$welcomeEmail = new WelcomeEmail('user@example.com', 'John Doe');
|
||
$orderEmail = new TransactionalOrderConfirmationEmail('customer@example.com', 'order-123', 99.99);
|
||
|
||
$emailQueue->pushEmail($welcomeEmail);
|
||
$emailQueue->pushEmail($orderEmail);
|
||
|
||
assert($emailQueue->size() === 2, "❌ Queue size should be 2");
|
||
assert(!$emailQueue->isEmpty(), "❌ Queue should not be empty");
|
||
|
||
$poppedEmail = $emailQueue->popEmail();
|
||
assert($poppedEmail instanceof WelcomeEmail || $poppedEmail instanceof TransactionalOrderConfirmationEmail, "❌ Should pop valid email");
|
||
|
||
echo "✅ Basic email operations work correctly\n\n";
|
||
|
||
// Test 2: Email Type Methods
|
||
echo "2️⃣ Testing Email Type Methods...\n";
|
||
|
||
$emailQueue->clear();
|
||
|
||
$transactionalEmail = new TransactionalOrderConfirmationEmail('trans@example.com', 'order-456', 150.00);
|
||
$marketingEmail = new MarketingNewsletterEmail('marketing@example.com', 'campaign-789');
|
||
$systemEmail = new SystemAdminAlertEmail('admin@example.com', 'High CPU usage detected', 'warning');
|
||
$bulkEmail = new BulkPromotionEmail('bulk@example.com', 'SAVE20', 20.0);
|
||
$criticalEmail = new CriticalSecurityNotificationEmail('security@example.com', 'Multiple failed login attempts');
|
||
|
||
// Push verschiedene Email-Typen
|
||
$emailQueue->pushTransactionalEmail($transactionalEmail);
|
||
$emailQueue->pushMarketingEmail($marketingEmail);
|
||
$emailQueue->pushSystemEmail($systemEmail);
|
||
$emailQueue->pushBulkEmail($bulkEmail);
|
||
$emailQueue->pushCriticalEmail($criticalEmail);
|
||
|
||
assert($emailQueue->size() === 5, "❌ Queue should contain 5 emails");
|
||
|
||
// Critical Email sollte höchste Priorität haben
|
||
$firstEmail = $emailQueue->popEmail();
|
||
$payload = $emailQueue->popEmailWithMetadata();
|
||
assert($payload !== null, "❌ Should have email with metadata");
|
||
|
||
echo "✅ Email type methods work correctly\n\n";
|
||
|
||
// Test 3: Scheduled Emails
|
||
echo "3️⃣ Testing Scheduled Emails...\n";
|
||
|
||
$emailQueue->clear();
|
||
|
||
$scheduledEmail = new WelcomeEmail('scheduled@example.com', 'Scheduled User');
|
||
$delay = Duration::fromHours(2);
|
||
|
||
$emailQueue->pushScheduledEmail($scheduledEmail, $delay);
|
||
|
||
$payload = $emailQueue->popEmailWithMetadata();
|
||
assert($payload !== null, "❌ Should have scheduled email");
|
||
assert($payload->delay->equals($delay), "❌ Delay should match");
|
||
assert($payload->job instanceof WelcomeEmail, "❌ Should be WelcomeEmail");
|
||
|
||
echo "✅ Scheduled emails work correctly\n\n";
|
||
|
||
// Test 4: Reminder Emails
|
||
echo "4️⃣ Testing Reminder Emails...\n";
|
||
|
||
$emailQueue->clear();
|
||
|
||
$reminderEmail = new ReminderFollowUpEmail('reminder@example.com', 'task-123');
|
||
$reminderDelay = Duration::fromDays(1);
|
||
|
||
$emailQueue->pushReminderEmail($reminderEmail, $reminderDelay);
|
||
|
||
$payload = $emailQueue->popEmailWithMetadata();
|
||
assert($payload !== null, "❌ Should have reminder email");
|
||
assert($payload->delay->equals($reminderDelay), "❌ Reminder delay should match");
|
||
|
||
echo "✅ Reminder emails work correctly\n\n";
|
||
|
||
// Test 5: Batch Operations
|
||
echo "5️⃣ Testing Batch Operations...\n";
|
||
|
||
$emailQueue->clear();
|
||
|
||
$emails = [
|
||
new WelcomeEmail('batch1@example.com', 'User 1'),
|
||
new WelcomeEmail('batch2@example.com', 'User 2'),
|
||
new TransactionalOrderConfirmationEmail('batch3@example.com', 'order-batch', 75.00),
|
||
new MarketingNewsletterEmail('batch4@example.com', 'batch-campaign')
|
||
];
|
||
|
||
// Test batch push
|
||
$emailQueue->pushBatch($emails, QueuePriority::high());
|
||
assert($emailQueue->size() === 4, "❌ Should have 4 emails after batch push");
|
||
|
||
// Test batch pop
|
||
$poppedEmails = $emailQueue->popBatch(2);
|
||
assert(count($poppedEmails) === 2, "❌ Should pop 2 emails");
|
||
assert($emailQueue->size() === 2, "❌ Should have 2 emails remaining");
|
||
|
||
echo "✅ Batch operations work correctly\n\n";
|
||
|
||
// Test 6: Smart Batch (Auto-Type-Detection)
|
||
echo "6️⃣ Testing Smart Batch (Auto-Type-Detection)...\n";
|
||
|
||
$emailQueue->clear();
|
||
|
||
$smartEmails = [
|
||
new TransactionalOrderConfirmationEmail('auto@example.com', 'auto-order', 100.00),
|
||
new MarketingNewsletterEmail('auto-marketing@example.com', 'auto-campaign'),
|
||
new SystemAdminAlertEmail('auto-admin@example.com', 'Auto alert', 'info'),
|
||
new BulkPromotionEmail('auto-bulk@example.com', 'AUTO10', 10.0),
|
||
new CriticalSecurityNotificationEmail('auto-critical@example.com', 'Auto security issue'),
|
||
new InvoiceEmail('auto-invoice@example.com', 'INV-001')
|
||
];
|
||
|
||
$emailQueue->pushSmartBatch($smartEmails);
|
||
assert($emailQueue->size() === 6, "❌ Should have 6 emails after smart batch");
|
||
|
||
// Critical sollte zuerst kommen
|
||
$firstEmail = $emailQueue->popEmail();
|
||
assert($firstEmail instanceof CriticalSecurityNotificationEmail, "❌ Critical email should be processed first");
|
||
|
||
echo "✅ Smart batch with auto-type-detection works correctly\n\n";
|
||
|
||
// Test 7: Email Statistics
|
||
echo "7️⃣ Testing Email Statistics...\n";
|
||
|
||
$emailQueue->clear();
|
||
$emailQueue->pushTransactionalEmail(new TransactionalOrderConfirmationEmail('stats@example.com', 'stats-order', 50.00));
|
||
$emailQueue->pushMarketingEmail(new MarketingNewsletterEmail('stats-marketing@example.com', 'stats-campaign'));
|
||
|
||
$stats = $emailQueue->getStats();
|
||
assert($stats['type'] === 'email', "❌ Stats should indicate email type");
|
||
assert($stats['size'] === 2, "❌ Stats should show correct size");
|
||
assert(!$stats['is_empty'], "❌ Stats should show queue is not empty");
|
||
|
||
echo "✅ Email statistics work correctly\n\n";
|
||
|
||
// Test 8: Scheduled Email Detection
|
||
echo "8️⃣ Testing Scheduled Email Detection...\n";
|
||
|
||
$emailQueue->clear();
|
||
|
||
// Add immediate emails
|
||
$emailQueue->pushTransactionalEmail(new TransactionalOrderConfirmationEmail('immediate@example.com', 'immediate-order', 25.00));
|
||
|
||
// Add scheduled emails
|
||
$emailQueue->pushScheduledEmail(new WelcomeEmail('scheduled1@example.com', 'User 1'), Duration::fromHours(1));
|
||
$emailQueue->pushScheduledEmail(new WelcomeEmail('scheduled2@example.com', 'User 2'), Duration::fromHours(2));
|
||
|
||
$scheduledEmails = $emailQueue->getScheduledEmails();
|
||
assert(count($scheduledEmails) === 2, "❌ Should detect 2 scheduled emails");
|
||
|
||
$statusCounts = $emailQueue->getDeliveryStatusCounts();
|
||
assert($statusCounts['pending'] === 3, "❌ Should have 3 pending emails");
|
||
assert($statusCounts['scheduled'] === 2, "❌ Should have 2 scheduled emails");
|
||
assert($statusCounts['immediate'] === 1, "❌ Should have 1 immediate email");
|
||
|
||
echo "✅ Scheduled email detection works correctly\n\n";
|
||
|
||
// Test 9: Rate-Limited Bulk Processing
|
||
echo "9️⃣ Testing Rate-Limited Bulk Processing...\n";
|
||
|
||
$emailQueue->clear();
|
||
|
||
$bulkEmails = [
|
||
new BulkPromotionEmail('bulk1@example.com', 'BULK1', 5.0),
|
||
new BulkPromotionEmail('bulk2@example.com', 'BULK2', 10.0),
|
||
new BulkPromotionEmail('bulk3@example.com', 'BULK3', 15.0)
|
||
];
|
||
|
||
$interval = Duration::fromMinutes(5);
|
||
$emailQueue->pushBulkWithRateLimit($bulkEmails, $interval);
|
||
|
||
assert($emailQueue->size() === 3, "❌ Should have 3 bulk emails");
|
||
|
||
// Check that delays are applied correctly by collecting all payloads
|
||
$payloads = [];
|
||
while (!$emailQueue->isEmpty()) {
|
||
$payload = $emailQueue->popEmailWithMetadata();
|
||
if ($payload !== null) {
|
||
$payloads[] = $payload;
|
||
}
|
||
}
|
||
|
||
assert(count($payloads) === 3, "❌ Should have 3 payloads");
|
||
|
||
// Sort payloads by delay to verify rate limiting
|
||
usort($payloads, fn($a, $b) => $a->delay->toSeconds() <=> $b->delay->toSeconds());
|
||
|
||
assert($payloads[0]->delay->toSeconds() === 0.0, "❌ First email should have no delay");
|
||
assert($payloads[1]->delay->toSeconds() === 300.0, "❌ Second email should have 5-minute delay");
|
||
assert($payloads[2]->delay->toSeconds() === 600.0, "❌ Third email should have 10-minute delay");
|
||
|
||
echo "✅ Rate-limited bulk processing works correctly\n\n";
|
||
|
||
// Test 10: Email Type Filtering
|
||
echo "🔟 Testing Email Type Filtering...\n";
|
||
|
||
$emailQueue->clear();
|
||
|
||
$emailQueue->pushTransactionalEmail(new TransactionalOrderConfirmationEmail('filter1@example.com', 'filter-order-1', 30.00));
|
||
$emailQueue->pushTransactionalEmail(new TransactionalOrderConfirmationEmail('filter2@example.com', 'filter-order-2', 40.00));
|
||
$emailQueue->pushMarketingEmail(new MarketingNewsletterEmail('filter-marketing@example.com', 'filter-campaign'));
|
||
|
||
$transactionalEmails = $emailQueue->getEmailsByType(TransactionalOrderConfirmationEmail::class);
|
||
assert(count($transactionalEmails) === 2, "❌ Should find 2 transactional emails");
|
||
|
||
// Queue should still have the marketing email
|
||
assert($emailQueue->size() === 1, "❌ Should have 1 email remaining (marketing)");
|
||
|
||
echo "✅ Email type filtering works correctly\n\n";
|
||
|
||
// Test 11: Empty Queue Handling
|
||
echo "1️⃣1️⃣ Testing Empty Queue Handling...\n";
|
||
|
||
$emailQueue->clear();
|
||
assert($emailQueue->isEmpty(), "❌ Queue should be empty after clear");
|
||
assert($emailQueue->size() === 0, "❌ Queue size should be 0");
|
||
|
||
$nullEmail = $emailQueue->popEmail();
|
||
assert($nullEmail === null, "❌ Popping from empty queue should return null");
|
||
|
||
$nullPeek = $emailQueue->peekEmail();
|
||
assert($nullPeek === null, "❌ Peeking empty queue should return null");
|
||
|
||
$emptyBatch = $emailQueue->popBatch(5);
|
||
assert(empty($emptyBatch), "❌ Batch pop from empty queue should return empty array");
|
||
|
||
$emptyScheduled = $emailQueue->getScheduledEmails();
|
||
assert(empty($emptyScheduled), "❌ Scheduled emails from empty queue should return empty array");
|
||
|
||
echo "✅ Empty queue handling works correctly\n\n";
|
||
|
||
// Test 12: Email Metadata Integration
|
||
echo "1️⃣2️⃣ Testing Email Metadata Integration...\n";
|
||
|
||
$emailQueue->clear();
|
||
$metaEmail = new WelcomeEmail('meta@example.com', 'Meta User');
|
||
$emailQueue->pushEmail($metaEmail);
|
||
|
||
$payload = $emailQueue->popEmailWithMetadata();
|
||
assert($payload !== null, "❌ Should have payload");
|
||
assert($payload->metadata !== null, "❌ Should have metadata");
|
||
assert($payload->metadata->type === 'email', "❌ Metadata type should be 'email'");
|
||
assert($payload->metadata->hasTag('email'), "❌ Metadata should have 'email' tag");
|
||
|
||
echo "✅ Email metadata integration works correctly\n\n";
|
||
|
||
echo "🎉 ALL EMAIL QUEUE TESTS PASSED!\n";
|
||
echo "✨ EmailQueue wrapper is ready for production use!\n"; |