- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
294 lines
9.2 KiB
PHP
294 lines
9.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Integration Test: Component getSseChannel() Method
|
|
*
|
|
* Verifies that Components correctly implement getSseChannel() method
|
|
* and return appropriate SSE channel names.
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Application\LiveComponents\ActivityFeed\ActivityFeedComponent;
|
|
use App\Application\LiveComponents\CommentThread\CommentThreadComponent;
|
|
use App\Application\LiveComponents\LivePresence\LivePresenceComponent;
|
|
use App\Application\LiveComponents\NotificationCenter\NotificationCenterComponent;
|
|
use App\Framework\DI\DefaultContainer;
|
|
use App\Framework\Discovery\Results\DiscoveryRegistry;
|
|
use App\Framework\LiveComponents\DataProviderResolver;
|
|
use App\Framework\LiveComponents\ValueObjects\ComponentId;
|
|
|
|
echo "=== Component getSseChannel() Integration Test ===\n\n";
|
|
|
|
// Setup minimal Container and DataProviderResolver for ActivityFeed tests
|
|
$container = new DefaultContainer();
|
|
$discoveryRegistry = new DiscoveryRegistry();
|
|
$dataProviderResolver = new DataProviderResolver($discoveryRegistry, $container);
|
|
|
|
// Test 1: NotificationCenter with user-specific channel
|
|
echo "Test 1: NotificationCenter - User-specific channel\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
$notificationComponent1 = new NotificationCenterComponent(
|
|
id: ComponentId::fromString('notification-center:user-123'),
|
|
initialData: null
|
|
);
|
|
|
|
$channel1 = $notificationComponent1->getSseChannel();
|
|
echo "Component ID: notification-center:user-123\n";
|
|
echo "SSE Channel: {$channel1}\n";
|
|
|
|
if ($channel1 === 'user:user-123') {
|
|
echo "✅ PASS: User-specific channel correct\n";
|
|
} else {
|
|
echo "❌ FAIL: Expected 'user:user-123', got '{$channel1}'\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 2: NotificationCenter with global channel
|
|
echo "Test 2: NotificationCenter - Global channel\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
$notificationComponent2 = new NotificationCenterComponent(
|
|
id: ComponentId::fromString('notification-center:global'),
|
|
initialData: null
|
|
);
|
|
|
|
$channel2 = $notificationComponent2->getSseChannel();
|
|
echo "Component ID: notification-center:global\n";
|
|
echo "SSE Channel: {$channel2}\n";
|
|
|
|
if ($channel2 === 'global') {
|
|
echo "✅ PASS: Global channel correct\n";
|
|
} else {
|
|
echo "❌ FAIL: Expected 'global', got '{$channel2}'\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 3: NotificationCenter with guest channel
|
|
echo "Test 3: NotificationCenter - Guest channel\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
$notificationComponent3 = new NotificationCenterComponent(
|
|
id: ComponentId::fromString('notification-center:guest'),
|
|
initialData: null
|
|
);
|
|
|
|
$channel3 = $notificationComponent3->getSseChannel();
|
|
echo "Component ID: notification-center:guest\n";
|
|
echo "SSE Channel: {$channel3}\n";
|
|
|
|
if ($channel3 === 'global') {
|
|
echo "✅ PASS: Guest uses global channel (correct)\n";
|
|
} else {
|
|
echo "❌ FAIL: Expected 'global', got '{$channel3}'\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 4: LivePresence with room-specific channel
|
|
echo "Test 4: LivePresence - Room-specific channel\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
$presenceComponent1 = new LivePresenceComponent(
|
|
id: ComponentId::fromString('live-presence:room-lobby'),
|
|
initialData: null
|
|
);
|
|
|
|
$channel4 = $presenceComponent1->getSseChannel();
|
|
echo "Component ID: live-presence:room-lobby\n";
|
|
echo "SSE Channel: {$channel4}\n";
|
|
|
|
if ($channel4 === 'presence:room-lobby') {
|
|
echo "✅ PASS: Room-specific presence channel correct\n";
|
|
} else {
|
|
echo "❌ FAIL: Expected 'presence:room-lobby', got '{$channel4}'\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 5: LivePresence with global channel
|
|
echo "Test 5: LivePresence - Global presence\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
$presenceComponent2 = new LivePresenceComponent(
|
|
id: ComponentId::fromString('live-presence:global'),
|
|
initialData: null
|
|
);
|
|
|
|
$channel5 = $presenceComponent2->getSseChannel();
|
|
echo "Component ID: live-presence:global\n";
|
|
echo "SSE Channel: {$channel5}\n";
|
|
|
|
if ($channel5 === 'presence:global') {
|
|
echo "✅ PASS: Global presence channel correct\n";
|
|
} else {
|
|
echo "❌ FAIL: Expected 'presence:global', got '{$channel5}'\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 6: CommentThread with post-specific channel
|
|
echo "Test 6: CommentThread - Post-specific channel\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
$commentComponent1 = new CommentThreadComponent(
|
|
id: ComponentId::fromString('comment-thread:post-123'),
|
|
initialData: null
|
|
);
|
|
|
|
$channel6 = $commentComponent1->getSseChannel();
|
|
echo "Component ID: comment-thread:post-123\n";
|
|
echo "SSE Channel: {$channel6}\n";
|
|
|
|
if ($channel6 === 'comments:post-123') {
|
|
echo "✅ PASS: Post-specific comment channel correct\n";
|
|
} else {
|
|
echo "❌ FAIL: Expected 'comments:post-123', got '{$channel6}'\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 7: CommentThread with article-specific channel
|
|
echo "Test 7: CommentThread - Article-specific channel\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
$commentComponent2 = new CommentThreadComponent(
|
|
id: ComponentId::fromString('comment-thread:article-456'),
|
|
initialData: null
|
|
);
|
|
|
|
$channel7 = $commentComponent2->getSseChannel();
|
|
echo "Component ID: comment-thread:article-456\n";
|
|
echo "SSE Channel: {$channel7}\n";
|
|
|
|
if ($channel7 === 'comments:article-456') {
|
|
echo "✅ PASS: Article-specific comment channel correct\n";
|
|
} else {
|
|
echo "❌ FAIL: Expected 'comments:article-456', got '{$channel7}'\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 8: ActivityFeed with user-specific channel
|
|
echo "Test 8: ActivityFeed - User-specific channel\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
// Create mock ActivityDataProvider with correct interface signatures
|
|
$mockDataProvider = new class () implements \App\Application\LiveComponents\Services\ActivityDataProvider {
|
|
public function getActivities(
|
|
\App\Application\LiveComponents\ValueObjects\ActivityFilter $filter = \App\Application\LiveComponents\ValueObjects\ActivityFilter::ALL,
|
|
int $limit = 50
|
|
): array {
|
|
return [];
|
|
}
|
|
|
|
public function addActivity(\App\Application\LiveComponents\ValueObjects\Activity $activity): bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public function markAsRead(string $activityId): bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public function markAllAsRead(): int
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
public function getUnreadCount(): int
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
public function deleteActivity(string $activityId): bool
|
|
{
|
|
return true;
|
|
}
|
|
};
|
|
|
|
$activityComponent1 = new ActivityFeedComponent(
|
|
id: ComponentId::fromString('activity-feed:user-789'),
|
|
dataProviderResolver: $dataProviderResolver,
|
|
initialData: null,
|
|
dataProvider: $mockDataProvider
|
|
);
|
|
|
|
$channel8 = $activityComponent1->getSseChannel();
|
|
echo "Component ID: activity-feed:user-789\n";
|
|
echo "SSE Channel: {$channel8}\n";
|
|
|
|
if ($channel8 === 'activity:user-789') {
|
|
echo "✅ PASS: User-specific activity channel correct\n";
|
|
} else {
|
|
echo "❌ FAIL: Expected 'activity:user-789', got '{$channel8}'\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 9: ActivityFeed with global channel
|
|
echo "Test 9: ActivityFeed - Global channel\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
$activityComponent2 = new ActivityFeedComponent(
|
|
id: ComponentId::fromString('activity-feed:global'),
|
|
dataProviderResolver: $dataProviderResolver,
|
|
initialData: null,
|
|
dataProvider: $mockDataProvider
|
|
);
|
|
|
|
$channel9 = $activityComponent2->getSseChannel();
|
|
echo "Component ID: activity-feed:global\n";
|
|
echo "SSE Channel: {$channel9}\n";
|
|
|
|
if ($channel9 === 'activity:global') {
|
|
echo "✅ PASS: Global activity channel correct\n";
|
|
} else {
|
|
echo "❌ FAIL: Expected 'activity:global', got '{$channel9}'\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 10: Verify method_exists check for all components
|
|
echo "Test 10: Verify method_exists for getSseChannel()\n";
|
|
echo "---------------------------------------------------\n";
|
|
|
|
if (method_exists($notificationComponent1, 'getSseChannel')) {
|
|
echo "✅ PASS: NotificationCenterComponent has getSseChannel() method\n";
|
|
} else {
|
|
echo "❌ FAIL: NotificationCenterComponent missing getSseChannel() method\n";
|
|
}
|
|
|
|
if (method_exists($presenceComponent1, 'getSseChannel')) {
|
|
echo "✅ PASS: LivePresenceComponent has getSseChannel() method\n";
|
|
} else {
|
|
echo "❌ FAIL: LivePresenceComponent missing getSseChannel() method\n";
|
|
}
|
|
|
|
if (method_exists($commentComponent1, 'getSseChannel')) {
|
|
echo "✅ PASS: CommentThreadComponent has getSseChannel() method\n";
|
|
} else {
|
|
echo "❌ FAIL: CommentThreadComponent missing getSseChannel() method\n";
|
|
}
|
|
|
|
if (method_exists($activityComponent1, 'getSseChannel')) {
|
|
echo "✅ PASS: ActivityFeedComponent has getSseChannel() method\n";
|
|
} else {
|
|
echo "❌ FAIL: ActivityFeedComponent missing getSseChannel() method\n";
|
|
}
|
|
|
|
echo "\n=== All Component Tests Complete ===\n";
|
|
echo "\nSummary:\n";
|
|
echo "- NotificationCenter uses 'user:' prefix for user-specific notifications\n";
|
|
echo "- NotificationCenter falls back to 'global' for guest/global instances\n";
|
|
echo "- LivePresence uses 'presence:' prefix for room-based tracking\n";
|
|
echo "- CommentThread uses 'comments:' prefix for context-based commenting\n";
|
|
echo "- ActivityFeed uses 'activity:' prefix for context-based activity tracking\n";
|
|
echo "- All components implement getSseChannel() correctly\n";
|