- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
335 lines
12 KiB
PHP
335 lines
12 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\Attributes\Route;
|
|
use App\Framework\Core\DynamicRoute;
|
|
use App\Framework\Core\RouteCompiler;
|
|
use App\Framework\Discovery\Visitors\UnifiedRouteVisitor;
|
|
use App\Framework\Router\Result\FileResult;
|
|
use App\Framework\Router\Result\JsonResult;
|
|
|
|
// Test Controller Klassen für Dynamic Routing Tests
|
|
class TestDynamicController
|
|
{
|
|
#[Route('/test/{id}')]
|
|
public function showById(int $id): JsonResult
|
|
{
|
|
return new JsonResult(['id' => $id]);
|
|
}
|
|
|
|
#[Route('/images/{filename}')]
|
|
public function showImage(string $filename): FileResult
|
|
{
|
|
return new FileResult("/path/to/{$filename}");
|
|
}
|
|
|
|
#[Route('/user/{userId}/post/{postId}')]
|
|
public function showUserPost(int $userId, string $postId): JsonResult
|
|
{
|
|
return new JsonResult(['userId' => $userId, 'postId' => $postId]);
|
|
}
|
|
|
|
#[Route('/api/search/{query?}')]
|
|
public function search(?string $query = null): JsonResult
|
|
{
|
|
return new JsonResult(['query' => $query]);
|
|
}
|
|
}
|
|
|
|
describe('Dynamic Routing Parameter Extraction', function () {
|
|
beforeEach(function () {
|
|
$this->discoveryVisitor = new UnifiedRouteVisitor();
|
|
$this->routeCompiler = new RouteCompiler();
|
|
});
|
|
|
|
test('discovers routes with dynamic parameters', function () {
|
|
$this->discoveryVisitor->onScanStart();
|
|
// UnifiedRouteVisitor benötigt ClassName und FilePath Value Objects
|
|
$className = \App\Framework\Core\ValueObjects\ClassName::fromString(TestDynamicController::class);
|
|
$filePath = \App\Framework\Filesystem\FilePath::create('test-file.php');
|
|
$reflection = new \App\Framework\Reflection\WrappedReflectionClass(new \ReflectionClass(TestDynamicController::class));
|
|
|
|
$this->discoveryVisitor->visitClass($className, $filePath, $reflection);
|
|
|
|
$routes = $this->discoveryVisitor->getResults();
|
|
|
|
expect($routes)->toHaveCount(4);
|
|
|
|
// Test route with single parameter
|
|
$singleParamRoute = null;
|
|
foreach ($routes as $route) {
|
|
if ($route['path'] === '/test/{id}') {
|
|
$singleParamRoute = $route;
|
|
|
|
break;
|
|
}
|
|
}
|
|
expect($singleParamRoute)->not->toBeNull();
|
|
expect($singleParamRoute['controller'])->toBe(TestDynamicController::class);
|
|
expect($singleParamRoute['action'])->toBe('showById');
|
|
|
|
// Test image route (the problematic one)
|
|
$imageRoute = null;
|
|
foreach ($routes as $route) {
|
|
if ($route['path'] === '/images/{filename}') {
|
|
$imageRoute = $route;
|
|
|
|
break;
|
|
}
|
|
}
|
|
expect($imageRoute)->not->toBeNull();
|
|
expect($imageRoute['controller'])->toBe(TestDynamicController::class);
|
|
expect($imageRoute['action'])->toBe('showImage');
|
|
|
|
// Test route with multiple parameters
|
|
$multiParamRoute = null;
|
|
foreach ($routes as $route) {
|
|
if ($route['path'] === '/user/{userId}/post/{postId}') {
|
|
$multiParamRoute = $route;
|
|
|
|
break;
|
|
}
|
|
}
|
|
expect($multiParamRoute)->not->toBeNull();
|
|
});
|
|
|
|
test('extracts parameter information correctly', function () {
|
|
$this->discoveryVisitor->onScanStart();
|
|
// UnifiedRouteVisitor benötigt ClassName und FilePath Value Objects
|
|
$className = \App\Framework\Core\ValueObjects\ClassName::fromString(TestDynamicController::class);
|
|
$filePath = \App\Framework\Filesystem\FilePath::create('test-file.php');
|
|
$reflection = new \App\Framework\Reflection\WrappedReflectionClass(new \ReflectionClass(TestDynamicController::class));
|
|
|
|
$this->discoveryVisitor->visitClass($className, $filePath, $reflection);
|
|
|
|
$routes = $this->discoveryVisitor->getResults();
|
|
|
|
// Suche die Image Route
|
|
$imageRoute = null;
|
|
foreach ($routes as $route) {
|
|
if ($route['path'] === '/images/{filename}') {
|
|
$imageRoute = $route;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Prüfe ob Parameter-Informationen vorhanden sind
|
|
if (isset($imageRoute['parameters'])) {
|
|
expect($imageRoute['parameters'])->toBeArray();
|
|
|
|
// Debug: Zeige Parameter-Struktur
|
|
error_log('Image Route Parameters: ' . json_encode($imageRoute['parameters']));
|
|
|
|
// Suche nach filename Parameter
|
|
$filenameParam = null;
|
|
foreach ($imageRoute['parameters'] as $param) {
|
|
if ($param['name'] === 'filename') {
|
|
$filenameParam = $param;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($filenameParam) {
|
|
expect($filenameParam['name'])->toBe('filename');
|
|
expect($filenameParam['type'])->toBe('string'); // Das ist wahrscheinlich null!
|
|
expect($filenameParam['isBuiltin'])->toBeTrue();
|
|
} else {
|
|
error_log('Filename parameter not found in parameters array');
|
|
}
|
|
} else {
|
|
error_log('No parameters found in route array');
|
|
expect($imageRoute)->toHaveKey('parameters'); // Dieser Test wird wahrscheinlich fehlschlagen
|
|
}
|
|
});
|
|
|
|
test('compiles dynamic routes with parameter names', function () {
|
|
$this->discoveryVisitor->onScanStart();
|
|
// UnifiedRouteVisitor benötigt ClassName und FilePath Value Objects
|
|
$className = \App\Framework\Core\ValueObjects\ClassName::fromString(TestDynamicController::class);
|
|
$filePath = \App\Framework\Filesystem\FilePath::create('test-file.php');
|
|
$reflection = new \App\Framework\Reflection\WrappedReflectionClass(new \ReflectionClass(TestDynamicController::class));
|
|
|
|
$this->discoveryVisitor->visitClass($className, $filePath, $reflection);
|
|
|
|
$routes = $this->discoveryVisitor->getResults();
|
|
$compiledRoutes = $this->routeCompiler->compile($routes);
|
|
|
|
// Prüfe GET routes
|
|
expect($compiledRoutes)->toHaveKey('GET');
|
|
expect($compiledRoutes['GET'])->toHaveKey('dynamic');
|
|
|
|
$dynamicRoutes = $compiledRoutes['GET']['dynamic'];
|
|
expect($dynamicRoutes)->toBeArray();
|
|
expect(count($dynamicRoutes))->toBeGreaterThan(0);
|
|
|
|
// Suche Image Route in compilierten Routes
|
|
$imageRoute = null;
|
|
foreach ($dynamicRoutes as $route) {
|
|
if ($route instanceof DynamicRoute && $route->path === '/images/{filename}') {
|
|
$imageRoute = $route;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
expect($imageRoute)->not->toBeNull();
|
|
expect($imageRoute)->toBeInstanceOf(DynamicRoute::class);
|
|
|
|
// Prüfe Parameter Names
|
|
expect($imageRoute->paramNames)->toBe(['filename']);
|
|
|
|
// Prüfe compiled regex
|
|
expect($imageRoute->regex)->toBeString();
|
|
expect($imageRoute->regex)->toMatch('/^~.*\/images\/.*\$~/'); // Regex für /images/{filename}
|
|
|
|
// Prüfe Parameter Details
|
|
error_log('Compiled Image Route Parameters: ' . json_encode($imageRoute->parameters));
|
|
|
|
if (! empty($imageRoute->parameters)) {
|
|
$filenameParam = null;
|
|
foreach ($imageRoute->parameters as $param) {
|
|
if ($param['name'] === 'filename') {
|
|
$filenameParam = $param;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($filenameParam) {
|
|
expect($filenameParam['type'])->not->toBeNull(); // Das sollte nicht null sein!
|
|
expect($filenameParam['type'])->toBe('string');
|
|
}
|
|
}
|
|
});
|
|
|
|
test('handles multiple parameter types correctly', function () {
|
|
$this->discoveryVisitor->onScanStart();
|
|
// UnifiedRouteVisitor benötigt ClassName und FilePath Value Objects
|
|
$className = \App\Framework\Core\ValueObjects\ClassName::fromString(TestDynamicController::class);
|
|
$filePath = \App\Framework\Filesystem\FilePath::create('test-file.php');
|
|
$reflection = new \App\Framework\Reflection\WrappedReflectionClass(new \ReflectionClass(TestDynamicController::class));
|
|
|
|
$this->discoveryVisitor->visitClass($className, $filePath, $reflection);
|
|
|
|
$routes = $this->discoveryVisitor->getResults();
|
|
|
|
// Test verschiedene Parameter-Typen
|
|
$userPostRoute = null;
|
|
foreach ($routes as $route) {
|
|
if ($route['path'] === '/user/{userId}/post/{postId}') {
|
|
$userPostRoute = $route;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isset($userPostRoute['parameters'])) {
|
|
$parameters = $userPostRoute['parameters'];
|
|
|
|
// Suche nach userId (int) und postId (string) Parametern
|
|
$userIdParam = null;
|
|
$postIdParam = null;
|
|
foreach ($parameters as $param) {
|
|
if ($param['name'] === 'userId') {
|
|
$userIdParam = $param;
|
|
} elseif ($param['name'] === 'postId') {
|
|
$postIdParam = $param;
|
|
}
|
|
}
|
|
|
|
if ($userIdParam) {
|
|
expect($userIdParam['type'])->toBe('int');
|
|
expect($userIdParam['isBuiltin'])->toBeTrue();
|
|
}
|
|
|
|
if ($postIdParam) {
|
|
expect($postIdParam['type'])->toBe('string');
|
|
expect($postIdParam['isBuiltin'])->toBeTrue();
|
|
}
|
|
}
|
|
});
|
|
|
|
test('handles optional parameters correctly', function () {
|
|
$this->discoveryVisitor->onScanStart();
|
|
// UnifiedRouteVisitor benötigt ClassName und FilePath Value Objects
|
|
$className = \App\Framework\Core\ValueObjects\ClassName::fromString(TestDynamicController::class);
|
|
$filePath = \App\Framework\Filesystem\FilePath::create('test-file.php');
|
|
$reflection = new \App\Framework\Reflection\WrappedReflectionClass(new \ReflectionClass(TestDynamicController::class));
|
|
|
|
$this->discoveryVisitor->visitClass($className, $filePath, $reflection);
|
|
|
|
$routes = $this->discoveryVisitor->getResults();
|
|
|
|
// Test optionale Parameter
|
|
$searchRoute = null;
|
|
foreach ($routes as $route) {
|
|
if ($route['path'] === '/api/search/{query?}') {
|
|
$searchRoute = $route;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isset($searchRoute['parameters'])) {
|
|
$parameters = $searchRoute['parameters'];
|
|
|
|
$queryParam = null;
|
|
foreach ($parameters as $param) {
|
|
if ($param['name'] === 'query') {
|
|
$queryParam = $param;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($queryParam) {
|
|
expect($queryParam['type'])->toBe('string');
|
|
expect($queryParam['isOptional'])->toBeTrue();
|
|
expect($queryParam['hasDefault'])->toBeTrue();
|
|
expect($queryParam['default'])->toBeNull();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('Dynamic Route Parameter Processing Debug', function () {
|
|
test('shows current parameter extraction workflow', function () {
|
|
$discoveryVisitor = new UnifiedRouteVisitor();
|
|
$discoveryVisitor->onScanStart();
|
|
$className = \App\Framework\Core\ValueObjects\ClassName::fromString(TestDynamicController::class);
|
|
$filePath = \App\Framework\Filesystem\FilePath::create('test-file.php');
|
|
$reflection = new \App\Framework\Reflection\WrappedReflectionClass(new \ReflectionClass(TestDynamicController::class));
|
|
|
|
$discoveryVisitor->visitClass($className, $filePath, $reflection);
|
|
|
|
$routes = $discoveryVisitor->getResults();
|
|
|
|
// Debug: Zeige alle gefundenen Routes
|
|
error_log('=== All discovered routes ===');
|
|
foreach ($routes as $i => $route) {
|
|
error_log("Route {$i}: " . json_encode([
|
|
'path' => $route['path'],
|
|
'controller' => $route['controller'],
|
|
'action' => $route['action'],
|
|
'has_parameters' => isset($route['parameters']),
|
|
'parameter_count' => isset($route['parameters']) ? count($route['parameters']) : 0,
|
|
]));
|
|
|
|
if (isset($route['parameters'])) {
|
|
foreach ($route['parameters'] as $j => $param) {
|
|
error_log(" Parameter {$j}: " . json_encode($param));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Debug: Zeige RouteDiscoveryVisitor interne Struktur
|
|
error_log('=== RouteDiscoveryVisitor internals ===');
|
|
// Wir können nicht auf private Properties zugreifen, aber wir können testen
|
|
|
|
expect(true)->toBeTrue(); // Placeholder - der Test ist für Debug-Zwecke
|
|
});
|
|
});
|