Files
michaelschiemer/tests/debug/test-livecomponents-strict-integration.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- 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.
2025-10-25 19:18:37 +02:00

252 lines
9.1 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Application\LiveComponents\Counter\CounterComponent;
use App\Application\LiveComponents\NotificationBell\NotificationBellComponent;
use App\Application\LiveComponents\Stats\StatsComponent;
use App\Framework\LiveComponents\ValueObjects\ActionParameters;
use App\Framework\LiveComponents\ValueObjects\ComponentData;
use App\Framework\LiveComponents\ValueObjects\ComponentId;
echo "=== LiveComponents Strict Type Integration Test ===\n\n";
// Note: We test components directly without the full DI container
// This tests the strict typing at the component level
echo "Testing components with strict Value Object types only...\n";
$testsPassed = 0;
$testsFailed = 0;
// Test 1: CounterComponent constructor with strict types
echo "\nTest 1: CounterComponent constructor with strict types\n";
try {
$id = ComponentId::create('counter', 'test-strict');
$data = ComponentData::fromArray(['count' => 5]);
$component = new CounterComponent($id, $data);
assert($component instanceof CounterComponent, 'Component should be CounterComponent');
assert($component->getId() instanceof ComponentId, 'getId() should return ComponentId');
assert($component->getData() instanceof ComponentData, 'getData() should return ComponentData');
assert($component->getData()->get('count') === 5, 'Initial count should be 5');
echo "✅ CounterComponent constructor accepts strict types\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ CounterComponent constructor test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Test 2: CounterComponent increment action returns ComponentData
echo "\nTest 2: CounterComponent increment action returns ComponentData\n";
try {
$id = ComponentId::create('counter', 'test-action');
$data = ComponentData::fromArray(['count' => 10]);
$component = new CounterComponent($id, $data);
$params = ActionParameters::empty();
$result = $component->increment($params);
assert($result instanceof ComponentData, 'increment() should return ComponentData');
assert($result->get('count') === 11, 'Count should be incremented to 11');
echo "✅ CounterComponent increment returns ComponentData\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ CounterComponent action test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Test 3: NotificationBellComponent constructor with strict types
echo "\nTest 3: NotificationBellComponent constructor with strict types\n";
try {
$id = ComponentId::create('notification-bell', 'user-123');
$data = ComponentData::fromArray([
'user_id' => '123',
'unread_count' => 3,
]);
$component = new NotificationBellComponent($id, $data);
assert($component instanceof NotificationBellComponent, 'Component should be NotificationBellComponent');
assert($component->getId() instanceof ComponentId, 'getId() should return ComponentId');
assert($component->getData() instanceof ComponentData, 'getData() should return ComponentData');
assert($component->getData()->get('unread_count') === 3, 'Initial unread_count should be 3');
echo "✅ NotificationBellComponent constructor accepts strict types\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ NotificationBellComponent test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Test 4: NotificationBellComponent poll returns ComponentData
echo "\nTest 4: NotificationBellComponent poll returns ComponentData\n";
try {
$id = ComponentId::create('notification-bell', 'user-poll');
$data = ComponentData::fromArray(['user_id' => '456']);
$component = new NotificationBellComponent($id, $data);
$params = ActionParameters::empty();
$result = $component->poll($params);
assert($result instanceof ComponentData, 'poll() should return ComponentData');
assert($result->has('unread_count'), 'Result should have unread_count');
assert($result->has('notifications'), 'Result should have notifications');
echo "✅ NotificationBellComponent poll returns ComponentData\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ NotificationBellComponent poll test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Test 5: StatsComponent constructor with strict types
echo "\nTest 5: StatsComponent constructor with strict types\n";
try {
$id = ComponentId::create('stats', 'dashboard');
$data = ComponentData::fromArray(['cache_enabled' => true]);
$component = new StatsComponent($id, $data);
assert($component instanceof StatsComponent, 'Component should be StatsComponent');
assert($component->getId() instanceof ComponentId, 'getId() should return ComponentId');
assert($component->getData() instanceof ComponentData, 'getData() should return ComponentData');
assert($component->getData()->get('cache_enabled') === true, 'cache_enabled should be true');
echo "✅ StatsComponent constructor accepts strict types\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ StatsComponent test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Test 6: StatsComponent toggleCache returns ComponentData
echo "\nTest 6: StatsComponent toggleCache returns ComponentData\n";
try {
$id = ComponentId::create('stats', 'toggle-test');
$data = ComponentData::fromArray(['cache_enabled' => true]);
$component = new StatsComponent($id, $data);
$params = ActionParameters::empty();
$result = $component->toggleCache($params);
assert($result instanceof ComponentData, 'toggleCache() should return ComponentData');
assert($result->get('cache_enabled') === false, 'cache_enabled should be toggled to false');
echo "✅ StatsComponent toggleCache returns ComponentData\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ StatsComponent toggle test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Test 7: Component constructor with null ComponentData
echo "\nTest 7: Component constructor with null ComponentData\n";
try {
$id = ComponentId::create('counter', 'null-data-test');
// Pass null, should use ComponentData::empty()
$component = new CounterComponent($id, null);
assert($component instanceof CounterComponent, 'Component should be CounterComponent');
assert($component->getData() instanceof ComponentData, 'getData() should return ComponentData');
assert($component->getData()->get('count', 0) === 0, 'Default count should be 0');
echo "✅ Component constructor handles null ComponentData correctly\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ Component null data test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Test 8: ComponentData immutability
echo "\nTest 8: ComponentData immutability\n";
try {
$id = ComponentId::create('counter', 'immutability-test');
$originalData = ComponentData::fromArray(['count' => 10]);
$component = new CounterComponent($id, $originalData);
$params = ActionParameters::empty();
$newData = $component->increment($params);
assert($originalData->get('count') === 10, 'Original data should be unchanged');
assert($newData->get('count') === 11, 'New data should be incremented');
assert($originalData !== $newData, 'Should be different instances');
echo "✅ ComponentData immutability preserved\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ Immutability test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Test 9: ComponentId toString consistency
echo "\nTest 9: ComponentId toString consistency\n";
try {
$id = ComponentId::create('counter', 'id-test');
$idString = $id->toString();
assert($idString === 'counter:id-test', 'ComponentId toString should match expected format');
$parsedId = ComponentId::fromString($idString);
assert($parsedId->toString() === $idString, 'Parsed ID should match original');
echo "✅ ComponentId toString/fromString working correctly\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ ComponentId test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Test 10: ActionParameters type coercion
echo "\nTest 10: ActionParameters type coercion\n";
try {
$params = ActionParameters::fromArray([
'amount' => '5', // String
'enabled' => 'true', // String boolean
'data' => ['key' => 'value'],
]);
assert($params->getInt('amount') === 5, 'getString should coerce to int');
assert($params->getBool('enabled') === true, 'getBool should coerce string to bool');
assert($params->getArray('data') === ['key' => 'value'], 'getArray should return array');
echo "✅ ActionParameters type coercion working\n";
$testsPassed++;
} catch (\Throwable $e) {
echo "❌ ActionParameters test failed: {$e->getMessage()}\n";
$testsFailed++;
}
// Summary
echo "\n=== Test Summary ===\n";
echo "✅ Passed: {$testsPassed}\n";
echo "❌ Failed: {$testsFailed}\n";
echo "Total: " . ($testsPassed + $testsFailed) . "\n";
if ($testsFailed === 0) {
echo "\n🎉 All strict type migration tests passed!\n";
exit(0);
} else {
echo "\n⚠️ Some tests failed. Please review the output above.\n";
exit(1);
}