diff --git a/Neos.Flow/Classes/Command/RoutingCommandController.php b/Neos.Flow/Classes/Command/RoutingCommandController.php index acb33fe95c..ae43d4907a 100644 --- a/Neos.Flow/Classes/Command/RoutingCommandController.php +++ b/Neos.Flow/Classes/Command/RoutingCommandController.php @@ -17,7 +17,6 @@ use Neos\Flow\Annotations as Flow; use Neos\Flow\Cli\CommandController; use Neos\Flow\Cli\Exception\StopCommandException; -use Neos\Flow\Configuration\ConfigurationManager; use Neos\Flow\Http\Helper\RequestInformationHelper; use Neos\Flow\Mvc\Exception\InvalidRoutePartValueException; use Neos\Flow\Mvc\Routing\Dto\ResolveContext; @@ -26,7 +25,7 @@ use Neos\Flow\Mvc\Routing\Dto\RouteTags; use Neos\Flow\Mvc\Routing\Dto\UriConstraints; use Neos\Flow\Mvc\Routing\Route; -use Neos\Flow\Mvc\Routing\Router; +use Neos\Flow\Mvc\Routing\RoutesProviderInterface; use Neos\Flow\ObjectManagement\ObjectManagerInterface; use Neos\Http\Factories\ServerRequestFactory; use Neos\Utility\Arrays; @@ -40,15 +39,9 @@ class RoutingCommandController extends CommandController { /** * @Flow\Inject - * @var ConfigurationManager + * @var RoutesProviderInterface */ - protected $configurationManager; - - /** - * @Flow\Inject - * @var Router - */ - protected $router; + protected $routesProvider; /** * @Flow\Inject @@ -73,8 +66,7 @@ public function listCommand(): void { $this->outputLine('Currently registered routes:'); $rows = []; - /** @var Route $route */ - foreach ($this->router->getRoutes() as $index => $route) { + foreach ($this->routesProvider->getRoutes() as $index => $route) { $routeNumber = $index + 1; $rows[] = [ '#' => $routeNumber, @@ -99,15 +91,12 @@ public function listCommand(): void */ public function showCommand(int $index): void { - /** @var Route[] $routes */ - $routes = $this->router->getRoutes(); - if (!isset($routes[$index - 1])) { + $route = $this->routesProvider->getRoutes()[$index - 1] ?? null; + if ($route === null) { $this->outputLine('Route %d was not found!', [$index]); $this->outputLine('Run ./flow routing:list to show all registered routes'); $this->quit(1); - return; } - $route = $routes[$index - 1]; $this->outputLine('Information for route #' . $index . ':'); $this->outputLine(); @@ -203,8 +192,8 @@ public function resolveCommand(string $package, string $controller = null, strin /** @var Route|null $resolvedRoute */ $resolvedRoute = null; $resolvedRouteNumber = 0; - /** @var int $index */ - foreach ($this->router->getRoutes() as $index => $route) { + + foreach ($this->routesProvider->getRoutes() as $index => $route) { /** @var Route $route */ if ($route->resolves($resolveContext) === true) { $resolvedRoute = $route; @@ -216,7 +205,6 @@ public function resolveCommand(string $package, string $controller = null, strin if ($resolvedRoute === null) { $this->outputLine('No route could resolve these values...'); $this->quit(1); - return; } /** @var UriConstraints $uriConstraints */ @@ -273,7 +261,6 @@ public function matchCommand(string $uri, string $method = null, string $paramet if (isset($requestUri->getPath()[0]) && $requestUri->getPath()[0] !== '/') { $this->outputLine('The URI "%s" is not valid. The path has to start with a "/"', [$requestUri]); $this->quit(1); - return; } $httpRequest = $this->serverRequestFactory->createServerRequest($method, $requestUri); $routeParameters = $this->createRouteParametersFromJson($parameters); @@ -292,8 +279,7 @@ public function matchCommand(string $uri, string $method = null, string $paramet /** @var Route|null $matchedRoute */ $matchedRoute = null; $matchedRouteNumber = 0; - /** @var int $index */ - foreach ($this->router->getRoutes() as $index => $route) { + foreach ($this->routesProvider->getRoutes() as $index => $route) { /** @var Route $route */ if ($route->matches($routeContext) === true) { $matchedRoute = $route; @@ -305,7 +291,6 @@ public function matchCommand(string $uri, string $method = null, string $paramet if ($matchedRoute === null) { $this->outputLine('No route could match %s request to URL %s...', [$method, $requestUri]); $this->quit(1); - return; } $this->outputLine('Route matched!'); @@ -365,12 +350,10 @@ private function parseJsonToArray(?string $json): array if ($parsedValue === null && \json_last_error() !== JSON_ERROR_NONE) { $this->outputLine('Failed to parse %s as JSON: %s', [$json, \json_last_error_msg()]); $this->quit(1); - return []; } if (!is_array($parsedValue)) { $this->outputLine('Failed to parse %s to an array, please a provide valid JSON object that can be represented as PHP array', [$json]); $this->quit(1); - return []; } return $parsedValue; } diff --git a/Neos.Flow/Classes/Mvc/Routing/ConfigurationRoutesProvider.php b/Neos.Flow/Classes/Mvc/Routing/ConfigurationRoutesProvider.php new file mode 100644 index 0000000000..f876008e8c --- /dev/null +++ b/Neos.Flow/Classes/Mvc/Routing/ConfigurationRoutesProvider.php @@ -0,0 +1,27 @@ +configurationManager = $configurationManager; + } + + public function getRoutes(): Routes + { + return Routes::fromConfiguration($this->configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_ROUTES)); + } +} diff --git a/Neos.Flow/Classes/Mvc/Routing/Route.php b/Neos.Flow/Classes/Mvc/Routing/Route.php index 2f60eedc2a..0b073796b9 100644 --- a/Neos.Flow/Classes/Mvc/Routing/Route.php +++ b/Neos.Flow/Classes/Mvc/Routing/Route.php @@ -31,6 +31,7 @@ /** * Implementation of a standard route + * @phpstan-consistent-constructor */ class Route { @@ -172,6 +173,41 @@ class Route */ protected $persistenceManager; + public static function fromConfiguration(array $configuration): static + { + /** @phpstan-ignore-next-line phpstan doesn't respekt the consistent constructor flag in the class doc block */ + $route = new static(); + if (isset($configuration['name'])) { + $route->setName($configuration['name']); + } + $uriPattern = $configuration['uriPattern']; + $route->setUriPattern($uriPattern); + if (isset($configuration['defaults'])) { + $route->setDefaults($configuration['defaults']); + } + if (isset($configuration['routeParts'])) { + $route->setRoutePartsConfiguration($configuration['routeParts']); + } + if (isset($configuration['toLowerCase'])) { + $route->setLowerCase($configuration['toLowerCase']); + } + if (isset($configuration['appendExceedingArguments'])) { + $route->setAppendExceedingArguments($configuration['appendExceedingArguments']); + } + if (isset($configuration['cache'])) { + if (isset($configuration['cache']['lifetime'])) { + $route->setCacheLifetime(RouteLifetime::fromInt($configuration['cache']['lifetime'])); + } + if (isset($configuration['cache']['tags']) && !empty($configuration['cache']['lifetime'])) { + $route->setCacheTags(RouteTags::createFromArray($configuration['cache']['tags'])); + } + } + if (isset($configuration['httpMethods'])) { + $route->setHttpMethods($configuration['httpMethods']); + } + return $route; + } + /** * Sets Route name. * diff --git a/Neos.Flow/Classes/Mvc/Routing/Router.php b/Neos.Flow/Classes/Mvc/Routing/Router.php index c66110009d..b4ebe8267c 100644 --- a/Neos.Flow/Classes/Mvc/Routing/Router.php +++ b/Neos.Flow/Classes/Mvc/Routing/Router.php @@ -12,7 +12,6 @@ */ use Neos\Flow\Annotations as Flow; -use Neos\Flow\Configuration\ConfigurationManager; use Neos\Flow\Http\Helper\RequestInformationHelper; use Neos\Flow\Http\Helper\UriHelper; use Neos\Flow\Log\Utility\LogEnvironment; @@ -21,8 +20,6 @@ use Neos\Flow\Mvc\Exception\NoMatchingRouteException; use Neos\Flow\Mvc\Routing\Dto\ResolveContext; use Neos\Flow\Mvc\Routing\Dto\RouteContext; -use Neos\Flow\Mvc\Routing\Dto\RouteLifetime; -use Neos\Flow\Mvc\Routing\Dto\RouteTags; use Psr\Http\Message\UriInterface; use Psr\Log\LoggerInterface; @@ -35,16 +32,16 @@ class Router implements RouterInterface { /** - * @Flow\Inject(name="Neos.Flow:SystemLogger") - * @var LoggerInterface + * @Flow\Inject + * @var RoutesProviderInterface */ - protected $logger; + protected $routesProvider; /** - * @Flow\Inject - * @var ConfigurationManager + * @Flow\Inject(name="Neos.Flow:SystemLogger") + * @var LoggerInterface */ - protected $configurationManager; + protected $logger; /** * @Flow\Inject @@ -52,27 +49,6 @@ class Router implements RouterInterface */ protected $routerCachingService; - /** - * Array containing the configuration for all routes - * - * @var array - */ - protected $routesConfiguration = null; - - /** - * Array of routes to match against - * - * @var array - */ - protected $routes = []; - - /** - * true if route object have been created, otherwise false - * - * @var boolean - */ - protected $routesCreated = false; - /** * @var Route */ @@ -94,25 +70,13 @@ public function injectLogger(LoggerInterface $logger) $this->logger = $logger; } - /** - * Sets the routes configuration. - * - * @param array|null $routesConfiguration The routes configuration or NULL if it should be fetched from configuration - * @return void - */ - public function setRoutesConfiguration(array $routesConfiguration = null) - { - $this->routesConfiguration = $routesConfiguration; - $this->routesCreated = false; - } - /** * Iterates through all configured routes and calls matches() on them. * Returns the matchResults of the matching route or NULL if no matching * route could be found. * * @param RouteContext $routeContext The Route Context containing the current HTTP Request and, optional, Routing RouteParameters - * @return array The results of the matching route + * @return array The results of the matching route or NULL if no route matched * @throws InvalidRouteSetupException * @throws NoMatchingRouteException if no route matched the given $routeContext * @throws InvalidRoutePartValueException @@ -124,10 +88,10 @@ public function route(RouteContext $routeContext): array if ($cachedRouteResult !== false) { return $cachedRouteResult; } - $this->createRoutesFromConfiguration(); + $httpRequest = $routeContext->getHttpRequest(); - foreach ($this->routes as $route) { + foreach ($this->routesProvider->getRoutes() as $route) { if ($route->matches($routeContext) === true) { $this->lastMatchedRoute = $route; $matchResults = $route->getMatchResults(); @@ -152,29 +116,6 @@ public function getLastMatchedRoute() return $this->lastMatchedRoute; } - /** - * Returns a list of configured routes - * - * @return array - */ - public function getRoutes() - { - $this->createRoutesFromConfiguration(); - return $this->routes; - } - - /** - * Manually adds a route to the beginning of the configured routes - * - * @param Route $route - * @return void - */ - public function addRoute(Route $route) - { - $this->createRoutesFromConfiguration(); - array_unshift($this->routes, $route); - } - /** * Builds the corresponding uri (excluding protocol and host) by iterating * through all configured routes and calling their respective resolves() @@ -193,9 +134,7 @@ public function resolve(ResolveContext $resolveContext): UriInterface return $cachedResolvedUriConstraints->applyTo($resolveContext->getBaseUri(), $resolveContext->isForceAbsoluteUri()); } - $this->createRoutesFromConfiguration(); - - foreach ($this->routes as $route) { + foreach ($this->routesProvider->getRoutes() as $route) { if ($route->resolves($resolveContext) === true) { $uriConstraints = $route->getResolvedUriConstraints()->withPathPrefix($resolveContext->getUriPathPrefix()); $resolvedUri = $uriConstraints->applyTo($resolveContext->getBaseUri(), $resolveContext->isForceAbsoluteUri()); @@ -218,75 +157,4 @@ public function getLastResolvedRoute() { return $this->lastResolvedRoute; } - - /** - * Creates \Neos\Flow\Mvc\Routing\Route objects from the injected routes - * configuration. - * - * @return void - * @throws InvalidRouteSetupException - */ - protected function createRoutesFromConfiguration() - { - if ($this->routesCreated === true) { - return; - } - $this->initializeRoutesConfiguration(); - $this->routes = []; - $routesWithHttpMethodConstraints = []; - foreach ($this->routesConfiguration as $routeConfiguration) { - $route = new Route(); - if (isset($routeConfiguration['name'])) { - $route->setName($routeConfiguration['name']); - } - $uriPattern = $routeConfiguration['uriPattern']; - $route->setUriPattern($uriPattern); - if (isset($routeConfiguration['defaults'])) { - $route->setDefaults($routeConfiguration['defaults']); - } - if (isset($routeConfiguration['routeParts'])) { - $route->setRoutePartsConfiguration($routeConfiguration['routeParts']); - } - if (isset($routeConfiguration['toLowerCase'])) { - $route->setLowerCase($routeConfiguration['toLowerCase']); - } - if (isset($routeConfiguration['appendExceedingArguments'])) { - $route->setAppendExceedingArguments($routeConfiguration['appendExceedingArguments']); - } - if (isset($routeConfiguration['httpMethods'])) { - if (isset($routesWithHttpMethodConstraints[$uriPattern]) && $routesWithHttpMethodConstraints[$uriPattern] === false) { - throw new InvalidRouteSetupException(sprintf('There are multiple routes with the uriPattern "%s" and "httpMethods" option set. Please specify accepted HTTP methods for all of these, or adjust the uriPattern', $uriPattern), 1365678427); - } - $routesWithHttpMethodConstraints[$uriPattern] = true; - $route->setHttpMethods($routeConfiguration['httpMethods']); - } else { - if (isset($routesWithHttpMethodConstraints[$uriPattern]) && $routesWithHttpMethodConstraints[$uriPattern] === true) { - throw new InvalidRouteSetupException(sprintf('There are multiple routes with the uriPattern "%s" and "httpMethods" option set. Please specify accepted HTTP methods for all of these, or adjust the uriPattern', $uriPattern), 1365678432); - } - $routesWithHttpMethodConstraints[$uriPattern] = false; - } - if (isset($routeConfiguration['cache'])) { - if (isset($routeConfiguration['cache']['lifetime']) && !is_null($routeConfiguration['cache']['lifetime'])) { - $route->setCacheLifetime(RouteLifetime::fromInt($routeConfiguration['cache']['lifetime'])); - } - if (isset($routeConfiguration['cache']['tags']) && !empty($routeConfiguration['cache']['lifetime'])) { - $route->setCacheTags(RouteTags::createFromArray($routeConfiguration['cache']['tags'])); - } - } - $this->routes[] = $route; - } - $this->routesCreated = true; - } - - /** - * Checks if a routes configuration was set and otherwise loads the configuration from the configuration manager. - * - * @return void - */ - protected function initializeRoutesConfiguration() - { - if ($this->routesConfiguration === null) { - $this->routesConfiguration = $this->configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_ROUTES); - } - } } diff --git a/Neos.Flow/Classes/Mvc/Routing/Routes.php b/Neos.Flow/Classes/Mvc/Routing/Routes.php new file mode 100644 index 0000000000..cc0822c971 --- /dev/null +++ b/Neos.Flow/Classes/Mvc/Routing/Routes.php @@ -0,0 +1,75 @@ + + */ +final class Routes implements \IteratorAggregate +{ + /** + * @var array + */ + private array $routes; + + private function __construct( + Route ...$routes + ) { + $this->routes = $routes; + + // validate that each route is unique + $routesWithHttpMethodConstraints = []; + foreach ($this->routes as $route) { + $uriPattern = $route->getUriPattern(); + if ($route->hasHttpMethodConstraints()) { + if (isset($routesWithHttpMethodConstraints[$uriPattern]) && $routesWithHttpMethodConstraints[$uriPattern] === false) { + throw new InvalidRouteSetupException(sprintf('There are multiple routes with the uriPattern "%s" and "httpMethods" option set. Please specify accepted HTTP methods for all of these, or adjust the uriPattern', $uriPattern), 1365678427); + } + $routesWithHttpMethodConstraints[$uriPattern] = true; + } else { + if (isset($routesWithHttpMethodConstraints[$uriPattern]) && $routesWithHttpMethodConstraints[$uriPattern] === true) { + throw new InvalidRouteSetupException(sprintf('There are multiple routes with the uriPattern "%s" and "httpMethods" option set. Please specify accepted HTTP methods for all of these, or adjust the uriPattern', $uriPattern), 1365678432); + } + $routesWithHttpMethodConstraints[$uriPattern] = false; + } + } + } + + public static function create(Route ...$routes): self + { + return new self(...$routes); + } + + public static function fromConfiguration(array $configuration): self + { + $routes = []; + foreach ($configuration as $routeConfiguration) { + $routes[] = Route::fromConfiguration($routeConfiguration); + } + return new self(...$routes); + } + + public static function empty(): self + { + return new self(); + } + + public function merge(Routes $other): self + { + return new self(...$this->routes, ...$other->routes); + } + + /** + * @return \Traversable + */ + public function getIterator(): Traversable + { + yield from $this->routes; + } +} diff --git a/Neos.Flow/Classes/Mvc/Routing/RoutesProviderInterface.php b/Neos.Flow/Classes/Mvc/Routing/RoutesProviderInterface.php new file mode 100644 index 0000000000..5cd3f98ae6 --- /dev/null +++ b/Neos.Flow/Classes/Mvc/Routing/RoutesProviderInterface.php @@ -0,0 +1,18 @@ +additionalRoutes = Routes::empty(); + } + + /** + * Prepends a route additionally to the routes form the Testing context configuration + * + * @internal Please use {@see FunctionalTestCase::registerRoute} instead. + */ + public function addRoute(Route $route) + { + // we prepended the route, like the old Router::addRoute + $this->additionalRoutes = Routes::create($route)->merge($this->additionalRoutes); + } + + public function reset(): void + { + $this->additionalRoutes = Routes::empty(); + } + + public function getRoutes(): Routes + { + // we prepended all additional routes, like the old Router::addRoute + return $this->additionalRoutes->merge( + $this->configurationRoutesProvider->getRoutes() + ); + } +} diff --git a/Neos.Flow/Configuration/Objects.yaml b/Neos.Flow/Configuration/Objects.yaml index be14f55c1e..4f116f465d 100644 --- a/Neos.Flow/Configuration/Objects.yaml +++ b/Neos.Flow/Configuration/Objects.yaml @@ -257,6 +257,9 @@ Neos\Flow\Http\Middleware\MiddlewaresChain: Neos\Flow\Mvc\Routing\RouterInterface: className: Neos\Flow\Mvc\Routing\Router +Neos\Flow\Mvc\Routing\RoutesProviderInterface: + className: Neos\Flow\Mvc\Routing\ConfigurationRoutesProvider + Neos\Flow\Mvc\Routing\RouterCachingService: properties: routeCache: diff --git a/Neos.Flow/Configuration/Testing/Objects.yaml b/Neos.Flow/Configuration/Testing/Objects.yaml index 35c3348b3b..5ab4af6180 100644 --- a/Neos.Flow/Configuration/Testing/Objects.yaml +++ b/Neos.Flow/Configuration/Testing/Objects.yaml @@ -15,6 +15,11 @@ Neos\Flow\Http\Client\Browser: properties: requestEngine: object: Neos\Flow\Http\Client\InternalRequestEngine +# +# Routing will be extended to be able to add custom routes at runtime +# +Neos\Flow\Mvc\Routing\RoutesProviderInterface: + className: Neos\Flow\Mvc\Routing\TestingRoutesProvider # # Security and PersistentResource handling need specialized testing classes: diff --git a/Neos.Flow/Tests/Functional/Http/Client/InternalRequestEngineTest.php b/Neos.Flow/Tests/Functional/Http/Client/InternalRequestEngineTest.php index d779fe9949..4af43df7cb 100644 --- a/Neos.Flow/Tests/Functional/Http/Client/InternalRequestEngineTest.php +++ b/Neos.Flow/Tests/Functional/Http/Client/InternalRequestEngineTest.php @@ -11,7 +11,6 @@ * source code. */ -use Neos\Flow\Mvc\Routing\Route; use Neos\Flow\Tests\FunctionalTestCase; /** @@ -31,17 +30,17 @@ protected function setUp(): void { parent::setUp(); - $route = new Route(); - $route->setName('Functional Test - Http::Client::InternalRequestEngine'); - $route->setUriPattern('test/security/restricted'); - $route->setDefaults([ - '@package' => 'Neos.Flow', - '@subpackage' => 'Tests\Functional\Security\Fixtures', - '@controller' => 'Restricted', - '@action' => 'admin', - '@format' => 'html' - ]); - $this->router->addRoute($route); + $this->registerRoute( + 'Functional Test - Http::Client::InternalRequestEngine', + 'test/security/restricted', + [ + '@package' => 'Neos.Flow', + '@subpackage' => 'Tests\Functional\Security\Fixtures', + '@controller' => 'Restricted', + '@action' => 'admin', + '@format' => 'html' + ] + ); } /** diff --git a/Neos.Flow/Tests/Functional/Http/RequestHandlerTest.php b/Neos.Flow/Tests/Functional/Http/RequestHandlerTest.php index 93a7dfac36..9851abb58f 100644 --- a/Neos.Flow/Tests/Functional/Http/RequestHandlerTest.php +++ b/Neos.Flow/Tests/Functional/Http/RequestHandlerTest.php @@ -11,6 +11,7 @@ * source code. */ +use Neos\Flow\Configuration\ConfigurationManager; use Neos\Flow\Http\RequestHandler; use Neos\Flow\Tests\FunctionalTestCase; use PHPUnit\Framework\MockObject\MockObject; @@ -31,14 +32,11 @@ class RequestHandlerTest extends FunctionalTestCase */ public function httpRequestIsConvertedToAnActionRequestAndDispatchedToTheRespectiveController(): void { - $foundRoute = false; - foreach ($this->router->getRoutes() as $route) { - if ($route->getName() === 'Neos.Flow :: Functional Test: HTTP - FooController') { - $foundRoute = true; - } - } - if (!$foundRoute) { - self::markTestSkipped('In this distribution the Flow routes are not included into the global configuration.'); + if ( + ($this->objectManager->get(ConfigurationManager::class) + ->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'Neos.Flow.mvc.routes')['Neos.Flow'] ?? false) !== true + ) { + self::markTestSkipped(sprintf('In this distribution the Flow routes are not included into the global configuration and thus cannot be tested. Please set in Neos.Flow.mvc.routes "Neos.Flow": true.')); } $_SERVER = [ diff --git a/Neos.Flow/Tests/Functional/Mvc/AbstractControllerTest.php b/Neos.Flow/Tests/Functional/Mvc/AbstractControllerTest.php index cf238db8db..facf6d3ef0 100644 --- a/Neos.Flow/Tests/Functional/Mvc/AbstractControllerTest.php +++ b/Neos.Flow/Tests/Functional/Mvc/AbstractControllerTest.php @@ -11,7 +11,6 @@ * source code. */ -use Neos\Flow\Mvc\Routing\Route; use Neos\Flow\Tests\FunctionalTestCase; class AbstractControllerTest extends FunctionalTestCase @@ -27,18 +26,17 @@ class AbstractControllerTest extends FunctionalTestCase protected function setUp(): void { parent::setUp(); - - $route = new Route(); - $route->setName('AbstractControllerTest Route 1'); - $route->setUriPattern('test/mvc/abstractcontrollertesta/{@action}'); - $route->setDefaults([ - '@package' => 'Neos.Flow', - '@subpackage' => 'Tests\Functional\Mvc\Fixtures', - '@controller' => 'AbstractControllerTestA', - '@format' =>'html' - ]); - $route->setAppendExceedingArguments(true); - $this->router->addRoute($route); + $this->registerRoute( + 'AbstractControllerTest Route 1', + 'test/mvc/abstractcontrollertesta/{@action}', + [ + '@package' => 'Neos.Flow', + '@subpackage' => 'Tests\Functional\Mvc\Fixtures', + '@controller' => 'AbstractControllerTestA', + '@format' =>'html' + ], + true + ); } /** diff --git a/Neos.Flow/Tests/Functional/Mvc/RoutingTest.php b/Neos.Flow/Tests/Functional/Mvc/RoutingTest.php index 726aeddce6..814e8a2700 100644 --- a/Neos.Flow/Tests/Functional/Mvc/RoutingTest.php +++ b/Neos.Flow/Tests/Functional/Mvc/RoutingTest.php @@ -12,12 +12,14 @@ */ use GuzzleHttp\Psr7\Uri; +use Neos\Flow\Configuration\ConfigurationManager; use Neos\Flow\Mvc\ActionRequest; use Neos\Flow\Mvc\Exception\NoMatchingRouteException; use Neos\Flow\Mvc\Routing\Dto\RouteParameters; use Neos\Flow\Mvc\Routing\Dto\ResolveContext; use Neos\Flow\Mvc\Routing\Dto\RouteContext; use Neos\Flow\Mvc\Routing\Route; +use Neos\Flow\Mvc\Routing\TestingRoutesProvider; use Neos\Flow\Tests\Functional\Mvc\Fixtures\Controller\ActionControllerTestAController; use Neos\Flow\Tests\Functional\Mvc\Fixtures\Controller\RoutingTestAController; use Neos\Flow\Tests\FunctionalTestCase; @@ -46,18 +48,11 @@ protected function setUp(): void parent::setUp(); $this->serverRequestFactory = $this->objectManager->get(ServerRequestFactoryInterface::class); - $foundRoute = false; - /** @var $route Route */ - foreach ($this->router->getRoutes() as $route) { - if ($route->getName() === 'Neos.Flow :: Functional Test: HTTP - FooController') { - $foundRoute = true; - break; - } - } - - if (!$foundRoute) { - self::markTestSkipped('In this distribution the Flow routes are not included into the global configuration.'); - return; + if ( + ($this->objectManager->get(ConfigurationManager::class) + ->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'Neos.Flow.mvc.routes')['Neos.Flow'] ?? false) !== true + ) { + self::markTestSkipped(sprintf('In this distribution the Flow routes are not included into the global configuration and thus cannot be tested. Please set in Neos.Flow.mvc.routes "Neos.Flow": true.')); } } @@ -386,7 +381,7 @@ public function uriPathPrefixIsRespectedInRoute() /** * @test */ - public function explicitlySpecifiedRoutesOverruleConfiguredRoutes() + public function testingRoutesProviderCanRegisterOwnRoute() { $routeValues = [ '@package' => 'Neos.Flow', @@ -395,24 +390,20 @@ public function explicitlySpecifiedRoutesOverruleConfiguredRoutes() '@action' => 'index', '@format' => 'html' ]; - $routesConfiguration = [ - [ - 'uriPattern' => 'custom/uri/pattern', - 'defaults' => [ - '@package' => 'Neos.Flow', - '@subpackage' => 'Tests\Functional\Http\Fixtures', - '@controller' => 'Foo', - '@action' => 'index', - '@format' => 'html' - ], - ] - ]; - $this->router->setRoutesConfiguration($routesConfiguration); + + $this->objectManager->get(TestingRoutesProvider::class)->addRoute(Route::fromConfiguration([ + 'uriPattern' => 'custom/uri/pattern', + 'defaults' => [ + '@package' => 'Neos.Flow', + '@subpackage' => 'Tests\Functional\Http\Fixtures', + '@controller' => 'Foo', + '@action' => 'index', + '@format' => 'html' + ], + ])); + $baseUri = new Uri('http://localhost'); $actualResult = $this->router->resolve(new ResolveContext($baseUri, $routeValues, false, '', RouteParameters::createEmpty())); self::assertSame('/custom/uri/pattern', (string)$actualResult); - - // reset router configuration for following tests - $this->router->setRoutesConfiguration(null); } } diff --git a/Neos.Flow/Tests/Functional/Mvc/UriBuilderTest.php b/Neos.Flow/Tests/Functional/Mvc/UriBuilderTest.php index 397a976613..97cbcc1e30 100644 --- a/Neos.Flow/Tests/Functional/Mvc/UriBuilderTest.php +++ b/Neos.Flow/Tests/Functional/Mvc/UriBuilderTest.php @@ -126,7 +126,7 @@ public function whenLinkingToSameHostTheUrlIsAsExpectedNotContainingDoubleSlashe */ public function whenLinkingToRootOfSameHostTheUrlContainsASingleSlash() { - // NOTE: the route part handler here does not really match; as we link to the the route + // NOTE: the route part handler here does not really match; as we link to the route // registered in "registerAbsoluteRoute()". $this->registerSingleRoute(UriBuilderSetDomainRoutePartHandler::class); // NOTE: the registered route is PREPENDED to the existing list; so we need to register the absolute route LAST as it should match FIRST. diff --git a/Neos.Flow/Tests/Functional/Security/AuthenticationTest.php b/Neos.Flow/Tests/Functional/Security/AuthenticationTest.php index 9d283088c4..7b54050948 100644 --- a/Neos.Flow/Tests/Functional/Security/AuthenticationTest.php +++ b/Neos.Flow/Tests/Functional/Security/AuthenticationTest.php @@ -12,7 +12,6 @@ */ use GuzzleHttp\Psr7\Uri; -use Neos\Flow\Mvc\Routing\Route; use Neos\Flow\Security\AccountFactory; use Neos\Flow\Security\AccountRepository; use Neos\Flow\Tests\FunctionalTestCase; @@ -56,57 +55,57 @@ protected function setUp(): void $accountRepository->add($account3); $this->persistenceManager->persistAll(); - $route = new Route(); - $route->setName('Functional Test - Security::Restricted'); - $route->setUriPattern('test/security/restricted(/{@action})'); - $route->setDefaults([ - '@package' => 'Neos.Flow', - '@subpackage' => 'Tests\Functional\Security\Fixtures', - '@controller' => 'Restricted', - '@action' => 'public', - '@format' =>'html' - ]); - $route->setAppendExceedingArguments(true); - $this->router->addRoute($route); - - $route2 = new Route(); - $route2->setName('Functional Test - Security::Authentication'); - $route2->setUriPattern('test/security/authentication(/{@action})'); - $route2->setDefaults([ - '@package' => 'Neos.Flow', - '@subpackage' => 'Tests\Functional\Security\Fixtures', - '@controller' => 'Authentication', - '@action' => 'authenticate', - '@format' => 'html' - ]); - $route2->setAppendExceedingArguments(true); - $this->router->addRoute($route2); - - $route3 = new Route(); - $route3->setName('Functional Test - Security::HttpBasicAuthentication'); - $route3->setUriPattern('test/security/authentication/httpbasic(/{@action})'); - $route3->setDefaults([ - '@package' => 'Neos.Flow', - '@subpackage' => 'Tests\Functional\Security\Fixtures', - '@controller' => 'HttpBasicTest', - '@action' => 'authenticate', - '@format' => 'html' - ]); - $route3->setAppendExceedingArguments(true); - $this->router->addRoute($route3); - - $route4 = new Route(); - $route4->setName('Functional Test - Security::UsernamePasswordAuthentication'); - $route4->setUriPattern('test/security/authentication/usernamepassword(/{@action})'); - $route4->setDefaults([ - '@package' => 'Neos.Flow', - '@subpackage' => 'Tests\Functional\Security\Fixtures', - '@controller' => 'UsernamePasswordTest', - '@action' => 'authenticate', - '@format' => 'html' - ]); - $route4->setAppendExceedingArguments(true); - $this->router->addRoute($route4); + $this->registerRoute( + 'Functional Test - Security::Restricted', + 'test/security/restricted(/{@action})', + [ + '@package' => 'Neos.Flow', + '@subpackage' => 'Tests\Functional\Security\Fixtures', + '@controller' => 'Restricted', + '@action' => 'public', + '@format' =>'html' + ], + true + ); + + $this->registerRoute( + 'Functional Test - Security::Authentication', + 'test/security/authentication(/{@action})', + [ + '@package' => 'Neos.Flow', + '@subpackage' => 'Tests\Functional\Security\Fixtures', + '@controller' => 'Authentication', + '@action' => 'authenticate', + '@format' => 'html' + ], + true + ); + + $this->registerRoute( + 'Functional Test - Security::HttpBasicAuthentication', + 'test/security/authentication/httpbasic(/{@action})', + [ + '@package' => 'Neos.Flow', + '@subpackage' => 'Tests\Functional\Security\Fixtures', + '@controller' => 'HttpBasicTest', + '@action' => 'authenticate', + '@format' => 'html' + ], + true + ); + + $this->registerRoute( + 'Functional Test - Security::UsernamePasswordAuthentication', + 'test/security/authentication/usernamepassword(/{@action})', + [ + '@package' => 'Neos.Flow', + '@subpackage' => 'Tests\Functional\Security\Fixtures', + '@controller' => 'UsernamePasswordTest', + '@action' => 'authenticate', + '@format' => 'html' + ], + true + ); $this->serverRequestFactory = $this->objectManager->get(ServerRequestFactoryInterface::class); } diff --git a/Neos.Flow/Tests/Functional/Session/SessionManagementTest.php b/Neos.Flow/Tests/Functional/Session/SessionManagementTest.php index 726850b1aa..8f309970c7 100644 --- a/Neos.Flow/Tests/Functional/Session/SessionManagementTest.php +++ b/Neos.Flow/Tests/Functional/Session/SessionManagementTest.php @@ -11,7 +11,6 @@ * source code. */ -use Neos\Flow\Mvc\Routing\Route; use Neos\Flow\Tests\FunctionalTestCase; use Neos\Flow\Session; @@ -24,17 +23,17 @@ protected function setUp(): void { parent::setUp(); - $route = new Route(); - $route->setName('Functional Test - Session::SessionTest'); - $route->setUriPattern('test/session(/{@action})'); - $route->setDefaults([ - '@package' => 'Neos.Flow', - '@subpackage' => 'Tests\Functional\Session\Fixtures', - '@controller' => 'SessionTest', - '@action' => 'sessionStart', - '@format' =>'html' - ]); - $this->router->addRoute($route); + $this->registerRoute( + 'Functional Test - Session::SessionTest', + 'test/session(/{@action})', + [ + '@package' => 'Neos.Flow', + '@subpackage' => 'Tests\Functional\Session\Fixtures', + '@controller' => 'SessionTest', + '@action' => 'sessionStart', + '@format' =>'html' + ] + ); } /** diff --git a/Neos.Flow/Tests/FunctionalTestCase.php b/Neos.Flow/Tests/FunctionalTestCase.php index 6af2923449..64b7347b82 100644 --- a/Neos.Flow/Tests/FunctionalTestCase.php +++ b/Neos.Flow/Tests/FunctionalTestCase.php @@ -14,6 +14,7 @@ use Neos\Flow\Configuration\ConfigurationManager; use Neos\Flow\Core\Bootstrap; use Neos\Flow\Annotations as Flow; +use Neos\Flow\Mvc\Routing\TestingRoutesProvider; use Neos\Flow\Security\Authentication\TokenAndProviderFactory; use Neos\Http\Factories\ServerRequestFactory; use Neos\Http\Factories\UriFactory; @@ -263,6 +264,7 @@ protected function tearDown(): void } self::$bootstrap->getObjectManager()->forgetInstance(\Neos\Flow\Http\Client\InternalRequestEngine::class); + self::$bootstrap->getObjectManager()->get(TestingRoutesProvider::class)->reset(); self::$bootstrap->getObjectManager()->forgetInstance(\Neos\Flow\Persistence\Aspect\PersistenceMagicAspect::class); $this->inject(self::$bootstrap->getObjectManager()->get(\Neos\Flow\ResourceManagement\ResourceRepository::class), 'addedResources', new \SplObjectStorage()); $this->inject(self::$bootstrap->getObjectManager()->get(\Neos\Flow\ResourceManagement\ResourceRepository::class), 'removedResources', new \SplObjectStorage()); @@ -369,7 +371,10 @@ protected function registerRoute($name, $uriPattern, array $defaults, $appendExc if ($httpMethods !== null) { $route->setHttpMethods($httpMethods); } - $this->router->addRoute($route); + + $testingRoutesProvider = $this->objectManager->get(TestingRoutesProvider::class); + $testingRoutesProvider->addRoute($route); + return $route; } @@ -430,7 +435,6 @@ protected function setupHttp() $this->browser = new \Neos\Flow\Http\Client\Browser(); $this->browser->setRequestEngine(new \Neos\Flow\Http\Client\InternalRequestEngine()); $this->router = $this->browser->getRequestEngine()->getRouter(); - $this->router->setRoutesConfiguration(null); $serverRequestFactory = new ServerRequestFactory(new UriFactory()); $request = $serverRequestFactory->createServerRequest('GET', 'http://localhost/neos/flow/test'); diff --git a/Neos.Flow/Tests/Unit/Mvc/Routing/ConfigurationRoutesProviderTest.php b/Neos.Flow/Tests/Unit/Mvc/Routing/ConfigurationRoutesProviderTest.php new file mode 100644 index 0000000000..08651da9ad --- /dev/null +++ b/Neos.Flow/Tests/Unit/Mvc/Routing/ConfigurationRoutesProviderTest.php @@ -0,0 +1,77 @@ +createMock(ConfigurationManager::class); + $mockConfigurationManager->expects($this->never())->method('getConfiguration'); + $configurationRoutesProvider = new Routing\ConfigurationRoutesProvider($mockConfigurationManager); + $this->assertInstanceOf(Routing\ConfigurationRoutesProvider::class, $configurationRoutesProvider); + } + + /** + * @test + */ + public function configurationFomConfigurationManagerIsHandled(): void + { + $configuration = [ + [ + 'name' => 'Route 1', + 'uriPattern' => 'route1/{@package}/{@controller}/{@action}(.{@format})', + 'defaults' => ['@format' => 'html'] + ], + [ + 'name' => 'Route 2', + 'uriPattern' => 'route2/{@package}/{@controller}/{@action}(.{@format})', + 'defaults' => ['@format' => 'html'], + 'appendExceedingArguments' => true, + 'cache' => ['lifetime' => 10000, 'tags' => ['foo', 'bar']] + ], + ]; + + $mockConfigurationManager = $this->createMock(ConfigurationManager::class); + $mockConfigurationManager->expects($this->once())->method('getConfiguration')->with(ConfigurationManager::CONFIGURATION_TYPE_ROUTES)->willReturn($configuration); + + $expectedRoute1 = new Route(); + $expectedRoute1->setName('Route 1'); + $expectedRoute1->setUriPattern('route1/{@package}/{@controller}/{@action}(.{@format})'); + $expectedRoute1->setDefaults(['@format' => 'html']); + + $expectedRoute2 = new Route(); + $expectedRoute2->setName('Route 2'); + $expectedRoute2->setUriPattern('route2/{@package}/{@controller}/{@action}(.{@format})'); + $expectedRoute2->setDefaults(['@format' => 'html']); + $expectedRoute2->setCacheLifetime(Routing\Dto\RouteLifetime::fromInt(10000)); + $expectedRoute2->setCacheTags(Routing\Dto\RouteTags::createFromArray(['foo', 'bar'])); + $expectedRoute2->setAppendExceedingArguments(true); + + $expectedRoutes = Routes::create($expectedRoute1, $expectedRoute2); + + $configurationRoutesProvider = new Routing\ConfigurationRoutesProvider($mockConfigurationManager); + $this->assertEquals($expectedRoutes, $configurationRoutesProvider->getRoutes()); + } +} diff --git a/Neos.Flow/Tests/Unit/Mvc/Routing/RouterTest.php b/Neos.Flow/Tests/Unit/Mvc/Routing/RouterTest.php index 3102cc8247..a793bf623b 100644 --- a/Neos.Flow/Tests/Unit/Mvc/Routing/RouterTest.php +++ b/Neos.Flow/Tests/Unit/Mvc/Routing/RouterTest.php @@ -11,9 +11,6 @@ * source code. */ -use GuzzleHttp\Psr7\Uri; -use Neos\Flow\Configuration\ConfigurationManager; -use Neos\Flow\Mvc\Exception\InvalidRouteSetupException; use Neos\Flow\Mvc\Exception\NoMatchingRouteException; use Neos\Flow\Mvc\Routing\Dto\RouteLifetime; use Neos\Flow\Mvc\Routing\Dto\RouteParameters; @@ -25,6 +22,8 @@ use Neos\Flow\Mvc\Routing\Router; use Neos\Flow\Mvc\Routing\RouterCachingService; use Neos\Flow\Mvc\ActionRequest; +use Neos\Flow\Mvc\Routing\Routes; +use Neos\Flow\Mvc\Routing\RoutesProviderInterface; use Neos\Flow\Tests\UnitTestCase; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\UriInterface; @@ -73,6 +72,10 @@ protected function setUp(): void { $this->router = $this->getAccessibleMock(Router::class, ['dummy']); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->method('getRoutes')->willReturn(Routes::empty()); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); + $this->mockSystemLogger = $this->createMock(LoggerInterface::class); $this->inject($this->router, 'logger', $this->mockSystemLogger); @@ -99,101 +102,13 @@ protected function setUp(): void $this->mockActionRequest = $this->getMockBuilder(ActionRequest::class)->disableOriginalConstructor()->getMock(); } - /** - * @test - */ - public function resolveCallsCreateRoutesFromConfiguration() - { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - - // not saying anything, but seems better than to expect the exception we'd get otherwise - /** @var Route|\PHPUnit\Framework\MockObject\MockObject $mockRoute */ - $mockRoute = $this->createMock(Route::class); - $mockRoute->expects(self::once())->method('resolves')->willReturn(true); - $mockRoute->expects(self::atLeastOnce())->method('getResolvedUriConstraints')->willReturn(UriConstraints::create()); - - $this->inject($router, 'routes', [$mockRoute]); - - // this we actually want to know - $router->expects(self::once())->method('createRoutesFromConfiguration'); - $router->resolve(new ResolveContext($this->mockBaseUri, [], false, '', RouteParameters::createEmpty())); - } - - /** - * @test - */ - public function createRoutesFromConfigurationParsesTheGivenConfigurationAndBuildsRouteObjectsFromIt() - { - $routesConfiguration = []; - $routesConfiguration['route1']['uriPattern'] = 'number1'; - $routesConfiguration['route2']['uriPattern'] = 'number2'; - $routesConfiguration['route3'] = [ - 'name' => 'route3', - 'defaults' => ['foodefault'], - 'routeParts' => ['fooroutepart'], - 'uriPattern' => 'number3', - 'toLowerCase' => false, - 'appendExceedingArguments' => true, - 'httpMethods' => ['POST', 'PUT'] - ]; - - $this->router->setRoutesConfiguration($routesConfiguration); - $this->router->_call('createRoutesFromConfiguration'); - - /** @var Route[] $createdRoutes */ - $createdRoutes = $this->router->_get('routes'); - - self::assertEquals('number1', $createdRoutes[0]->getUriPattern()); - self::assertTrue($createdRoutes[0]->isLowerCase()); - self::assertFalse($createdRoutes[0]->getAppendExceedingArguments()); - self::assertEquals('number2', $createdRoutes[1]->getUriPattern()); - self::assertFalse($createdRoutes[1]->hasHttpMethodConstraints()); - self::assertEquals([], $createdRoutes[1]->getHttpMethods()); - self::assertEquals('route3', $createdRoutes[2]->getName()); - self::assertEquals(['foodefault'], $createdRoutes[2]->getDefaults()); - self::assertEquals(['fooroutepart'], $createdRoutes[2]->getRoutePartsConfiguration()); - self::assertEquals('number3', $createdRoutes[2]->getUriPattern()); - self::assertFalse($createdRoutes[2]->isLowerCase()); - self::assertTrue($createdRoutes[2]->getAppendExceedingArguments()); - self::assertTrue($createdRoutes[2]->hasHttpMethodConstraints()); - self::assertEquals(['POST', 'PUT'], $createdRoutes[2]->getHttpMethods()); - } - - /** - * @test - */ - public function createRoutesFromConfigurationThrowsExceptionIfOnlySomeRoutesWithTheSameUriPatternHaveHttpMethodConstraints() - { - $this->expectException(InvalidRouteSetupException::class); - $routesConfiguration = [ - [ - 'uriPattern' => 'somePattern' - ], - [ - 'uriPattern' => 'somePattern', - 'httpMethods' => ['POST', 'PUT'] - ], - ]; - shuffle($routesConfiguration); - $this->router->setRoutesConfiguration($routesConfiguration); - $this->router->_call('createRoutesFromConfiguration'); - } - /** * @test */ public function resolveIteratesOverTheRegisteredRoutesAndReturnsTheResolvedUriConstraintsIfAny() { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); $routeValues = ['foo' => 'bar']; $resolveContext = new ResolveContext($this->mockBaseUri, $routeValues, false, '', RouteParameters::createEmpty()); - $route1 = $this->getMockBuilder(Route::class)->disableOriginalConstructor()->setMethods(['resolves'])->getMock(); $route1->expects(self::once())->method('resolves')->with($resolveContext)->willReturn(false); @@ -204,12 +119,12 @@ public function resolveIteratesOverTheRegisteredRoutesAndReturnsTheResolvedUriCo $route3 = $this->getMockBuilder(Route::class)->disableOriginalConstructor()->setMethods(['resolves'])->getMock(); $route3->expects(self::never())->method('resolves'); - $mockRoutes = [$route1, $route2, $route3]; + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->expects($this->once())->method("getRoutes")->willReturn(Routes::create($route1, $route2, $route3)); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); - $router->expects(self::once())->method('createRoutesFromConfiguration'); - $router->_set('routes', $mockRoutes); + $resolvedUri = $this->router->resolve($resolveContext); - $resolvedUri = $router->resolve($resolveContext); self::assertSame('/route2', $resolvedUri->getPath()); } @@ -219,10 +134,6 @@ public function resolveIteratesOverTheRegisteredRoutesAndReturnsTheResolvedUriCo public function resolveThrowsExceptionIfNoMatchingRouteWasFound() { $this->expectException(NoMatchingRouteException::class); - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); $route1 = $this->createMock(Route::class); $route1->expects(self::once())->method('resolves')->willReturn(false); @@ -230,11 +141,11 @@ public function resolveThrowsExceptionIfNoMatchingRouteWasFound() $route2 = $this->createMock(Route::class); $route2->expects(self::once())->method('resolves')->willReturn(false); - $mockRoutes = [$route1, $route2]; - - $router->_set('routes', $mockRoutes); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->expects($this->once())->method("getRoutes")->willReturn(Routes::create($route1, $route2)); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); - $router->resolve(new ResolveContext($this->mockBaseUri, [], false, '', RouteParameters::createEmpty())); + $this->router->resolve(new ResolveContext($this->mockBaseUri, [], false, '', RouteParameters::createEmpty())); } /** @@ -250,12 +161,6 @@ public function getLastResolvedRouteReturnsNullByDefault() */ public function resolveSetsLastResolvedRoute() { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - - $routeValues = ['some' => 'route values']; $resolveContext = new ResolveContext($this->mockBaseUri, $routeValues, false, '', RouteParameters::createEmpty()); $mockRoute1 = $this->getMockBuilder(Route::class)->getMock(); @@ -264,11 +169,13 @@ public function resolveSetsLastResolvedRoute() $mockRoute2->expects(self::once())->method('resolves')->with($resolveContext)->willReturn(true); $mockRoute2->method('getResolvedUriConstraints')->willReturn(UriConstraints::create()); - $router->_set('routes', [$mockRoute1, $mockRoute2]); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->expects($this->once())->method("getRoutes")->willReturn(Routes::create($mockRoute1, $mockRoute2)); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); - $router->resolve($resolveContext); + $this->router->resolve($resolveContext); - self::assertSame($mockRoute2, $router->getLastResolvedRoute()); + self::assertSame($mockRoute2, $this->router->getLastResolvedRoute()); } /** @@ -276,22 +183,20 @@ public function resolveSetsLastResolvedRoute() */ public function resolveReturnsCachedResolvedUriIfFoundInCache() { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - $routeValues = ['some' => 'route values']; $mockCachedResolvedUriConstraints = UriConstraints::create()->withPath('cached/path'); $resolveContext = new ResolveContext($this->mockBaseUri, $routeValues, false, '', RouteParameters::createEmpty()); - $mockRouterCachingService = $this->getMockBuilder(RouterCachingService::class)->getMock(); - $mockRouterCachingService->method('getCachedResolvedUriConstraints')->with($resolveContext)->willReturn($mockCachedResolvedUriConstraints); - $router->_set('routerCachingService', $mockRouterCachingService); + $mockRouterCachingService = $this->createMock(RouterCachingService::class); + $mockRouterCachingService->expects($this->once())->method('getCachedResolvedUriConstraints')->with($resolveContext)->willReturn($mockCachedResolvedUriConstraints); + $this->inject($this->router, 'routerCachingService', $mockRouterCachingService); - $router->expects(self::never())->method('createRoutesFromConfiguration'); - self::assertSame('/cached/path', (string)$router->resolve($resolveContext)); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->expects($this->never())->method("getRoutes"); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); + + self::assertSame('/cached/path', (string)$this->router->resolve($resolveContext)); } /** @@ -299,11 +204,6 @@ public function resolveReturnsCachedResolvedUriIfFoundInCache() */ public function resolveStoresResolvedUriPathInCacheIfNotFoundInCache() { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - $routeValues = ['some' => 'route values']; $mockResolvedUriConstraints = UriConstraints::create()->withPath('resolved/path'); @@ -315,10 +215,16 @@ public function resolveStoresResolvedUriPathInCacheIfNotFoundInCache() $mockRoute2->expects(self::once())->method('resolves')->with($resolveContext)->willReturn(true); $mockRoute2->expects(self::atLeastOnce())->method('getResolvedUriConstraints')->willReturn($mockResolvedUriConstraints); - $router->_set('routes', [$mockRoute1, $mockRoute2]); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->expects($this->once())->method("getRoutes")->willReturn(Routes::create($mockRoute1, $mockRoute2)); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); + + $mockRouterCachingService = $this->createMock(RouterCachingService::class); + $mockRouterCachingService->expects(self::once())->method('getCachedResolvedUriConstraints')->with($resolveContext)->willReturn(false); + $mockRouterCachingService->expects(self::once())->method('storeResolvedUriConstraints')->with($resolveContext, $mockResolvedUriConstraints, null, null); + $this->inject($this->router, 'routerCachingService', $mockRouterCachingService); - $this->mockRouterCachingService->expects(self::once())->method('storeResolvedUriConstraints')->with($resolveContext, $mockResolvedUriConstraints, null, null); - self::assertSame('/resolved/path', (string)$router->resolve($resolveContext)); + self::assertSame('/resolved/path', (string)$this->router->resolve($resolveContext)); } /** @@ -326,11 +232,6 @@ public function resolveStoresResolvedUriPathInCacheIfNotFoundInCache() */ public function resolveStoresResolvedUriPathInCacheIfNotFoundInCachWithTagsAndCacheLifetime() { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - $routeValues = ['some' => 'route values']; $mockResolvedUriConstraints = UriConstraints::create()->withPath('resolved/path'); @@ -345,10 +246,17 @@ public function resolveStoresResolvedUriPathInCacheIfNotFoundInCachWithTagsAndCa $mockRoute2->expects(self::atLeastOnce())->method('getResolvedUriConstraints')->willReturn($mockResolvedUriConstraints); $mockRoute2->expects(self::atLeastOnce())->method('getResolvedTags')->willReturn($routeTags); $mockRoute2->expects(self::atLeastOnce())->method('getResolvedLifetime')->willReturn($routeLifetime); - $router->_set('routes', [$mockRoute1, $mockRoute2]); - $this->mockRouterCachingService->expects(self::once())->method('storeResolvedUriConstraints')->with($resolveContext, $mockResolvedUriConstraints, $routeTags, $routeLifetime); - self::assertSame('/resolved/path', (string)$router->resolve($resolveContext)); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->expects($this->once())->method("getRoutes")->willReturn(Routes::create($mockRoute1, $mockRoute2)); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); + + $mockRouterCachingService = $this->createMock(RouterCachingService::class); + $mockRouterCachingService->expects($this->once())->method('getCachedResolvedUriConstraints')->with($resolveContext)->willReturn(false); + $mockRouterCachingService->expects($this->once())->method('storeResolvedUriConstraints')->with($resolveContext, $mockResolvedUriConstraints)->willReturn(false); + $this->inject($this->router, 'routerCachingService', $mockRouterCachingService); + + self::assertSame('/resolved/path', (string)$this->router->resolve($resolveContext)); } /** @@ -356,20 +264,14 @@ public function resolveStoresResolvedUriPathInCacheIfNotFoundInCachWithTagsAndCa */ public function routeReturnsCachedMatchResultsIfFoundInCache() { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'logger', $this->mockSystemLogger); - $routeContext = new RouteContext($this->mockHttpRequest, RouteParameters::createEmpty()); $cachedMatchResults = ['some' => 'cached results']; - $mockRouterCachingService = $this->getMockBuilder(RouterCachingService::class)->getMock(); - $mockRouterCachingService->expects(self::once())->method('getCachedMatchResults')->with($routeContext)->willReturn($cachedMatchResults); - $this->inject($router, 'routerCachingService', $mockRouterCachingService); - - $router->expects(self::never())->method('createRoutesFromConfiguration'); + $mockRouterCachingService = $this->createMock(RouterCachingService::class); + $mockRouterCachingService->method('getCachedMatchResults')->with($routeContext)->willReturn($cachedMatchResults); + $this->inject($this->router, 'routerCachingService', $mockRouterCachingService); - self::assertSame($cachedMatchResults, $router->route($routeContext)); + self::assertSame($cachedMatchResults, $this->router->route($routeContext)); } /** @@ -377,11 +279,6 @@ public function routeReturnsCachedMatchResultsIfFoundInCache() */ public function routeStoresMatchResultsInCacheIfNotFoundInCache() { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - $matchResults = ['some' => 'match results']; $routeContext = new RouteContext($this->mockHttpRequest, RouteParameters::createEmpty()); @@ -391,11 +288,16 @@ public function routeStoresMatchResultsInCacheIfNotFoundInCache() $mockRoute2->expects(self::once())->method('matches')->with($routeContext)->willReturn(true); $mockRoute2->expects(self::once())->method('getMatchResults')->willReturn($matchResults); - $router->_set('routes', [$mockRoute1, $mockRoute2]); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->expects(self::once())->method("getRoutes")->willReturn(Routes::create($mockRoute1, $mockRoute2)); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); - $this->mockRouterCachingService->expects(self::once())->method('storeMatchResults')->with($routeContext, $matchResults, null, null); + $mockRouterCachingService = $this->createMock(RouterCachingService::class); + $mockRouterCachingService->expects(self::once())->method('getCachedMatchResults')->with($routeContext)->willReturn(false); + $mockRouterCachingService->expects(self::once())->method('storeMatchResults')->with($routeContext, $matchResults, null, null); + $this->inject($this->router, 'routerCachingService', $mockRouterCachingService); - self::assertSame($matchResults, $router->route($routeContext)); + self::assertSame($matchResults, $this->router->route($routeContext)); } /** @@ -403,11 +305,6 @@ public function routeStoresMatchResultsInCacheIfNotFoundInCache() */ public function routeStoresMatchResultsInCacheIfNotFoundInCacheWithTagsAndCacheLifetime() { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - $matchResults = ['some' => 'match results']; $routeContext = new RouteContext($this->mockHttpRequest, RouteParameters::createEmpty()); $routeTags = RouteTags::createFromArray(['foo', 'bar']); @@ -421,11 +318,16 @@ public function routeStoresMatchResultsInCacheIfNotFoundInCacheWithTagsAndCacheL $mockRoute2->expects(self::once())->method('getMatchedTags')->willReturn($routeTags); $mockRoute2->expects(self::once())->method('getMatchedLifetime')->willReturn($routeLifetime); - $router->_set('routes', [$mockRoute1, $mockRoute2]); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->expects(self::once())->method("getRoutes")->willReturn(Routes::create($mockRoute1, $mockRoute2)); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); - $this->mockRouterCachingService->expects(self::once())->method('storeMatchResults')->with($routeContext, $matchResults, $routeTags, $routeLifetime); + $mockRouterCachingService = $this->createMock(RouterCachingService::class); + $mockRouterCachingService->expects(self::once())->method('getCachedMatchResults')->with($routeContext)->willReturn(false); + $mockRouterCachingService->expects(self::once())->method('storeMatchResults')->with($routeContext, $matchResults, $routeTags, $routeLifetime); + $this->inject($this->router, 'routerCachingService', $mockRouterCachingService); - self::assertSame($matchResults, $router->route($routeContext)); + self::assertSame($matchResults, $this->router->route($routeContext)); } /** @@ -441,11 +343,6 @@ public function getLastMatchedRouteReturnsNullByDefault() */ public function routeSetsLastMatchedRoute() { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['createRoutesFromConfiguration']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - $routeContext = new RouteContext($this->mockHttpRequest, RouteParameters::createEmpty()); $mockRoute1 = $this->getMockBuilder(Route::class)->getMock(); @@ -454,85 +351,12 @@ public function routeSetsLastMatchedRoute() $mockRoute2->expects(self::once())->method('matches')->with($routeContext)->willReturn(true); $mockRoute2->expects(self::once())->method('getMatchResults')->willReturn([]); - $router->_set('routes', [$mockRoute1, $mockRoute2]); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->expects($this->once())->method("getRoutes")->willReturn(Routes::create($mockRoute1, $mockRoute2)); + $this->inject($this->router, 'routesProvider', $mockRoutesProvider); - $router->route($routeContext); + $this->router->route($routeContext); - self::assertSame($mockRoute2, $router->getLastMatchedRoute()); - } - - /** - * @test - */ - public function routeLoadsRoutesConfigurationFromConfigurationManagerIfNotSetExplicitly() - { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['dummy']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - - $uri = new Uri('http://localhost/'); - $this->mockHttpRequest->expects(self::any())->method('getUri')->willReturn($uri); - - $routesConfiguration = [ - [ - 'uriPattern' => 'some/uri/pattern', - ], - [ - 'uriPattern' => 'some/other/uri/pattern', - ], - ]; - - /** @var ConfigurationManager|\PHPUnit\Framework\MockObject\MockObject $mockConfigurationManager */ - $mockConfigurationManager = $this->getMockBuilder(ConfigurationManager::class)->disableOriginalConstructor()->getMock(); - $mockConfigurationManager->expects(self::once())->method('getConfiguration')->with(ConfigurationManager::CONFIGURATION_TYPE_ROUTES)->willReturn($routesConfiguration); - $this->inject($router, 'configurationManager', $mockConfigurationManager); - - try { - $router->route(new RouteContext($this->mockHttpRequest, RouteParameters::createEmpty())); - } catch (NoMatchingRouteException $exception) { - } - - $routes = $router->getRoutes(); - $firstRoute = reset($routes); - self::assertSame('some/uri/pattern', $firstRoute->getUriPattern()); - } - - /** - * @test - */ - public function routeDoesNotLoadRoutesConfigurationFromConfigurationManagerIfItsSetExplicitly() - { - /** @var Router|\PHPUnit\Framework\MockObject\MockObject $router */ - $router = $this->getAccessibleMock(Router::class, ['dummy']); - $this->inject($router, 'routerCachingService', $this->mockRouterCachingService); - $this->inject($router, 'logger', $this->mockSystemLogger); - - $uri = new Uri('http://localhost/'); - $this->mockHttpRequest->expects(self::any())->method('getUri')->willReturn($uri); - - $routesConfiguration = [ - [ - 'uriPattern' => 'some/uri/pattern', - ], - [ - 'uriPattern' => 'some/other/uri/pattern', - ], - ]; - - /** @var ConfigurationManager|\PHPUnit\Framework\MockObject\MockObject $mockConfigurationManager */ - $mockConfigurationManager = $this->getMockBuilder(ConfigurationManager::class)->disableOriginalConstructor()->getMock(); - $mockConfigurationManager->expects(self::never())->method('getConfiguration'); - $this->inject($router, 'configurationManager', $mockConfigurationManager); - - $router->setRoutesConfiguration($routesConfiguration); - try { - $router->route(new RouteContext($this->mockHttpRequest, RouteParameters::createEmpty())); - } catch (NoMatchingRouteException $exception) { - } - - $routes = $router->getRoutes(); - $firstRoute = reset($routes); - self::assertSame('some/uri/pattern', $firstRoute->getUriPattern()); + self::assertSame($mockRoute2, $this->router->getLastMatchedRoute()); } } diff --git a/Neos.Flow/Tests/Unit/Mvc/Routing/RoutesTest.php b/Neos.Flow/Tests/Unit/Mvc/Routing/RoutesTest.php new file mode 100644 index 0000000000..86bc766926 --- /dev/null +++ b/Neos.Flow/Tests/Unit/Mvc/Routing/RoutesTest.php @@ -0,0 +1,166 @@ +assertSame([], iterator_to_array($routes)); + } + + /** + * @test + */ + public function fromConfigurationWorksAsExpected(): void + { + $route1 = new Route(); + $route1->setName('Route 1'); + $route1->setUriPattern('route1/{@package}/{@controller}/{@action}(.{@format})'); + $route1->setDefaults(['@format' => 'html']); + + $route2 = new Route(); + $route2->setName('Route 2'); + $route2->setDefaults(['@format' => 'html']); + $route2->setUriPattern('route2/{@package}/{@controller}/{@action}(.{@format})'); + $route2->setLowerCase(false); + $route2->setAppendExceedingArguments(true); + $route2->setRoutePartsConfiguration( + [ + '@controller' => [ + 'handler' => 'MyRoutePartHandler' + ] + ] + ); + $route2->setHttpMethods(['PUT']); + $route2->setCacheTags(Routing\Dto\RouteTags::createFromArray(['foo', 'bar'])); + $route2->setCacheLifetime(Routing\Dto\RouteLifetime::fromInt(10000)); + + $configuration = [ + [ + 'name' => 'Route 1', + 'uriPattern' => 'route1/{@package}/{@controller}/{@action}(.{@format})', + 'defaults' => ['@format' => 'html'] + ], + [ + 'name' => 'Route 2', + 'defaults' => ['@format' => 'html'], + 'uriPattern' => 'route2/{@package}/{@controller}/{@action}(.{@format})', + 'toLowerCase' => false, + 'appendExceedingArguments' => true, + 'routeParts' => [ + '@controller' => [ + 'handler' => 'MyRoutePartHandler' + ] + ], + 'httpMethods' => ['PUT'], + 'cache' => [ + 'lifetime' => 10000, + 'tags' => ['foo', 'bar'] + ], + ], + ]; + + $routes = Routes::fromConfiguration($configuration); + + $this->assertEquals( + [$route1, $route2], + iterator_to_array($routes) + ); + } + + /** + * @test + */ + public function mergeRoutes(): void + { + $route1 = new Route(); + $route1->setName("Route 1"); + + $route2 = new Route(); + $route2->setName("Route 2"); + + $routes = Routes::create($route1)->merge(Routes::create($route2)); + + $this->assertSame([$route1, $route2], iterator_to_array($routes)); + } + + /** + * @test + */ + public function createRoutesFromConfigurationThrowsExceptionIfOnlySomeRoutesWithTheSameUriPatternHaveHttpMethodConstraints() + { + // multiple routes with the uriPattern and "httpMethods" option + $this->expectException(InvalidRouteSetupException::class); + $routesConfiguration = [ + [ + 'uriPattern' => 'somePattern' + ], + [ + 'uriPattern' => 'somePattern', + 'httpMethods' => ['POST', 'PUT'] + ], + ]; + shuffle($routesConfiguration); + Routes::fromConfiguration($routesConfiguration); + } + + /** + * @test + */ + public function createRoutesFromConfigurationParsesTheGivenConfigurationAndBuildsRouteObjectsFromIt() + { + $routesConfiguration = []; + $routesConfiguration['route1']['uriPattern'] = 'number1'; + $routesConfiguration['route2']['uriPattern'] = 'number2'; + $routesConfiguration['route3'] = [ + 'name' => 'route3', + 'defaults' => ['foodefault'], + 'routeParts' => ['fooroutepart'], + 'uriPattern' => 'number3', + 'toLowerCase' => false, + 'appendExceedingArguments' => true, + 'httpMethods' => ['POST', 'PUT'] + ]; + + /** @var Route[] $createdRoutes */ + $createdRoutes = iterator_to_array(Routes::fromConfiguration($routesConfiguration)); + + self::assertEquals('number1', $createdRoutes[0]->getUriPattern()); + self::assertTrue($createdRoutes[0]->isLowerCase()); + self::assertFalse($createdRoutes[0]->getAppendExceedingArguments()); + self::assertEquals('number2', $createdRoutes[1]->getUriPattern()); + self::assertFalse($createdRoutes[1]->hasHttpMethodConstraints()); + self::assertEquals([], $createdRoutes[1]->getHttpMethods()); + self::assertEquals('route3', $createdRoutes[2]->getName()); + self::assertEquals(['foodefault'], $createdRoutes[2]->getDefaults()); + self::assertEquals(['fooroutepart'], $createdRoutes[2]->getRoutePartsConfiguration()); + self::assertEquals('number3', $createdRoutes[2]->getUriPattern()); + self::assertFalse($createdRoutes[2]->isLowerCase()); + self::assertTrue($createdRoutes[2]->getAppendExceedingArguments()); + self::assertTrue($createdRoutes[2]->hasHttpMethodConstraints()); + self::assertEquals(['POST', 'PUT'], $createdRoutes[2]->getHttpMethods()); + } +} diff --git a/Neos.Flow/Tests/Unit/Mvc/Routing/RoutingMiddlewareTest.php b/Neos.Flow/Tests/Unit/Mvc/Routing/RoutingMiddlewareTest.php index e7f8a58e3e..273cd38085 100644 --- a/Neos.Flow/Tests/Unit/Mvc/Routing/RoutingMiddlewareTest.php +++ b/Neos.Flow/Tests/Unit/Mvc/Routing/RoutingMiddlewareTest.php @@ -12,11 +12,12 @@ */ use GuzzleHttp\Psr7\Response; -use Neos\Flow\Configuration\ConfigurationManager; use Neos\Flow\Http\ServerRequestAttributes; use Neos\Flow\Mvc\Routing\Dto\RouteParameters; use Neos\Flow\Mvc\Routing\Dto\RouteContext; use Neos\Flow\Mvc\Routing\Router; +use Neos\Flow\Mvc\Routing\Routes; +use Neos\Flow\Mvc\Routing\RoutesProviderInterface; use Neos\Flow\Mvc\Routing\RoutingMiddleware; use Neos\Flow\Tests\UnitTestCase; use Psr\Http\Message\ServerRequestInterface; @@ -38,11 +39,6 @@ class RoutingMiddlewareTest extends UnitTestCase */ protected $mockRouter; - /** - * @var ConfigurationManager|\PHPUnit\Framework\MockObject\MockObject - */ - protected $mockConfigurationManager; - /** * @var RequestHandlerInterface|\PHPUnit\Framework\MockObject\MockObject */ @@ -66,9 +62,10 @@ protected function setUp(): void { $this->routingMiddleware = new RoutingMiddleware(); - $this->mockRouter = $this->getMockBuilder(Router::class)->getMock(); - $this->mockConfigurationManager = $this->getMockBuilder(ConfigurationManager::class)->disableOriginalConstructor()->getMock(); - $this->inject($this->mockRouter, 'configurationManager', $this->mockConfigurationManager); + $this->mockRouter = $this->createMock(Router::class); + $mockRoutesProvider = $this->createMock(RoutesProviderInterface::class); + $mockRoutesProvider->method('getRoutes')->willReturn(Routes::empty()); + $this->inject($this->mockRouter, 'routesProvider', $mockRoutesProvider); $this->inject($this->routingMiddleware, 'router', $this->mockRouter); diff --git a/Neos.FluidAdaptor/Tests/Functional/Core/WidgetTest.php b/Neos.FluidAdaptor/Tests/Functional/Core/WidgetTest.php index 93dcbc4813..e6367dd320 100644 --- a/Neos.FluidAdaptor/Tests/Functional/Core/WidgetTest.php +++ b/Neos.FluidAdaptor/Tests/Functional/Core/WidgetTest.php @@ -11,7 +11,6 @@ * source code. */ -use Neos\Flow\Mvc\Routing\Route; use Neos\Flow\Tests\FunctionalTestCase; /** @@ -26,17 +25,17 @@ protected function setUp(): void { parent::setUp(); - $route = new Route(); - $route->setName('WidgetTest'); - $route->setUriPattern('test/widget/{@controller}(/{@action})'); - $route->setDefaults([ - '@package' => 'Neos.FluidAdaptor', - '@subpackage' => 'Tests\Functional\Core\Fixtures', - '@action' => 'index', - '@format' => 'html' - ]); - $route->setAppendExceedingArguments(true); - $this->router->addRoute($route); + $this->registerRoute( + 'WidgetTest', + 'test/widget/{@controller}(/{@action})', + [ + '@package' => 'Neos.FluidAdaptor', + '@subpackage' => 'Tests\Functional\Core\Fixtures', + '@action' => 'index', + '@format' => 'html' + ], + true + ); } /** diff --git a/Neos.FluidAdaptor/Tests/Functional/Form/FormObjectsTest.php b/Neos.FluidAdaptor/Tests/Functional/Form/FormObjectsTest.php index 518f646d26..48eb7ed61f 100644 --- a/Neos.FluidAdaptor/Tests/Functional/Form/FormObjectsTest.php +++ b/Neos.FluidAdaptor/Tests/Functional/Form/FormObjectsTest.php @@ -11,7 +11,6 @@ * source code. */ -use Neos\Flow\Mvc\Routing\Route; /** * Testcase for Standalone View @@ -37,17 +36,18 @@ protected function setUp(): void { parent::setUp(); - $route = new Route(); - $route->setUriPattern('test/fluid/formobjects(/{@action})'); - $route->setDefaults([ - '@package' => 'Neos.FluidAdaptor', - '@subpackage' => 'Tests\Functional\Form\Fixtures', - '@controller' => 'Form', - '@action' => 'index', - '@format' => 'html' - ]); - $route->setAppendExceedingArguments(true); - $this->router->addRoute($route); + $this->registerRoute( + 'Form Test Route', + 'test/fluid/formobjects(/{@action})', + [ + '@package' => 'Neos.FluidAdaptor', + '@subpackage' => 'Tests\Functional\Form\Fixtures', + '@controller' => 'Form', + '@action' => 'index', + '@format' => 'html' + ], + true + ); } /**