- 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.
276 lines
9.0 KiB
PHP
276 lines
9.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Application\LiveComponents\TodoList\TodoItemComponent;
|
|
use App\Application\LiveComponents\TodoList\TodoListComponent;
|
|
use App\Framework\LiveComponents\NestedComponentEventDispatcher;
|
|
use App\Framework\LiveComponents\NestedComponentManager;
|
|
use App\Framework\LiveComponents\ValueObjects\ComponentHierarchy;
|
|
use App\Framework\LiveComponents\ValueObjects\ComponentId;
|
|
|
|
echo "🧪 Testing Nested Components System\n";
|
|
echo str_repeat('=', 70) . "\n\n";
|
|
|
|
// Test 1: Component Hierarchy Creation
|
|
echo "Test 1: Component Hierarchy Creation\n";
|
|
echo str_repeat('-', 70) . "\n";
|
|
|
|
$hierarchy = ComponentHierarchy::root();
|
|
echo "✓ Created root hierarchy: depth={$hierarchy->depth}, isRoot=" . ($hierarchy->isRoot() ? 'true' : 'false') . "\n";
|
|
|
|
$parentId = ComponentId::fromString('todo-list:main');
|
|
$childId = ComponentId::fromString('todo-item:1');
|
|
|
|
$childHierarchy = ComponentHierarchy::fromParent($parentId, $childId);
|
|
echo "✓ Created child hierarchy: depth={$childHierarchy->depth}, isChild=" . ($childHierarchy->isChild() ? 'true' : 'false') . "\n";
|
|
echo "✓ Child has parent: " . ($childHierarchy->parentId !== null ? 'true' : 'false') . "\n";
|
|
echo "✓ Path length: " . count($childHierarchy->path) . "\n\n";
|
|
|
|
// Test 2: Nested Component Manager
|
|
echo "Test 2: Nested Component Manager\n";
|
|
echo str_repeat('-', 70) . "\n";
|
|
|
|
$nestedManager = new NestedComponentManager();
|
|
|
|
// Register parent (root)
|
|
$parentId = ComponentId::fromString('todo-list:main');
|
|
$nestedManager->registerHierarchy($parentId, ComponentHierarchy::root());
|
|
echo "✓ Registered parent component: {$parentId->toString()}\n";
|
|
|
|
// Register children
|
|
$childIds = [
|
|
ComponentId::fromString('todo-item:1'),
|
|
ComponentId::fromString('todo-item:2'),
|
|
ComponentId::fromString('todo-item:3'),
|
|
];
|
|
|
|
foreach ($childIds as $childId) {
|
|
$hierarchy = ComponentHierarchy::fromParent($parentId, $childId);
|
|
$nestedManager->registerHierarchy($childId, $hierarchy);
|
|
echo "✓ Registered child component: {$childId->toString()}\n";
|
|
}
|
|
|
|
// Verify hierarchy queries
|
|
echo "\nHierarchy Queries:\n";
|
|
echo " Parent has children: " . ($nestedManager->hasChildren($parentId) ? 'true' : 'false') . "\n";
|
|
echo " Number of children: " . count($nestedManager->getChildIds($parentId)) . "\n";
|
|
echo " First child's parent: " . $nestedManager->getParentId($childIds[0])?->toString() . "\n";
|
|
echo " Parent is root: " . ($nestedManager->isRoot($parentId) ? 'true' : 'false') . "\n";
|
|
echo " Child is root: " . ($nestedManager->isRoot($childIds[0]) ? 'true' : 'false') . "\n";
|
|
|
|
// Statistics
|
|
$stats = $nestedManager->getStats();
|
|
echo "\nHierarchy Statistics:\n";
|
|
echo " Total components: {$stats['total_components']}\n";
|
|
echo " Root components: {$stats['root_components']}\n";
|
|
echo " Child components: {$stats['child_components']}\n";
|
|
echo " Max nesting depth: {$stats['max_nesting_depth']}\n";
|
|
echo " Parents with children: {$stats['parent_components_with_children']}\n\n";
|
|
|
|
// Test 3: TodoList Component with Children
|
|
echo "Test 3: TodoList Component with Children\n";
|
|
echo str_repeat('-', 70) . "\n";
|
|
|
|
$todoListId = ComponentId::fromString('todo-list:demo');
|
|
$initialTodos = [
|
|
[
|
|
'id' => 'todo_1',
|
|
'title' => 'Learn Nested Components',
|
|
'completed' => false,
|
|
'created_at' => time(),
|
|
],
|
|
[
|
|
'id' => 'todo_2',
|
|
'title' => 'Implement Event Bubbling',
|
|
'completed' => true,
|
|
'created_at' => time() - 3600,
|
|
],
|
|
[
|
|
'id' => 'todo_3',
|
|
'title' => 'Write Integration Tests',
|
|
'completed' => false,
|
|
'created_at' => time() - 7200,
|
|
],
|
|
];
|
|
|
|
$todoList = new TodoListComponent(
|
|
id: $todoListId,
|
|
initialData: null,
|
|
todos: $initialTodos,
|
|
filter: 'all'
|
|
);
|
|
|
|
echo "✓ Created TodoList component: {$todoListId->toString()}\n";
|
|
echo " Initial todos count: " . count($initialTodos) . "\n";
|
|
|
|
// Get child component IDs
|
|
$childComponents = $todoList->getChildComponents();
|
|
echo " Child components declared: " . count($childComponents) . "\n";
|
|
foreach ($childComponents as $childIdString) {
|
|
echo " - {$childIdString}\n";
|
|
}
|
|
|
|
// Test child compatibility
|
|
$validChild = ComponentId::fromString('todo-item:test');
|
|
$invalidChild = ComponentId::fromString('other-component:test');
|
|
|
|
echo "\n Child compatibility tests:\n";
|
|
echo " todo-item:test can be child: " . ($todoList->canHaveChild($validChild) ? 'true' : 'false') . "\n";
|
|
echo " other-component:test can be child: " . ($todoList->canHaveChild($invalidChild) ? 'true' : 'false') . "\n";
|
|
|
|
// Test Actions
|
|
echo "\n Testing Actions:\n";
|
|
|
|
// Add Todo
|
|
$newData = $todoList->addTodo('New Todo Item');
|
|
$newDataArray = $newData->toArray();
|
|
echo " ✓ Added todo, new count: " . count($newDataArray['todos']) . "\n";
|
|
|
|
// Set Filter
|
|
$filteredData = $todoList->setFilter('active');
|
|
echo " ✓ Changed filter to 'active'\n";
|
|
|
|
// Clear Completed
|
|
$clearedData = $todoList->clearCompleted();
|
|
echo " ✓ Cleared completed todos\n\n";
|
|
|
|
// Test 4: TodoItem Component
|
|
echo "Test 4: TodoItem Component\n";
|
|
echo str_repeat('-', 70) . "\n";
|
|
|
|
$todoItemId = ComponentId::fromString('todo-item:demo_1');
|
|
$todoData = [
|
|
'id' => 'demo_1',
|
|
'title' => 'Test TodoItem',
|
|
'completed' => false,
|
|
'created_at' => time(),
|
|
];
|
|
|
|
// Create event dispatcher
|
|
$eventDispatcher = new NestedComponentEventDispatcher();
|
|
|
|
$todoItem = new TodoItemComponent(
|
|
id: $todoItemId,
|
|
eventDispatcher: $eventDispatcher,
|
|
initialData: null,
|
|
todoData: $todoData
|
|
);
|
|
|
|
echo "✓ Created TodoItem component: {$todoItemId->toString()}\n";
|
|
echo " Title: " . $todoData['title'] . "\n";
|
|
echo " Completed: " . ($todoData['completed'] ? 'true' : 'false') . "\n\n";
|
|
|
|
echo " Testing TodoItem Actions:\n";
|
|
|
|
// Toggle
|
|
$eventDispatcher->clear();
|
|
$todoItem->toggle();
|
|
echo " ✓ Toggled todo\n";
|
|
echo " Events dispatched: " . $eventDispatcher->count() . "\n";
|
|
if ($eventDispatcher->hasEvents()) {
|
|
foreach ($eventDispatcher->getEvents() as $event) {
|
|
echo " 📡 {$event['event_name']} from {$event['component_id']}\n";
|
|
}
|
|
}
|
|
echo "\n";
|
|
|
|
// Start Edit
|
|
$editData = $todoItem->startEdit();
|
|
echo " ✓ Started edit mode\n";
|
|
|
|
// Save Edit
|
|
$eventDispatcher->clear();
|
|
$savedData = $todoItem->saveEdit('Updated Title');
|
|
echo " ✓ Saved edit\n";
|
|
echo " Events dispatched: " . $eventDispatcher->count() . "\n";
|
|
if ($eventDispatcher->hasEvents()) {
|
|
foreach ($eventDispatcher->getEvents() as $event) {
|
|
echo " 📡 {$event['event_name']} from {$event['component_id']}\n";
|
|
}
|
|
}
|
|
echo "\n";
|
|
|
|
// Delete
|
|
$eventDispatcher->clear();
|
|
$todoItem->delete();
|
|
echo " ✓ Deleted todo\n";
|
|
echo " Events dispatched: " . $eventDispatcher->count() . "\n";
|
|
if ($eventDispatcher->hasEvents()) {
|
|
foreach ($eventDispatcher->getEvents() as $event) {
|
|
echo " 📡 {$event['event_name']} from {$event['component_id']}\n";
|
|
}
|
|
}
|
|
echo "\n";
|
|
|
|
// Test 5: Event Bubbling Simulation
|
|
echo "Test 5: Event Bubbling Simulation\n";
|
|
echo str_repeat('-', 70) . "\n";
|
|
|
|
// Create parent with event handling
|
|
$parentId = ComponentId::fromString('todo-list:bubble-test');
|
|
$parent = new TodoListComponent(
|
|
id: $parentId,
|
|
initialData: null,
|
|
todos: [
|
|
['id' => 'child_1', 'title' => 'First Todo', 'completed' => false, 'created_at' => time()],
|
|
]
|
|
);
|
|
|
|
$childId = ComponentId::fromString('todo-item:child_1');
|
|
|
|
// Test different events
|
|
$events = [
|
|
['todo-completed', ['todo_id' => 'child_1', 'completed' => true]],
|
|
['todo-deleted', ['todo_id' => 'child_1']],
|
|
['todo-title-changed', ['todo_id' => 'child_1', 'title' => 'Updated Title']],
|
|
];
|
|
|
|
echo "Testing event bubbling (check error_log for details):\n";
|
|
foreach ($events as [$eventName, $payload]) {
|
|
$shouldContinue = $parent->onChildEvent($childId, $eventName, $payload);
|
|
echo " ✓ {$eventName}: bubbling " . ($shouldContinue ? 'continues' : 'stopped') . "\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Test 6: Circular Dependency Detection
|
|
echo "Test 6: Circular Dependency Detection\n";
|
|
echo str_repeat('-', 70) . "\n";
|
|
|
|
try {
|
|
$selfId = ComponentId::fromString('component:self');
|
|
$circularHierarchy = ComponentHierarchy::fromParent($selfId, $selfId);
|
|
|
|
$manager = new NestedComponentManager();
|
|
$manager->registerHierarchy($selfId, $circularHierarchy);
|
|
|
|
echo "❌ Should have thrown exception for circular dependency\n";
|
|
} catch (\InvalidArgumentException $e) {
|
|
echo "✓ Circular dependency correctly detected and prevented\n";
|
|
echo " Error message: {$e->getMessage()}\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Summary
|
|
echo str_repeat('=', 70) . "\n";
|
|
echo "✅ All Nested Components Tests Completed!\n\n";
|
|
|
|
echo "Summary:\n";
|
|
echo " ✓ Component Hierarchy Value Objects\n";
|
|
echo " ✓ Nested Component Manager\n";
|
|
echo " ✓ TodoList Parent Component\n";
|
|
echo " ✓ TodoItem Child Component\n";
|
|
echo " ✓ Event Dispatching\n";
|
|
echo " ✓ Event Bubbling\n";
|
|
echo " ✓ Circular Dependency Protection\n\n";
|
|
|
|
echo "Next Steps:\n";
|
|
echo " - Integrate with LiveComponentHandler\n";
|
|
echo " - Test in browser with real DOM\n";
|
|
echo " - Add client-side event bubbling tests\n";
|
|
echo " - Implement Slot System for flexible composition\n";
|