testLog) implements \App\Framework\Logging\Logger { public function __construct(private array &$logCapture) { } public function debug(string $message, array $context = []): void { $this->logCapture[] = ['level' => 'debug', 'message' => $message, 'context' => $context]; } public function info(string $message, array $context = []): void { $this->logCapture[] = ['level' => 'info', 'message' => $message, 'context' => $context]; } public function notice(string $message, array $context = []): void { $this->logCapture[] = ['level' => 'notice', 'message' => $message, 'context' => $context]; } public function warning(string $message, array $context = []): void { $this->logCapture[] = ['level' => 'warning', 'message' => $message, 'context' => $context]; } public function error(string $message, array $context = []): void { $this->logCapture[] = ['level' => 'error', 'message' => $message, 'context' => $context]; } public function critical(string $message, array $context = []): void { $this->logCapture[] = ['level' => 'critical', 'message' => $message, 'context' => $context]; } public function alert(string $message, array $context = []): void { $this->logCapture[] = ['level' => 'alert', 'message' => $message, 'context' => $context]; } public function emergency(string $message, array $context = []): void { $this->logCapture[] = ['level' => 'emergency', 'message' => $message, 'context' => $context]; } public function log(\App\Framework\Logging\LogLevel $level, string $message, array $context = []): void { $this->logCapture[] = ['level' => $level->value, 'message' => $message, 'context' => $context]; } }; $this->resolver = new MiddlewareDependencyResolver( $reflectionProvider, $container, $logger ); } public function test_resolves_existing_middlewares_and_filters_missing_ones(): void { $middlewares = [ // Critical middlewares (required by resolver) \App\Framework\Http\Middlewares\ExceptionHandlingMiddleware::class, \App\Framework\Http\Middlewares\RequestIdMiddleware::class, \App\Framework\Http\Middlewares\RoutingMiddleware::class, // Additional middlewares to test \App\Framework\Http\Middlewares\AuthMiddleware::class, // This doesn't exist 'NonExistentMiddleware', // This might have missing dependencies \App\Framework\Http\Middlewares\ResponseGeneratorMiddleware::class, ]; $result = $this->resolver->resolve($middlewares); // Should have some middlewares resolved (at least the simple ones) $this->assertGreaterThan(0, count($result->getMiddlewares())); // Check that logging happened $logMessages = array_column($this->testLog, 'message'); $combinedLog = implode(' ', $logMessages); $this->assertStringContainsString( 'Class not found: NonExistentMiddleware', $combinedLog ); // Should log start and completion $this->assertStringContainsString('Starting resolution for', implode(' ', $logMessages)); $this->assertStringContainsString('Resolution completed with', implode(' ', $logMessages)); } public function test_identifies_middlewares_with_missing_dependencies(): void { // Test a middleware that likely has dependencies $middlewares = [ // Critical middlewares (required by resolver) \App\Framework\Http\Middlewares\ExceptionHandlingMiddleware::class, \App\Framework\Http\Middlewares\RequestIdMiddleware::class, \App\Framework\Http\Middlewares\RoutingMiddleware::class, \App\Framework\Http\Middlewares\ResponseGeneratorMiddleware::class, ]; $result = $this->resolver->resolve($middlewares); // Check if there are warnings about missing dependencies $warningMessages = array_filter($this->testLog, fn ($log) => $log['level'] === 'warning'); if (count($result->getMiddlewares()) === 0) { // If middleware was filtered out, should have warning about missing dependencies $warningText = implode(' ', array_column($warningMessages, 'message')); $this->assertStringContainsString('Missing dependencies for ResponseGeneratorMiddleware', $warningText); } } public function test_logs_middleware_resolution_statistics(): void { $middlewares = [ // Critical middlewares (required by resolver) \App\Framework\Http\Middlewares\ExceptionHandlingMiddleware::class, \App\Framework\Http\Middlewares\RequestIdMiddleware::class, \App\Framework\Http\Middlewares\RoutingMiddleware::class, \App\Framework\Http\Middlewares\AuthMiddleware::class, 'NonExistentMiddleware1', 'NonExistentMiddleware2', ]; $result = $this->resolver->resolve($middlewares); // Extract log messages $logMessages = array_column($this->testLog, 'message'); $combinedLog = implode(' ', $logMessages); // Should log how many middlewares we started with (only existing ones are counted) $this->assertStringContainsString('Starting resolution for 4 middlewares', $combinedLog); // Should log how many we ended up with $this->assertStringContainsString('Resolution completed with', $combinedLog); // Should have warnings about non-existent classes $this->assertStringContainsString('Class not found: NonExistentMiddleware1', $combinedLog); $this->assertStringContainsString('Class not found: NonExistentMiddleware2', $combinedLog); } public function test_dependency_graph_information(): void { $middlewares = [ // Critical middlewares (required by resolver) \App\Framework\Http\Middlewares\ExceptionHandlingMiddleware::class, \App\Framework\Http\Middlewares\RequestIdMiddleware::class, \App\Framework\Http\Middlewares\RoutingMiddleware::class, \App\Framework\Http\Middlewares\AuthMiddleware::class, ]; $result = $this->resolver->resolve($middlewares); $dependencyInfo = $this->resolver->getDependencyInfo($middlewares); // Should have dependency information for each middleware $this->assertArrayHasKey(\App\Framework\Http\Middlewares\RequestIdMiddleware::class, $dependencyInfo); $this->assertArrayHasKey(\App\Framework\Http\Middlewares\AuthMiddleware::class, $dependencyInfo); // Each entry should have expected structure foreach ($dependencyInfo as $className => $info) { if (isset($info['error'])) { continue; // Skip errored ones } $this->assertArrayHasKey('short_name', $info); $this->assertArrayHasKey('exists', $info); $this->assertArrayHasKey('can_instantiate', $info); } } }