diff --git a/composer.json b/composer.json index 73d4d1b1..31d824c9 100755 --- a/composer.json +++ b/composer.json @@ -26,17 +26,18 @@ "illuminate/encryption": "^13", "illuminate/events": "^13", "illuminate/filesystem": "^13", - "illuminate/hashing": "^13", - "illuminate/http": "^13", + "illuminate/hashing": "^13", + "illuminate/http": "^13", "illuminate/log": "^13", "illuminate/macroable": "^13", "illuminate/pagination": "^13", "illuminate/pipeline": "^13", "illuminate/redis": "^13", "illuminate/reflection": "^13", + "illuminate/routing": "^13", "illuminate/session": "^13", - "illuminate/support": "^13", - "illuminate/translation": "^13", + "illuminate/support": "^13", + "illuminate/translation": "^13", "illuminate/validation": "^13", "illuminate/view": "^13", "ircmaxell/password-compat": "~1.0", @@ -69,7 +70,6 @@ "illuminate/html": "self.version", "illuminate/mail": "self.version", "illuminate/queue": "self.version", - "illuminate/routing": "self.version", "illuminate/workbench": "self.version" }, "require-dev": { diff --git a/src/Illuminate/CachedRouting/Route.php b/src/Illuminate/CachedRouting/Route.php deleted file mode 100644 index c0870cb4..00000000 --- a/src/Illuminate/CachedRouting/Route.php +++ /dev/null @@ -1,105 +0,0 @@ -routingToController($this->action) === true) { - $this->action = $app['router']->makeControllerActionClosure($this->action); - } - - return parent::run(); - } - - /** - * Determines whether routes should be compiled. Caches the value at a class - * level. - * - * @return bool - */ - protected function shouldCompile() - { - if (static::$shouldCompileRoute === null) { - // If the compiled variable exists, we should compile. - static::$shouldCompileRoute = array_key_exists('compiled', get_object_vars($this)); - } - - return static::$shouldCompileRoute; - } - - /** - * Compile the route into a Symfony CompiledRoute instance. - */ - #[\Override] - protected function compileRoute() - { - if ($this->shouldCompile() === true && $this->compiled === null) { - parent::compileRoute(); - } - } - - /** - * Prepare to go to sleep. Compiles the route so that doesn't have to happen - * on every subsequent request. - * - * @return array - */ - public function __sleep() - { - $this->compileRoute(); - - return array_keys(get_object_vars($this)); - } -} diff --git a/src/Illuminate/CachedRouting/RouteCollection.php b/src/Illuminate/CachedRouting/RouteCollection.php deleted file mode 100644 index 2f6f4fcd..00000000 --- a/src/Illuminate/CachedRouting/RouteCollection.php +++ /dev/null @@ -1,174 +0,0 @@ -backup; - } - - /** - * Save the current collection of routes to the backup to start with an empty - * collection to cache. - */ - public function saveRouteCollection() - { - $this->backup = $this->getCacheableRouteContents(); - - foreach (array_keys($this->backup) as $k) { - $this->$k = array(); - } - } - - /** - * Restore the backed up routes. - */ - public function restoreRouteCollection() - { - $this->restoreRoutes($this->getBackup(), true); - } - - /** - * Get the routes in a form that can be saved to the cache. - * - * @return string - */ - public function getCacheableRoutes() - { - return serialize($this->getCacheableRouteContents()); - } - - /** - * Get the data that should be sent to the cache. - * - * @return array - */ - public function getCacheableRouteContents() - { - return array_except(get_object_vars($this), array('backup')); - } - - /** - * Restore a set of cached routes into this collection. - * - * @param string $cache - */ - public function restoreRouteCache($cache) - { - $routes = unserialize($cache); - - $this->restoreRoutes($routes); - } - - /** - * Add a set of routes back into this collection. - * - * @param bool $prepend - * @param array $routes - */ - protected function restoreRoutes($routes, $prepend = false) - { - foreach ($routes as $k => $v) { - if ($k === 'routes') { - $this->$k = $prepend === false ? - $this->mergeGroupedRoutes($this->$k, $v) : - $this->mergeGroupedRoutes($v, $this->$k); - } else { - $this->$k = $prepend === false ? - $this->mergeRoutes($this->$k, $v) : - $this->mergeRoutes($v, $this->$k); - } - } - } - - /** - * Merge two array, each containing routes grouped by method. - * - * @param array - * @param array - * @return array - */ - public function mergeGroupedRoutes(array $r1, array $r2) - { - $methods = array('GET', 'POST', 'HEAD', 'PATH', 'PUT', 'DELETE'); - foreach ($methods as $method) { - if (isset($r2[$method]) === false) { - continue; - } - if (isset($r1[$method]) === false) { - $r1[$method] = array(); - } - - $r1[$method] = $this->mergeRoutes($r1[$method], $r2[$method]); - } - - return $r1; - } - - /** - * Merge two arrays, each containing routes. - * - * @param array - * @param array - * @return array - */ - public function mergeRoutes(array $r1, array $r2) - { - foreach ($r2 as $uri => $route) { - $r1[$uri] = $route; - } - - return $r1; - } -} diff --git a/src/Illuminate/CachedRouting/Router.php b/src/Illuminate/CachedRouting/Router.php deleted file mode 100644 index 580e26a5..00000000 --- a/src/Illuminate/CachedRouting/Router.php +++ /dev/null @@ -1,295 +0,0 @@ -routes = new RouteCollection; - } - - /** - * Indicate that the routes that are defined in the given callback - * should be cached. - * - * @param string $filename - * @param Closure $callback - * @param int $cacheMinutes - * @return string|null - */ - public function cache($filename, Closure $callback, $cacheMinutes = 1440): ?string - { - $cacheKey = null; - if ($cacheMinutes > 0) { - $cacheKey = $this->getCacheKey($filename); - } - - // No cache key — either caching is disabled, or the route file cannot be - // stat'd (e.g. removed in a deploy while a worker still serves its stale - // opcode). Define the routes directly and skip caching; boot must never - // break, and a null key must never reach the cache store (it would - // collide across files under an empty key). - if ($cacheKey === null) { - call_user_func($callback, $this); - - return null; - } - - $cacher = $this->getRouteCacher(); - - // Route caching is best-effort: an unreadable/corrupt entry or an - // unwritable cache directory (e.g. permissions, or a torn write from - // concurrent boots after a deploy) must never break application boot. - // On any cache I/O failure we fall back to defining the routes directly. - $cache = null; - try { - $cache = $cacher->get($cacheKey); - } catch (\Throwable $e) { - // Treat an unreadable cache as a miss and rebuild below. - } - - if ($cache !== null) { - $this->routes->restoreRouteCache($cache); - } else { - // Back up current RouteCollection contents. - $this->routes->saveRouteCollection(); - - // Call closure to define routes that should be cached. - call_user_func($callback, $this); - - // Persist the routes, ignoring failures so a broken cache store - // never propagates out of boot (routes stay defined in memory). - try { - $cacher->put($cacheKey, $this->routes->getCacheableRoutes(), Carbon::now()->addMinutes($cacheMinutes)); - } catch (\Throwable $e) { - // Best-effort cache; a write failure is non-fatal. - } - - // And restore the routes that shouldn't be cached. - $this->routes->restoreRouteCollection(); - } - - return $cacheKey; - } - - /** - * Clear the cached data for the given routes file. - * - * @param string $filename - */ - public function clearCache($filename) - { - $cacheKey = $this->getCacheKey($filename); - - if ($cacheKey !== null) { - $this->getRouteCacher()->forget($cacheKey); - } - } - - /** - * Get the cache store used to persist compiled routes. - * - * Always the local "file" store so that booting the application (web or - * artisan) never depends on a networked cache such as Redis. - * - * @return \Illuminate\Cache\Repository - */ - protected function getRouteCacher() - { - return $this->container['cache']->driver('file'); - } - - /** - * Get the key under which the routes cache for the given file should be stored. - * - * @param string $filename - * @return string|null - */ - protected function getCacheKey($filename) - { - // Building the key must never break boot. filemtime() (and md5() on a - // null path) raise warnings the app's error handler escalates to a - // fatal — e.g. a route file removed in a deploy while a worker still - // serves its stale opcode. Treat any failure as "not cacheable". - try { - return 'routes.cache.'.$this->cacheVersion.'.'.md5($filename).filemtime($filename); - } catch (\Throwable $e) { - return null; - } - } - - /** - * Determine if the action is routing to a controller. - * - * @param array $action - * @return bool - */ - #[\Override] - public function routingToController($action) - { - return parent::routingToController($action); - } - - /** - * Add a controller based route action to the action array. - * - * @param array|string $action - * @return array - */ - #[\Override] - protected function getControllerAction($action) - { - if (is_string($action) === true) { - $action = array('uses' => $action); - } - - // Here we'll get an instance of this controller dispatcher and hand it off to - // the Closure so it will be used to resolve the class instances out of our - // IoC container instance and call the appropriate methods on the class. - if (count($this->groupStack) > 0) { - $action['uses'] = $this->prependGroupUses($action['uses']); - } - - // Here we'll get an instance of this controller dispatcher and hand it off to - // the Closure so it will be used to resolve the class instances out of our - // IoC container instance and call the appropriate methods on the class. - $action['controller'] = $action['uses']; - - $closure = $action['uses']; - - return array_set($action, 'uses', $closure); - } - - /** - * Replace the string action in the given array with a Closure to call. - * - * @param array $action - * @return array - */ - public function makeControllerActionClosure(array $action) - { - $closure = $this->getClassClosure($action['uses']); - - return array_set($action, 'uses', $closure); - } - - /** - * Create a new route instance. - * - * @param array|string $methods - * @param string $uri - * @param mixed $action - * @return \Illuminate\Routing\Route - */ - #[\Override] - protected function createRoute($methods, $uri, $action) - { - // If the route is routing to a controller we will parse the route action into - // an acceptable array format before registering it and creating this route - // instance itself. We need to build the Closure that will call this out. - if ($this->routingToController($action) === true) { - $action = $this->getControllerAction($action); - } - - $route = $this->newRoute( - $methods, - $uri = $this->prefix($uri), - $action - ); - - // If we have groups that need to be merged, we will merge them now after this - // route has already been created and is ready to go. After we're done with - // the merge we will be ready to return the route back out to the caller. - if (empty($this->groupStack) === false) { - $this->mergeController($route); - } - - $this->addWhereClausesToRoute($route); - - return $route; - } - - /** - * Create a new Route object. - * - * @param array|string $methods - * @param string $uri - * @param mixed $action - * @return \Illuminate\Routing\Route - */ - #[\Override] - protected function newRoute($methods, $uri, $action) - { - return new Route($methods, $uri, $action); - } - - /** - * Add the necessary where clauses to the route based on its initial registration. - * - * @param \Illuminate\Routing\Route $route - * @return \Illuminate\Routing\Route - */ - #[\Override] - protected function addWhereClausesToRoute($route) - { - $route->where( - array_merge($this->patterns, array_get($route->getAction(), 'where', array())) - ); - return $route; - } -} diff --git a/src/Illuminate/CachedRouting/RoutingServiceProvider.php b/src/Illuminate/CachedRouting/RoutingServiceProvider.php deleted file mode 100644 index 472777e6..00000000 --- a/src/Illuminate/CachedRouting/RoutingServiceProvider.php +++ /dev/null @@ -1,74 +0,0 @@ -registerRouter(); - } - - /** - * Register the router instance. - * - * @return void - */ - protected function registerRouter() - { - $this->app->singleton('router', - function ($app) { - $router = new Router($app['events'], $app); - - // If the current application environment is "testing", we will disable the - // routing filters, since they can be tested independently of the routes - // and just get in the way of our typical controller testing concerns. - if ($app['env'] === 'testing') { - $router->disableFilters(); - } - - return $router; - } - ); - } -} diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 7b92b2b1..0d68fdad 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -61,6 +61,18 @@ class Application extends Container implements HttpKernelInterface, TerminableIn */ protected $finishCallbacks = array(); + /** + * ponytail: global before/after callbacks (App::before/App::after). L4.2 stored + * these as router.before/after global filters; v13's Router has no global-filter + * concept, so the app runs them itself around the route dispatch (see dispatch()). + * Remove at task 4.5 foundation swap if global middleware replaces them. + * + * @var array + */ + protected $beforeCallbacks = array(); + + protected $afterCallbacks = array(); + /** * ponytail: v13 terminating-callback shim (v13 ServiceProviders register * these; fork Foundation predates the API). Remove at task 4.5 foundation swap. @@ -627,7 +639,7 @@ public function extend($abstract, Closure $closure): void */ public function before($callback) { - return $this['router']->before($callback); + $this->beforeCallbacks[] = $callback; } /** @@ -638,7 +650,7 @@ public function before($callback) */ public function after($callback) { - return $this['router']->after($callback); + $this->afterCallbacks[] = $callback; } /** @@ -929,7 +941,23 @@ public function dispatch(Request $request) $this['session']->start(); } - return $this['router']->dispatch($this->prepareRequest($request)); + $request = $this->prepareRequest($request); + + foreach ($this->beforeCallbacks as $callback) + { + $response = call_user_func($callback, $request); + + if ( ! is_null($response)) return $this->prepareResponse($response, $request); + } + + $response = $this['router']->dispatch($request); + + foreach ($this->afterCallbacks as $callback) + { + call_user_func($callback, $request, $response); + } + + return $response; } /** diff --git a/tests/CachedRouting/RoutingIntegrationTest.php b/tests/CachedRouting/RoutingIntegrationTest.php deleted file mode 100755 index ee015226..00000000 --- a/tests/CachedRouting/RoutingIntegrationTest.php +++ /dev/null @@ -1,450 +0,0 @@ -app === null) { - $this->refreshApplication(); - } - } - - protected function tearDown(): void - { - if (self::$cachePath !== null) { - (new Filesystem)->deleteDirectory(self::$cachePath); - } - } - - /** - * Refresh the application instance. - */ - protected function refreshApplication(): void - { - $this->app = $this->createApplication(); - - Facade::setFacadeApplication($this->app); - - $this->app['env'] = 'testing'; - - $this->app['path.storage'] = __DIR__; - - $this->app['config'] = new Repository(); - - $this->app['files'] = new Filesystem; - $this->app['cache'] = new CacheManager($this->app); - self::$cachePath = sys_get_temp_dir() . '/l42x-route-cache-' . uniqid(); - $this->app['config']['cache.default'] = 'file'; - $this->app['config']['cache.stores.file'] = ['driver' => 'file', 'path' => self::$cachePath]; - - $this->app['session'] = new SessionManager($this->app); - $this->app['config']['session.driver'] = 'array'; - $this->app['session.store'] = $this->app['session']->driver(); - - $this->app->boot(); - } - - /** - * Creates the application. - */ - protected function createApplication(): Application - { - return new Application(); - } - - /** - * Create a router. - */ - protected function getRouter(): Router - { - return new Router($this->app['events'], $this->app); - } - - /** - * Create a new HttpKernel client instance. - */ - protected function createClient(array $server = array()): HttpKernelBrowser - { - return new HttpKernelBrowser($this->app, $server); - } - - public function testCacheRoutes(): void - { - $router = $this->getRouter(); - - $key = $router->cache(__FILE__, function () use ($router) { - $router->get('/', 'HomeController@actionIndex'); - }); - - static::assertTrue($this->app->cache->has($key), 'Routes must be in cache'); - static::assertEquals(1, $router->getRoutes()->count(), 'Routes must be in collection'); - - $cachedRoutes = unserialize($this->app->cache->get($key)); - static::assertArrayHasKey('routes', $cachedRoutes); - static::assertArrayHasKey('GET', $cachedRoutes['routes']); - static::assertCount(1, $cachedRoutes['routes']['GET']); - - // Next request should not call the callback. - $router = $this->getRouter(); - $router->cache(__FILE__, function () use ($router) { - throw new RuntimeException('This should not be called'); - }); - static::assertEquals(1, $router->getRoutes()->count(), 'Routes must be obtained from cache'); - } - - public function testCacheRoutesNoTtl(): void - { - $router = $this->getRouter(); - - $key = $router->cache(__FILE__, function () use ($router) { - $router->get('/', 'HomeController@actionIndex'); - }, 0); - - static::assertNull($key, 'Cache key should be null with TTL=0'); - static::assertEquals(1, $router->getRoutes()->count(), 'Route must be added to router'); - } - - public function testAllMethodsWorks(): void - { - $methods = ['get', 'post', 'put', 'patch', 'delete']; - - $router = $this->getRouter(); - - $key = $router->cache(__FILE__, function () use ($router, $methods) { - foreach ($methods as $method) { - $router->$method('/', 'HomeController@action' . ucfirst($method)); - } - }); - - static::assertTrue($this->app->cache->has($key), 'Routes must be in cache'); - static::assertEquals(count($methods), $router->getRoutes()->count(), 'Routes must be in collection'); - - $cachedRoutes = unserialize($this->app->cache->get($key)); - static::assertArrayHasKey('routes', $cachedRoutes); - - foreach ($methods as $method) { - static::assertArrayHasKey(strtoupper($method), $cachedRoutes['routes']); - static::assertCount(1, $cachedRoutes['routes'][strtoupper($method)]); - } - - // Next request should not call the callback. - $router = $this->getRouter(); - $router->cache(__FILE__, function () use ($router) { - throw new RuntimeException('This should not be called'); - }); - static::assertEquals(count($methods), $router->getRoutes()->count(), 'Routes must be obtained from cache'); - } - - public function testControllerRouting(): void - { - $router = $this->getRouter(); - - $controllerName = str_shuffle('abcdefghijklmnopqrstuvwxyz'); - - // Create a controller class. - eval('class ' . $controllerName . ' extends Illuminate\Routing\Controller { public function getHomePage() {} }'); - - $key = $router->cache(__FILE__, function () use ($router, $controllerName) { - $router->controller('/', $controllerName); - }); - - static::assertTrue($this->app->cache->has($key), 'Routes must be in cache'); - // 2 because controller adds missingMethod - static::assertEquals(2, $router->getRoutes()->count(), 'Routes must be in collection'); - - // Next request should not call the callback. - $router = $this->getRouter(); - $router->cache(__FILE__, function () use ($router) { - throw new Exception('This should not be called'); - }); - static::assertEquals(2, $router->getRoutes()->count(), 'Routes must be obtained from cache'); - } - - public function testCanDispatchRequest(): void - { - // Create a controller class. - $controllerName = str_shuffle('abcdefghijklmnopqrstuvwxyz'); - eval('class ' . $controllerName . ' extends Illuminate\Routing\Controller { - public function getIndex() { - return Illuminate\Support\Facades\Response::make(1); - } - }'); - - // First, define a route. - $router = $this->getRouter(); - $router->cache(__FILE__, function () use ($router, $controllerName) { - $router->get('/', $controllerName . '@getIndex'); - }); - - // Create a new router, set it on the app, and simulate a request. - $this->app['router'] = $this->getRouter(); - $this->app['router']->cache(__FILE__, function () use ($router) { - throw new RuntimeException('This should not be called'); - }); - - $client = $this->createClient(); - $client->request('get', '/'); - - $response = $client->getResponse(); - static::assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); - static::assertEquals(1, $response->getContent()); - } - - public function testCanRouteToClosure(): void - { - // Create a new router, set it on the app, and simulate a request. - $this->app['router'] = $this->getRouter(); - $this->app['router']->get('/', fn() => 1); - - $client = $this->createClient(); - $client->request('get', '/'); - - $response = $client->getResponse(); - static::assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); - static::assertEquals(1, $response->getContent()); - } - - public function testCanGroupRoutes(): void - { - $router = $this->getRouter(); - - $controllerName = str_shuffle('abcdefghijklmnopqrstuvwxyz'); - - // Create a controller class. - eval('class ' . $controllerName . ' extends Illuminate\Routing\Controller { - public function getHomePage() { - return Illuminate\Support\Facades\Response::make(1); - } - }'); - - $router->cache(__FILE__, function () use ($controllerName, $router) { - $router->group( - ['prefix' => 'grouped'], - function () use ($router, $controllerName) { - $router->get('/', $controllerName . '@getHomePage'); - $router->get('/dashboard', $controllerName . '@getHomePage'); - } - ); - }); - - // 2 routes originating from group closure - static::assertEquals(2, $router->getRoutes()->count(), 'Routes must be in collection'); - - // Create a new router, set it on the app, and simulate a request. - $this->app['router'] = $this->getRouter(); - $this->app['router']->cache(__FILE__, callback: function () use ($router) { - throw new RuntimeException('This should not be called'); - }); - - $client = $this->createClient(); - $client->request('GET', '/grouped/dashboard'); - - $response = $client->getResponse(); - static::assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); - static::assertEquals(1, $response->getContent()); - } - - public function testCanChainWheres(): void - { - $this->expectException(NotFoundHttpException::class); - - $this->app['router'] = $this->getRouter(); - $this->app['router']->get('/{foo}/{bar}', fn() => 'baz') - ->where('foo', '\w+') - ->where('bar', '\d+'); - - // /herp/derp should not match above route. - $client = $this->createClient(); - $client->catchExceptions(false); - $client->request('GET', '/herp/derp'); - } - - public function testWheresRetainedInCache(): void - { - $this->expectException(NotFoundHttpException::class); - - // Create a controller class. - $controllerName = str_shuffle('abcdefghijklmnopqrstuvwxyz'); - eval('class ' . $controllerName . ' extends Illuminate\Routing\Controller { - public function getIndex() { - return Illuminate\Support\Facades\Response::make(1); - } - }'); - - // First, define a route. - $router = $this->getRouter(); - $router->cache(__FILE__, function () use ($router, $controllerName) { - $router->get('/{foo}/{bar}', $controllerName . '@getIndex')->where('foo', '\w+')->where('bar', '\d+'); - }); - - // Create a new router, set it on the app, and simulate a request. - $this->app['router'] = $this->getRouter(); - $this->app['router']->cache(__FILE__, callback: function () use ($router) { - throw new RuntimeException('This should not be called'); - }); - - // /herp/derp should not match above route. - $client = $this->createClient(); - $client->catchExceptions(false); - $client->request('GET', '/herp/derp'); - } - - public function testCanUseResource(): void - { - // Create a controller class. - $controllerName = str_shuffle('abcdefghijklmnopqrstuvwxyz'); - eval('class ' . $controllerName . ' extends Illuminate\Routing\Controller { }'); - - // First, define a resource. - $router = $this->getRouter(); - $key = $router->cache(__FILE__, function () use ($router, $controllerName) { - $router->resource('item', $controllerName); - }); - - static::assertTrue($this->app->cache->has($key), 'Routes must be in cache'); - static::assertEquals(8, $router->getRoutes()->count(), 'Routes must be in collection'); - - // Next request should not call the callback. - $router = $this->getRouter(); - $router->cache(__FILE__, function () use ($router) { - throw new RuntimeException('This should not be called'); - }); - static::assertEquals(8, $router->getRoutes()->count(), 'Routes must be obtained from cache'); - } - - public function testCanClearCache(): void - { - // Create a controller class. - $controllerName = str_shuffle('abcdefghijklmnopqrstuvwxyz'); - eval('class ' . $controllerName . ' extends Illuminate\Routing\Controller { }'); - - // First, define a route. - $router = $this->getRouter(); - $key = $router->cache(__FILE__, function () use ($router, $controllerName) { - $router->get('/{foo}/{bar}', $controllerName . '@getIndex')->where('foo', '\w+')->where('bar', '\d+'); - }); - static::assertTrue($this->app->cache->has($key), 'Routes must be in cache'); - - // Next, clear it. - $router->clearCache(__FILE__); - static::assertFalse($this->app->cache->has($key), 'Routes must no longer be cached'); - } - - public function testRebuildsWhenCachedFileIsCorrupt(): void - { - $router = $this->getRouter(); - $router->cache(__FILE__, function () use ($router) { - $router->get('/', 'HomeController@actionIndex'); - }); - - // Simulate a torn/partial write: keep a far-future expiry prefix so the - // entry is not treated as expired, but leave an unserializable body. - foreach (glob(self::$cachePath . '/*/*/*') as $file) { - file_put_contents($file, '9999999999corrupt-payload'); - } - - $rebuilt = false; - $router = $this->getRouter(); - $router->cache(__FILE__, function () use ($router, &$rebuilt) { - $rebuilt = true; - $router->get('/', 'HomeController@actionIndex'); - }); - - static::assertTrue($rebuilt, 'Corrupt cache must trigger a rebuild, not a failure'); - static::assertEquals(1, $router->getRoutes()->count(), 'Routes must be rebuilt from the callback'); - } - - public function testBootStillWorksWhenCacheIsUnwritable(): void - { - // Point the cache at a path that cannot be created (a file where a - // directory is expected), so the underlying write fails — mirroring an - // unwritable cache directory on a production node. - $files = new Filesystem; - $files->makeDirectory(self::$cachePath, 0777, true, true); - $blocker = self::$cachePath . '/blocker'; - file_put_contents($blocker, 'x'); - $this->app['config']['cache.path'] = $blocker . '/nested'; - - $router = $this->getRouter(); - $key = $router->cache(__FILE__, function () use ($router) { - $router->get('/', 'HomeController@actionIndex'); - }); - - static::assertNotNull($key, 'cache() must return normally despite the write failure'); - static::assertEquals(1, $router->getRoutes()->count(), 'Routes must still be defined when caching fails'); - } - - public function testBootStillWorksWhenRouteFileIsMissing(): void - { - // A route file removed in a deploy (while a worker still serves its - // stale opcode) makes filemtime() fail on the cache-key path. That must - // fall back to a rebuild, not escalate to a fatal boot error. - $missing = sys_get_temp_dir() . '/route-deleted-mid-deploy-' . uniqid() . '.php'; - - $defined = false; - $router = $this->getRouter(); - $key = $router->cache($missing, function () use ($router, &$defined) { - $defined = true; - $router->get('/', 'HomeController@actionIndex'); - }); - - static::assertNull($key, 'An unstattable route file must not be cached'); - static::assertTrue($defined, 'A missing route file must still define its routes directly'); - static::assertEquals(1, $router->getRoutes()->count(), 'Routes must still be defined'); - } -} diff --git a/tests/CachedRouting/RoutingServiceProviderTest.php b/tests/CachedRouting/RoutingServiceProviderTest.php deleted file mode 100644 index 05588ca4..00000000 --- a/tests/CachedRouting/RoutingServiceProviderTest.php +++ /dev/null @@ -1,97 +0,0 @@ -app === null) { - $this->refreshApplication(); - } - } - - /** - * Refresh the application instance. - * - * @return void - */ - protected function refreshApplication(): void - { - $this->app = $this->createApplication(); - - $this->app['env'] = 'testing'; - - $this->app->boot(); - } - - /** - * Creates the application. - */ - public function createApplication(): Application - { - return new Application(); - } - - /** - * @covers ::register - * @covers ::registerRouter - */ - public function testRegister(): void - { - $provider = new RoutingServiceProvider($this->app); - $provider->register(); - - static::assertInstanceOf(Router::class, $this->app->router); - } -} diff --git a/tests/Routing/RoutingControllerDispatcherTest.php b/tests/Routing/RoutingControllerDispatcherTest.php deleted file mode 100644 index 3e238c59..00000000 --- a/tests/Routing/RoutingControllerDispatcherTest.php +++ /dev/null @@ -1,74 +0,0 @@ - function () { - } - ] - ); - $route->bind($request); - $dispatcher = new ControllerDispatcher(m::mock(RouteFiltererInterface::class), new Container); - - $this->assertNull($_SERVER['ControllerDispatcherTestControllerStub']); - - $response = $dispatcher->dispatch($route, $request, 'ControllerDispatcherTestControllerStub', 'getIndex'); - $this->assertEquals('getIndex', $response); - $this->assertEquals('setupLayout', $_SERVER['ControllerDispatcherTestControllerStub']); - } - -} - - -class ControllerDispatcherTestControllerStub extends Controller { - - public function __construct() - { - // construct shouldn't affect setupLayout. - } - - protected function setupLayout() - { - $_SERVER['ControllerDispatcherTestControllerStub'] = __FUNCTION__; - } - - - public function getIndex() - { - return __FUNCTION__; - } - - - public function getFoo() - { - return __FUNCTION__; - } - -} diff --git a/tests/Routing/RoutingRedirectorTest.php b/tests/Routing/RoutingRedirectorTest.php deleted file mode 100644 index 449c92f0..00000000 --- a/tests/Routing/RoutingRedirectorTest.php +++ /dev/null @@ -1,167 +0,0 @@ -headers = m::mock(HeaderBag::class); - - $this->request = m::mock(Request::class); - $this->request->headers = $this->headers; - - $this->url = m::mock(UrlGenerator::class); - $this->url->shouldReceive('getRequest')->andReturn($this->request); - $this->url->shouldReceive('to')->with('bar', [], null)->andReturn('http://foo.com/bar'); - $this->url->shouldReceive('to')->with('bar', [], true)->andReturn('https://foo.com/bar'); - $this->url->shouldReceive('to')->with('login', [], null)->andReturn('http://foo.com/login'); - $this->url->shouldReceive('to')->with('http://foo.com/bar', [], null)->andReturn('http://foo.com/bar'); - $this->url->shouldReceive('to')->with('/', [], null)->andReturn('http://foo.com/'); - - $this->session = m::mock(Store::class); - - $this->redirect = new Redirector($this->url); - $this->redirect->setSession($this->session); - } - - - protected function tearDown(): void - { - m::close(); - } - - - public function testBasicRedirectTo() - { - $response = $this->redirect->to('bar'); - - $this->assertInstanceOf(RedirectResponse::class, $response); - $this->assertEquals('http://foo.com/bar', $response->getTargetUrl()); - $this->assertEquals(302, $response->getStatusCode()); - $this->assertEquals($this->session, $response->getSession()); - } - - - public function testComplexRedirectTo() - { - $response = $this->redirect->to('bar', 303, ['X-RateLimit-Limit' => 60, 'X-RateLimit-Remaining' => 59], true); - - $this->assertEquals('https://foo.com/bar', $response->getTargetUrl()); - $this->assertEquals(303, $response->getStatusCode()); - $this->assertEquals(60, $response->headers->get('X-RateLimit-Limit')); - $this->assertEquals(59, $response->headers->get('X-RateLimit-Remaining')); - } - - - public function testGuestPutCurrentUrlInSession() - { - $this->url->shouldReceive('full')->andReturn('http://foo.com/bar'); - $this->session->shouldReceive('put')->once()->with('url.intended', 'http://foo.com/bar'); - - $response = $this->redirect->guest('login'); - - $this->assertEquals('http://foo.com/login', $response->getTargetUrl()); - } - - - public function testIntendedRedirectToIntendedUrlInSession() - { - $this->session->shouldReceive('pull')->with('url.intended', '/')->andReturn('http://foo.com/bar'); - - $response = $this->redirect->intended(); - - $this->assertEquals('http://foo.com/bar', $response->getTargetUrl()); - } - - - public function testIntendedWithoutIntendedUrlInSession() - { - $this->session->shouldReceive('forget')->with('url.intended'); - - // without fallback url - $this->session->shouldReceive('pull')->with('url.intended', '/')->andReturn('/'); - $response = $this->redirect->intended(); - $this->assertEquals('http://foo.com/', $response->getTargetUrl()); - - // with a fallback url - $this->session->shouldReceive('pull')->with('url.intended', 'bar')->andReturn('bar'); - $response = $this->redirect->intended('bar'); - $this->assertEquals('http://foo.com/bar', $response->getTargetUrl()); - } - - - public function testRefreshRedirectToCurrentUrl() - { - $this->request->shouldReceive('path')->andReturn('http://foo.com/bar'); - $response = $this->redirect->refresh(); - $this->assertEquals('http://foo.com/bar', $response->getTargetUrl()); - } - - - public function testBackRedirectToHttpReferer() - { - $this->url->shouldReceive('previous')->andReturn('http://foo.com/bar'); - $response = $this->redirect->back(); - $this->assertEquals('http://foo.com/bar', $response->getTargetUrl()); - } - - - public function testBackRedirectToFallbackUrl() - { - $this->url->shouldReceive('previous')->with('/fallback')->andReturn('http://foo.com/fallback'); - - $response = $this->redirect->back(fallback: '/fallback'); - $this->assertEquals('http://foo.com/fallback', $response->getTargetUrl()); - } - - - public function testAwayDoesntValidateTheUrl() - { - $response = $this->redirect->away('bar'); - $this->assertEquals('bar', $response->getTargetUrl()); - } - - - public function testSecureRedirectToHttpsUrl() - { - $response = $this->redirect->secure('bar'); - $this->assertEquals('https://foo.com/bar', $response->getTargetUrl()); - } - - - public function testAction() - { - $this->url->shouldReceive('action')->with('bar@index', [])->andReturn('http://foo.com/bar'); - $response = $this->redirect->action('bar@index'); - $this->assertEquals('http://foo.com/bar', $response->getTargetUrl()); - } - - - public function testRoute() - { - $this->url->shouldReceive('route')->with('home')->andReturn('http://foo.com/bar'); - $this->url->shouldReceive('route')->with('home', [])->andReturn('http://foo.com/bar'); - - $response = $this->redirect->route('home'); - $this->assertEquals('http://foo.com/bar', $response->getTargetUrl()); - - $response = $this->redirect->home(); - $this->assertEquals('http://foo.com/bar', $response->getTargetUrl()); - } - -} diff --git a/tests/Routing/RoutingRouteTest.php b/tests/Routing/RoutingRouteTest.php deleted file mode 100644 index 64dec601..00000000 --- a/tests/Routing/RoutingRouteTest.php +++ /dev/null @@ -1,1084 +0,0 @@ -getRouter(); - $router->get( - 'foo/bar', - fn() => 'hello' - ); - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $route = $router->get( - 'foo/bar', - [ - 'domain' => 'api.{name}.bar', - fn($name) => $name - ] - ); - $route = $router->get( - 'foo/bar', - [ - 'domain' => 'api.{name}.baz', - fn($name) => $name - ] - ); - $this->assertEquals('taylor', $router->dispatch(Request::create('http://api.taylor.bar/foo/bar', 'GET'))->getContent()); - $this->assertEquals('dayle', $router->dispatch(Request::create('http://api.dayle.baz/foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $route = $router->get('foo/{age}', ['domain' => 'api.{name}.bar', fn($name, $age) => $name.$age]); - $this->assertEquals('taylor25', $router->dispatch(Request::create('http://api.taylor.bar/foo/25', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->post('foo/bar', fn() => 'post hello'); - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - $this->assertEquals('post hello', $router->dispatch(Request::create('foo/bar', 'POST'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/{bar}', fn($name) => $name); - $this->assertEquals('taylor', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/{bar}/{baz?}', fn($name, $age = 25) => $name.$age); - $this->assertEquals('taylor25', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/{name}/boom/{age?}/{location?}', fn($name, $age = 25, $location = 'AR') => $name.$age.$location); - $this->assertEquals('taylor30AR', $router->dispatch(Request::create('foo/taylor/boom/30', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('{bar}/{baz?}', fn($name, $age = 25) => $name.$age); - $this->assertEquals('taylor25', $router->dispatch(Request::create('taylor', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('{baz?}', fn($age = 25) => $age); - $this->assertEquals('25', $router->dispatch(Request::create('/', 'GET'))->getContent()); - $this->assertEquals('30', $router->dispatch(Request::create('30', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('{foo?}/{baz?}', ['as' => 'foo', fn($name = 'taylor', $age = 25) => $name.$age]); - $this->assertEquals('taylor25', $router->dispatch(Request::create('/', 'GET'))->getContent()); - $this->assertEquals('fred25', $router->dispatch(Request::create('fred', 'GET'))->getContent()); - $this->assertEquals('fred30', $router->dispatch(Request::create('fred/30', 'GET'))->getContent()); - $this->assertTrue($router->currentRouteNamed('foo')); - $this->assertTrue($router->is('foo')); - $this->assertFalse($router->is('bar')); - - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $this->assertEquals('', $router->dispatch(Request::create('foo/bar', 'HEAD'))->getContent()); - - $router = $this->getRouter(); - $router->any('foo/bar', fn() => 'hello'); - $this->assertEquals('', $router->dispatch(Request::create('foo/bar', 'HEAD'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'first'); - $router->get('foo/bar', fn() => 'second'); - $this->assertEquals('second', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar/åαф', function() { return 'hello'; }); - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar/%C3%A5%CE%B1%D1%84', 'GET'))->getContent()); - } - - - public function testOptionsResponsesAreGeneratedByDefault(): void - { - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->post('foo/bar', fn() => 'hello'); - $response = $router->dispatch(Request::create('foo/bar', 'OPTIONS')); - - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('GET,HEAD,POST', $response->headers->get('Allow')); - } - - - public function testHeadDispatcher(): void - { - $router = $this->getRouter(); - $router->match(['GET', 'POST'], 'foo', fn() => 'bar'); - - $response = $router->dispatch(Request::create('foo', 'OPTIONS')); - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('GET,HEAD,POST', $response->headers->get('Allow')); - - $response = $router->dispatch(Request::create('foo', 'HEAD')); - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('', $response->getContent()); - - $router = $this->getRouter(); - $router->match(['GET'], 'foo', fn() => 'bar'); - - $response = $router->dispatch(Request::create('foo', 'OPTIONS')); - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('GET,HEAD', $response->headers->get('Allow')); - - $router = $this->getRouter(); - $router->match(['POST'], 'foo', fn() => 'bar'); - - $response = $router->dispatch(Request::create('foo', 'OPTIONS')); - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('POST', $response->headers->get('Allow')); - } - - - public function testNonGreedyMatches(): void - { - $route = new Route('GET', 'images/{id}.{ext}', function() {}); - - $request1 = Request::create('images/1.png', 'GET'); - $this->assertTrue($route->matches($request1)); - $route->bind($request1); - $this->assertEquals('1', $route->parameter('id')); - $this->assertEquals('png', $route->parameter('ext')); - - $request2 = Request::create('images/12.png', 'GET'); - $this->assertTrue($route->matches($request2)); - $route->bind($request2); - $this->assertEquals('12', $route->parameter('id')); - $this->assertEquals('png', $route->parameter('ext')); - - // Test parameter() default value - $route = new Route('GET', 'foo/{foo?}', function() {}); - - $request3 = Request::create('foo', 'GET'); - $this->assertTrue($route->matches($request3)); - $route->bind($request3); - $this->assertEquals('bar', $route->parameter('foo', 'bar')); - } - - - public function testRoutesDontMatchNonMatchingPathsWithLeadingOptionals(): void - { - $this->expectException(Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class); - $router = $this->getRouter(); - $router->get( - '{baz?}', - fn($age = 25) => $age - ); - $this->assertEquals('25', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - } - - - public function testRoutesDontMatchNonMatchingDomain(): void - { - $this->expectException(Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class); - $router = $this->getRouter(); - $route = $router->get( - 'foo/bar', - [ - 'domain' => 'api.foo.bar', - fn() => 'hello' - ] - ); - $this->assertEquals( - 'hello', - $router->dispatch(Request::create('http://api.baz.boom/foo/bar', 'GET'))->getContent() - ); - } - - - public function testDispatchingOfControllers(): void - { - $router = $this->getRouter(); - $router->get('foo', 'RouteTestControllerDispatchStub@foo'); - $this->assertEquals('bar', $router->dispatch(Request::create('foo', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->filter('foo', fn() => 'filter'); - $router->get('bar', 'RouteTestControllerDispatchStub@bar'); - $this->assertEquals('filter', $router->dispatch(Request::create('bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('baz', 'RouteTestControllerDispatchStub@baz'); - $this->assertEquals('filtered', $router->dispatch(Request::create('baz', 'GET'))->getContent()); - - - unset($_SERVER['__test.after.filter']); - $router = $this->getRouter(); - $router->filter('qux', function() - { - $_SERVER['__test.after.filter'] = true; - }); - $router->get('qux', 'RouteTestControllerDispatchStub@qux'); - $this->assertEquals('qux', $router->dispatch(Request::create('qux', 'GET'))->getContent()); - $this->assertTrue($_SERVER['__test.after.filter']); - - /** - * Test filter removal. - */ - $router = $this->getRouter(); - $router->filter('removeBefore', function() { - $_SERVER['__test.before.removeBeforeFilter'] = true; - }); - $router->get('beforeRoute', 'RouteTestControllerRemoveFilterStub@beforeRoute'); - $this->assertEquals('beforeRoute', $router->dispatch(Request::create('beforeRoute', 'GET'))->getContent()); - $this->assertTrue(!isset($_SERVER['__test.after.removeBeforeFilter']) || is_null(isset($_SERVER['__test.after.removeBeforeFilter']))); - - $router = $this->getRouter(); - $router->filter('removeAfter', function() { - $_SERVER['__test.after.removeAfterFilter'] = true; - }); - $router->get('afterRoute', 'RouteTestControllerRemoveFilterStub@afterRoute'); - $this->assertEquals('afterRoute', $router->dispatch(Request::create('afterRoute', 'GET'))->getContent()); - $this->assertTrue(!isset($_SERVER['__test.after.removeAfterFilter']) || is_null(isset($_SERVER['__test.after.removeAfterFilter']))); - - /** - * Test filters disabled... - */ - $router = $this->getRouter(); - $router->filter('foo', fn() => 'filter'); - $router->disableFilters(); - $router->get('bar', 'RouteTestControllerDispatchStub@bar'); - $this->assertEquals('baz', $router->dispatch(Request::create('bar', 'GET'))->getContent()); - - $this->assertTrue($router->currentRouteUses('RouteTestControllerDispatchStub@bar')); - $this->assertTrue($router->uses('RouteTestControllerDispatchStub@bar')); - $this->assertFalse($router->uses('RouteTestControllerDispatchStub@baz')); - } - - - public function testBasicBeforeFilters(): void - { - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->before(fn() => 'foo!'); - $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->before('RouteTestFilterStub'); - $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->before('RouteTestFilterStub@handle'); - $this->assertEquals('handling!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', ['before' => 'foo', fn() => 'hello']); - $router->filter('foo', fn() => 'foo!'); - $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', ['before' => 'foo:25', fn() => 'hello']); - $router->filter('foo', fn($route, $request, $age) => $age); - $this->assertEquals('25', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', ['before' => 'foo:0,taylor', fn() => 'hello']); - $router->filter('foo', fn($route, $request, $age, $name) => $age.$name); - $this->assertEquals('0taylor', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', ['before' => 'foo:bar,baz', fn() => 'hello']); - $router->filter('foo', fn($route, $request, $bar, $baz) => $bar.$baz); - $this->assertEquals('barbaz', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', ['before' => 'foo:bar,baz|bar:boom', fn() => 'hello']); - $router->filter('foo', fn($route, $request, $bar, $baz) => null); - $router->filter('bar', fn($route, $request, $boom) => $boom); - $this->assertEquals('boom', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - /** - * Basic filter parameter - */ - unset($_SERVER['__route.filter']); - $router = $this->getRouter(); - $router->get('foo/bar', ['before' => 'foo:bar', fn() => 'hello']); - $router->filter('foo', function($route, $request, $value = null) { $_SERVER['__route.filter'] = $value; }); - $router->dispatch(Request::create('foo/bar', 'GET')); - $this->assertEquals('bar', $_SERVER['__route.filter']); - - /** - * Optional filter parameter - */ - unset($_SERVER['__route.filter']); - $router = $this->getRouter(); - $router->get('foo/bar', ['before' => 'foo', fn() => 'hello']); - $router->filter('foo', function($route, $request, $value = null) { $_SERVER['__route.filter'] = $value; }); - $router->dispatch(Request::create('foo/bar', 'GET')); - $this->assertNull($_SERVER['__route.filter']); - } - - - public function testFiltersCanBeDisabled(): void - { - $router = $this->getRouter(); - $router->disableFilters(); - $router->get('foo/bar', fn() => 'hello'); - $router->before(fn() => 'foo!'); - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->disableFilters(); - $router->get('foo/bar', ['before' => 'foo', fn() => 'hello']); - $router->filter('foo', fn() => 'foo!'); - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - } - - - public function testGlobalAfterFilters(): void - { - unset($_SERVER['__filter.after']); - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->after(function() { $_SERVER['__filter.after'] = true; return 'foo!'; }); - - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - $this->assertTrue($_SERVER['__filter.after']); - } - - - public function testBasicAfterFilters(): void - { - unset($_SERVER['__filter.after']); - $router = $this->getRouter(); - $router->get('foo/bar', ['after' => 'foo', fn() => 'hello']); - $router->filter('foo', function() { $_SERVER['__filter.after'] = true; return 'foo!'; }); - - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - $this->assertTrue($_SERVER['__filter.after']); - } - - - public function testPatternBasedFilters(): void - { - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->filter('foo', fn($route, $request, $bar) => 'foo'.$bar); - $router->when('foo/*', 'foo:bar'); - $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->filter('foo', fn($route, $request, $bar) => 'foo'.$bar); - $router->when('bar/*', 'foo:bar'); - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->filter('foo', fn($route, $request, $bar) => 'foo'.$bar); - $router->when('foo/*', 'foo:bar', ['post']); - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->filter('foo', fn($route, $request, $bar) => 'foo'.$bar); - $router->when('foo/*', 'foo:bar', ['get']); - $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->filter('foo', function($route, $request) {}); - $router->filter('bar', fn($route, $request) => 'bar'); - $router->when('foo/*', 'foo|bar', ['get']); - $this->assertEquals('bar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - } - - - public function testRegexBasedFilters(): void - { - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello'); - $router->get('bar/foo', fn() => 'hello'); - $router->get('baz/foo', fn() => 'hello'); - $router->filter('foo', fn($route, $request, $bar) => 'foo'.$bar); - $router->whenRegex('/^(foo|bar).*/', 'foo:bar'); - $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - $this->assertEquals('foobar', $router->dispatch(Request::create('bar/foo', 'GET'))->getContent()); - $this->assertEquals('hello', $router->dispatch(Request::create('baz/foo', 'GET'))->getContent()); - } - - - public function testRegexBasedFiltersWithVariables(): void - { - $router = $this->getRouter(); - $router->get('{var}/bar', fn($var) => 'hello'); - $router->filter('foo', fn($route, $request, $bar) => 'foo'.$bar); - $router->whenRegex('/^(foo|bar).*/', 'foo:bar'); - $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - $this->assertEquals('foobar', $router->dispatch(Request::create('bar/bar', 'GET'))->getContent()); - $this->assertEquals('hello', $router->dispatch(Request::create('baz/bar', 'GET'))->getContent()); - } - - - public function testGroupFiltersAndRouteFilters(): void - { - $router = $this->getRouter(); - $router->group(['before' => ['foo']], function() use ($router) - { - $router->get('foo/bar', fn() => 'hello')->before('bar'); - }); - $router->filter('foo', fn($route, $request) => 'foo'); - $router->filter('bar', fn($route, $request) => 'bar'); - $this->assertEquals('foo', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - } - - - public function testMatchesMethodAgainstRequests(): void - { - /** - * Basic - */ - $request = Request::create('foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', function() {}); - $this->assertTrue($route->matches($request)); - - $request = Request::create('foo/bar', 'GET'); - $route = new Route('GET', 'foo', function() {}); - $this->assertFalse($route->matches($request)); - - /** - * Method checks - */ - $request = Request::create('foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', function() {}); - $this->assertTrue($route->matches($request)); - - $request = Request::create('foo/bar', 'POST'); - $route = new Route('GET', 'foo', function() {}); - $this->assertFalse($route->matches($request)); - - /** - * Domain checks - */ - $request = Request::create('http://something.foo.com/foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', ['domain' => '{foo}.foo.com', function() {}]); - $this->assertTrue($route->matches($request)); - - $request = Request::create('http://something.bar.com/foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', ['domain' => '{foo}.foo.com', function() {}]); - $this->assertFalse($route->matches($request)); - - /** - * HTTPS checks - */ - $request = Request::create('https://foo.com/foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', ['https', function() {}]); - $this->assertTrue($route->matches($request)); - - $request = Request::create('https://foo.com/foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', ['https', 'baz' => true, function() {}]); - $this->assertTrue($route->matches($request)); - - $request = Request::create('http://foo.com/foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', ['https', function() {}]); - $this->assertFalse($route->matches($request)); - - /** - * HTTP checks - */ - $request = Request::create('https://foo.com/foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', ['http', function() {}]); - $this->assertFalse($route->matches($request)); - - $request = Request::create('http://foo.com/foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', ['http', function() {}]); - $this->assertTrue($route->matches($request)); - - $request = Request::create('http://foo.com/foo/bar', 'GET'); - $route = new Route('GET', 'foo/{bar}', ['baz' => true, function() {}]); - $this->assertTrue($route->matches($request)); - } - - - public function testWherePatternsProperlyFilter(): void - { - $request = Request::create('foo/123', 'GET'); - $route = new Route('GET', 'foo/{bar}', function() {}); - $route->where('bar', '[0-9]+'); - $this->assertTrue($route->matches($request)); - - $request = Request::create('foo/123abc', 'GET'); - $route = new Route('GET', 'foo/{bar}', function() {}); - $route->where('bar', '[0-9]+'); - $this->assertFalse($route->matches($request)); - - $request = Request::create('foo/123abc', 'GET'); - $route = new Route('GET', 'foo/{bar}', ['where' => ['bar' => '[0-9]+'], function() {}]); - $route->where('bar', '[0-9]+'); - $this->assertFalse($route->matches($request)); - - /** - * Optional - */ - $request = Request::create('foo/123', 'GET'); - $route = new Route('GET', 'foo/{bar?}', function() {}); - $route->where('bar', '[0-9]+'); - $this->assertTrue($route->matches($request)); - - $request = Request::create('foo/123', 'GET'); - $route = new Route('GET', 'foo/{bar?}', ['where' => ['bar' => '[0-9]+'], function() {}]); - $route->where('bar', '[0-9]+'); - $this->assertTrue($route->matches($request)); - - $request = Request::create('foo/123', 'GET'); - $route = new Route('GET', 'foo/{bar?}/{baz?}', function() {}); - $route->where('bar', '[0-9]+'); - $this->assertTrue($route->matches($request)); - - $request = Request::create('foo/123/foo', 'GET'); - $route = new Route('GET', 'foo/{bar?}/{baz?}', function() {}); - $route->where('bar', '[0-9]+'); - $this->assertTrue($route->matches($request)); - - $request = Request::create('foo/123abc', 'GET'); - $route = new Route('GET', 'foo/{bar?}', function() {}); - $route->where('bar', '[0-9]+'); - $this->assertFalse($route->matches($request)); - } - - - public function testDotDoesNotMatchEverything(): void - { - $route = new Route('GET', 'images/{id}.{ext}', function() {}); - - $request1 = Request::create('images/1.png', 'GET'); - $this->assertTrue($route->matches($request1)); - $route->bind($request1); - $this->assertEquals('1', $route->parameter('id')); - $this->assertEquals('png', $route->parameter('ext')); - - $request2 = Request::create('images/12.png', 'GET'); - $this->assertTrue($route->matches($request2)); - $route->bind($request2); - $this->assertEquals('12', $route->parameter('id')); - $this->assertEquals('png', $route->parameter('ext')); - - } - - - public function testRouteBinding(): void - { - $router = $this->getRouter(); - $router->get('foo/{bar}', fn($name) => $name); - $router->bind('bar', fn($value) => strtoupper($value)); - $this->assertEquals('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); - } - - - public function testRouteClassBinding(): void - { - $router = $this->getRouter(); - $router->get('foo/{bar}', fn($name) => $name); - $router->bind('bar', 'RouteBindingStub'); - $this->assertEquals('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); - } - - - public function testRouteClassMethodBinding(): void - { - $router = $this->getRouter(); - $router->get('foo/{bar}', fn($name) => $name); - $router->bind('bar', 'RouteBindingStub@find'); - $this->assertEquals('dragon', $router->dispatch(Request::create('foo/Dragon', 'GET'))->getContent()); - } - - - public function testModelBinding(): void - { - $router = $this->getRouter(); - $router->get('foo/{bar}', fn($name) => $name); - $router->model('bar', 'RouteModelBindingStub'); - $this->assertEquals('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); - } - - - public function testModelBindingWithNullReturn(): void - { - $this->expectException(Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class); - $router = $this->getRouter(); - $router->get( - 'foo/{bar}', - fn($name) => $name - ); - $router->model('bar', 'RouteModelBindingNullStub'); - $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent(); - } - - - public function testModelBindingWithCustomNullReturn(): void - { - $router = $this->getRouter(); - $router->get('foo/{bar}', fn($name) => $name); - $router->model('bar', 'RouteModelBindingNullStub', fn() => 'missing'); - $this->assertEquals('missing', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); - } - - - public function testGroupMerging(): void - { - $old = ['prefix' => 'foo/bar/']; - $this->assertEquals( - ['prefix' => 'foo/bar/baz', 'namespace' => null, 'where' => []], Router::mergeGroup( - ['prefix' => 'baz'], $old)); - - $old = ['domain' => 'foo']; - $this->assertEquals( - ['domain' => 'baz', 'prefix' => null, 'namespace' => null, 'where' => []], Router::mergeGroup( - ['domain' => 'baz'], $old)); - - $old = ['where' => ['var1' => 'foo', 'var2' => 'bar']]; - $this->assertEquals([ - 'prefix' => null, 'namespace' => null, 'where' => [ - 'var1' => 'foo', 'var2' => 'baz', 'var3' => 'qux', - ] - ], Router::mergeGroup(['where' => ['var2' => 'baz', 'var3' => 'qux']], $old)); - - $old = []; - $this->assertEquals([ - 'prefix' => null, 'namespace' => null, 'where' => [ - 'var1' => 'foo', 'var2' => 'bar', - ] - ], Router::mergeGroup(['where' => ['var1' => 'foo', 'var2' => 'bar']], $old)); - } - - - public function testRouteGrouping(): void - { - /** - * Inhereting Filters - */ - $router = $this->getRouter(); - $router->group(['before' => 'foo'], function() use ($router) - { - $router->get('foo/bar', fn() => 'hello'); - }); - $router->filter('foo', fn() => 'foo!'); - $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - - /** - * Merging Filters - */ - $router = $this->getRouter(); - $router->group(['before' => 'foo'], function() use ($router) - { - $router->get('foo/bar', ['before' => 'bar', fn() => 'hello']); - }); - $router->filter('foo', function() {}); - $router->filter('bar', fn() => 'foo!'); - $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - - /** - * Merging Filters - */ - $router = $this->getRouter(); - $router->group(['before' => 'foo|bar'], function() use ($router) - { - $router->get('foo/bar', ['before' => 'baz', fn() => 'hello']); - }); - $router->filter('foo', function() {}); - $router->filter('bar', function() {}); - $router->filter('baz', fn() => 'foo!'); - $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - /** - * getPrefix() method - */ - $router = $this->getRouter(); - $router->group(['prefix' => 'foo'], function() use ($router) - { - $router->get('bar', fn() => 'hello'); - }); - $routes = $router->getRoutes(); - $routes = $routes->getRoutes(); - $this->assertEquals('foo', $routes[0]->getPrefix()); - } - - - public function testMergingControllerUses(): void - { - $router = $this->getRouter(); - $router->group(['namespace' => 'Namespace'], function() use ($router) - { - $router->get('foo/bar', 'Controller'); - }); - $routes = $router->getRoutes()->getRoutes(); - $action = $routes[0]->getAction(); - - $this->assertEquals('Namespace\\Controller', $action['controller']); - - - $router = $this->getRouter(); - $router->group(['namespace' => 'Namespace'], function() use ($router) - { - $router->group(['namespace' => 'Nested'], function() use ($router) - { - $router->get('foo/bar', 'Controller'); - }); - }); - $routes = $router->getRoutes()->getRoutes(); - $action = $routes[0]->getAction(); - - $this->assertEquals('Namespace\\Nested\\Controller', $action['controller']); - - - $router = $this->getRouter(); - $router->group(['prefix' => 'baz'], function() use ($router) - { - $router->group(['namespace' => 'Namespace'], function() use ($router) - { - $router->get('foo/bar', 'Controller'); - }); - }); - $routes = $router->getRoutes()->getRoutes(); - $action = $routes[0]->getAction(); - - $this->assertEquals('Namespace\\Controller', $action['controller']); - } - - - public function testResourceRouting(): void - { - $router = $this->getRouter(); - $router->resource('foo', 'FooController'); - $routes = $router->getRoutes(); - $this->assertCount(8, $routes); - - $router = $this->getRouter(); - $router->resource('foo', 'FooController', ['only' => ['show', 'destroy']]); - $routes = $router->getRoutes(); - - $this->assertCount(2, $routes); - - $router = $this->getRouter(); - $router->resource('foo', 'FooController', ['except' => ['show', 'destroy']]); - $routes = $router->getRoutes(); - - $this->assertCount(6, $routes); - - $router = $this->getRouter(); - $router->resource('foo-bars', 'FooController', ['only' => ['show']]); - $routes = $router->getRoutes(); - $routes = $routes->getRoutes(); - - $this->assertEquals('foo-bars/{foo_bars}', $routes[0]->getUri()); - - $router = $this->getRouter(); - $router->resource('foo-bars.foo-bazs', 'FooController', ['only' => ['show']]); - $routes = $router->getRoutes(); - $routes = $routes->getRoutes(); - - $this->assertEquals('foo-bars/{foo_bars}/foo-bazs/{foo_bazs}', $routes[0]->getUri()); - - $router = $this->getRouter(); - $router->resource('foo-bars', 'FooController', ['only' => ['show'], 'as' => 'prefix']); - $routes = $router->getRoutes(); - $routes = $routes->getRoutes(); - - $this->assertEquals('foo-bars/{foo_bars}', $routes[0]->getUri()); - $this->assertEquals('prefix.foo-bars.show', $routes[0]->getName()); - } - - - public function testResourceRouteNaming(): void - { - $router = $this->getRouter(); - $router->resource('foo', 'FooController'); - - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.index')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.show')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.create')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.store')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.edit')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.update')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.destroy')); - - $router = $this->getRouter(); - $router->resource('foo.bar', 'FooController'); - - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.bar.index')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.bar.show')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.bar.create')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.bar.store')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.bar.edit')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.bar.update')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo.bar.destroy')); - - $router = $this->getRouter(); - $router->resource('foo', 'FooController', [ - 'names' => [ - 'index' => 'foo', - 'show' => 'bar', - ] - ]); - - $this->assertTrue($router->getRoutes()->hasNamedRoute('foo')); - $this->assertTrue($router->getRoutes()->hasNamedRoute('bar')); - } - - - public function testRouterFiresRoutedEvent(): void - { - $events = new Illuminate\Events\Dispatcher(); - $router = new Router($events); - $router->get('foo/bar', fn() => ''); - - $request = Request::create('http://foo.com/foo/bar', 'GET'); - $route = new Route('GET', 'foo/bar', ['http', function() {}]); - - $_SERVER['__router.request'] = null; - $_SERVER['__router.route'] = null; - - $router->matched(function($route, $request){ - $_SERVER['__router.request'] = $request; - $_SERVER['__router.route'] = $route; - }); - - $router->dispatchToRoute($request); - - $this->assertInstanceOf(Request::class, $_SERVER['__router.request']); - $this->assertEquals($_SERVER['__router.request'], $request); - unset($_SERVER['__router.request']); - - $this->assertInstanceOf(Route::class, $_SERVER['__router.route']); - $this->assertEquals($_SERVER['__router.route']->getUri(), $route->getUri()); - unset($_SERVER['__router.route']); - } - - - public function testRouterPatternSetting(): void - { - $router = $this->getRouter(); - $router->pattern('test', 'pattern'); - $this->assertEquals(['test' => 'pattern'], $router->getPatterns()); - - $router = $this->getRouter(); - $router->patterns(['test' => 'pattern', 'test2' => 'pattern2']); - $this->assertEquals(['test' => 'pattern', 'test2' => 'pattern2'], $router->getPatterns()); - } - - - public function testRouteParametersDefaultValue() - { - $router = $this->getRouter(); - - $router->get('foo/{bar?}', function ($bar = '') { - return $bar; - })->defaults('bar', 'foo'); - $this->assertEquals('foo', $router->dispatch(Request::create('foo', 'GET'))->getContent()); - - - $router->get('foo/{bar?}', function ($bar = '') { - return $bar; - })->defaults('bar', 'foo'); - $this->assertEquals('bar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - } - - - public function testRouteRedirect() - { - $router = $this->getRouter(); - $router->get('contact_us', function () { - throw new \Exception('Route should not be reachable.'); - }); - $router->redirect('contact_us', 'contact', 302); - - $response = $router->dispatch(Request::create('contact_us', 'GET')); - $this->assertTrue($response->isRedirect('contact')); - $this->assertEquals(302, $response->getStatusCode()); - } - - - public function testDispatchingCallableActionClasses() - { - $router = $this->getRouter(); - $router->get('foo/bar', 'ActionStub'); - - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - $router->get('foo/bar2', [ - 'uses' => 'ActionStub', - ]); - - $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar2', 'GET'))->getContent()); - } - - - public function testRouteMiddlewareRunsAndWraps(): void - { - // Closure middleware wraps the route response. - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello')->middleware(fn($request, $next) => $next($request).'!'); - $this->assertEquals('hello!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - // Middleware that never calls $next short-circuits the route. - $router = $this->getRouter(); - $router->get('foo/bar', fn() => 'hello')->middleware(fn($request, $next) => 'blocked'); - $this->assertEquals('blocked', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - // Alias resolves to a class middleware. - $router = $this->getRouter(); - $router->aliasMiddleware('stub', 'RouteMiddlewareStub'); - $router->get('foo/bar', fn() => 'hello')->middleware('stub'); - $this->assertEquals('hello-stubbed', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - // Parameter after ':' is passed to the middleware. - $router = $this->getRouter(); - $router->aliasMiddleware('append', 'RouteAppendMiddlewareStub'); - $router->get('foo/bar', fn() => 'hello')->middleware('append:X'); - $this->assertEquals('helloX', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - // A group expands to its members, nesting outer->inner. - $router = $this->getRouter(); - $router->aliasMiddleware('append', 'RouteAppendMiddlewareStub'); - $router->middlewareGroup('grp', ['append:-a', 'append:-b']); - $router->get('foo/bar', fn() => 'x')->middleware('grp'); - $this->assertEquals('x-b-a', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - } - - - public function testRouteMiddlewareCoexistsWithFilters(): void - { - // A before filter that short-circuits still bypasses middleware (filters wrap middleware). - $router = $this->getRouter(); - $router->filter('block', fn() => 'blocked-by-filter'); - $router->get('foo/bar', ['before' => 'block', fn() => 'hello']) - ->middleware(fn($request, $next) => $next($request).'+mw'); - $this->assertEquals('blocked-by-filter', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - - // A pass-through before filter lets the route run; middleware still wraps it. - $router = $this->getRouter(); - $router->filter('pass', fn() => null); - $router->get('foo/bar', ['before' => 'pass', fn() => 'hello']) - ->middleware(fn($request, $next) => $next($request).'+mw'); - $this->assertEquals('hello+mw', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent()); - } - - - protected function getRouter(): Router - { - return new Router(new Illuminate\Events\Dispatcher); - } - -} - - -class RouteTestControllerDispatchStub extends Illuminate\Routing\Controller { - public function __construct() - { - $this->beforeFilter('foo', ['only' => 'bar']); - $this->beforeFilter('@filter', ['only' => 'baz']); - $this->afterFilter('qux', ['only' => 'qux']); - } - public function foo(): string - { - return 'bar'; - } - public function bar(): string - { - return 'baz'; - } - public function filter(): string - { - return 'filtered'; - } - public function baz(): string - { - return 'baz'; - } - public function qux(): string - { - return 'qux'; - } -} - -class RouteTestControllerRemoveFilterStub extends Controller -{ - public function __construct() - { - $this->beforeFilter('removeBefore', ['only' => 'beforeRoute']); - $this->beforeFilter('@inlineBeforeFilter', ['only' => 'beforeRoute']); - $this->afterFilter('removeAfter', ['only' => 'afterRoute']); - $this->afterFilter('@inlineAfterFilter', ['only' => 'afterRoute']); - - $this->forgetBeforeFilter('removeBefore'); - $this->forgetBeforeFilter('@inlineBeforeFilter'); - $this->forgetAfterFilter('removeAfter'); - $this->forgetAfterFilter('@inlineAfterFilter'); - } - public function beforeRoute(): string - { - return __FUNCTION__; - } - public function afterRoute(): string - { - return __FUNCTION__; - } - public function inlineBeforeFilter(): string - { - return __FUNCTION__; - } - public function inlineAfterFilter(): string - { - return __FUNCTION__; - } -} - -class RouteBindingStub { - public function bind($value, $route): string - { return strtoupper((string) $value); } - public function find($value, $route): string - { return strtolower((string) $value); } -} - -class RouteModelBindingStub { - public function find($value): string - { return strtoupper((string) $value); } -} - -class RouteModelBindingNullStub { - public function find($value): void - {} -} - -class RouteTestFilterStub { - public function filter(): string - { - return 'foo!'; - } - public function handle(): string - { - return 'handling!'; - } -} - -class ActionStub extends Controller -{ - public function __invoke(): string - { - return 'hello'; - } -} - -class RouteMiddlewareStub { - public function handle($request, $next) - { - return $next($request).'-stubbed'; - } -} - -class RouteAppendMiddlewareStub { - public function handle($request, $next, $suffix) - { - return $next($request).$suffix; - } -} diff --git a/tests/Routing/RoutingUrlGeneratorTest.php b/tests/Routing/RoutingUrlGeneratorTest.php deleted file mode 100755 index 700aee70..00000000 --- a/tests/Routing/RoutingUrlGeneratorTest.php +++ /dev/null @@ -1,293 +0,0 @@ -assertEquals('http://www.foo.com/foo/bar', $url->to('foo/bar')); - $this->assertEquals('https://www.foo.com/foo/bar', $url->to('foo/bar', [], true)); - $this->assertEquals('https://www.foo.com/foo/bar/baz/boom', $url->to('foo/bar', ['baz', 'boom'], true)); - - /** - * Test HTTPS request URL generation... - */ - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('https://www.foo.com/') - ); - - $this->assertEquals('https://www.foo.com/foo/bar', $url->to('foo/bar')); - - /** - * Test asset URL generation... - */ - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('http://www.foo.com/index.php/') - ); - - $this->assertEquals('http://www.foo.com/foo/bar', $url->asset('foo/bar')); - $this->assertEquals('https://www.foo.com/foo/bar', $url->asset('foo/bar', true)); - } - - - public function testBasicRouteGeneration(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('http://www.foo.com/') - ); - - /** - * Empty Named Route - */ - $route = new Illuminate\Routing\Route(['GET'], '/', ['as' => 'plain']); - $routes->add($route); - - /** - * Named Routes - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar', ['as' => 'foo']); - $routes->add($route); - - /** - * Parameters... - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar/{baz}/breeze/{boom}', ['as' => 'bar']); - $routes->add($route); - - /** - * HTTPS... - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar', ['as' => 'baz', 'https']); - $routes->add($route); - - /** - * Controller Route Route - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar', ['controller' => 'foo@bar']); - $routes->add($route); - - /** - * Non ASCII routes - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar/åαф/{baz}', ['as' => 'foobarbaz']); - $routes->add($route); - - $this->assertEquals('/', $url->route('plain', [], false)); - $this->assertEquals('/?foo=bar', $url->route('plain', ['foo' => 'bar'], false)); - $this->assertEquals('http://www.foo.com/foo/bar', $url->route('foo')); - $this->assertEquals('/foo/bar', $url->route('foo', [], false)); - $this->assertEquals('/foo/bar?foo=bar', $url->route('foo', ['foo' => 'bar'], false)); - $this->assertEquals('http://www.foo.com/foo/bar/taylor/breeze/otwell?fly=wall', $url->route('bar', ['taylor', 'otwell', 'fly' => 'wall'] - )); - $this->assertEquals('http://www.foo.com/foo/bar/otwell/breeze/taylor?fly=wall', $url->route('bar', ['boom' => 'taylor', 'baz' => 'otwell', 'fly' => 'wall'] - )); - $this->assertEquals('/foo/bar/taylor/breeze/otwell?fly=wall', $url->route('bar', ['taylor', 'otwell', 'fly' => 'wall'], false)); - $this->assertEquals('https://www.foo.com/foo/bar', $url->route('baz')); - $this->assertEquals('http://www.foo.com/foo/bar', $url->action('foo@bar')); - $this->assertEquals('http://www.foo.com/foo/bar/taylor/breeze/otwell?wall&woz', $url->route('bar', ['wall', 'woz', 'boom' => 'otwell', 'baz' => 'taylor'] - )); - $this->assertEquals('http://www.foo.com/foo/bar/taylor/breeze/otwell?wall&woz', $url->route('bar', ['taylor', 'otwell', 'wall', 'woz'] - )); - $this->assertEquals('http://www.foo.com/foo/bar/%C3%A5%CE%B1%D1%84/%C3%A5%CE%B1%D1%84', $url->route('foobarbaz', ['baz' => 'åαф'] - )); - - } - - - public function testRoutesMaintainRequestScheme(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('https://www.foo.com/') - ); - - /** - * Named Routes - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar', ['as' => 'foo']); - $routes->add($route); - - $this->assertEquals('https://www.foo.com/foo/bar', $url->route('foo')); - } - - - public function testHttpOnlyRoutes(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('https://www.foo.com/') - ); - - /** - * Named Routes - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar', ['as' => 'foo', 'http']); - $routes->add($route); - - $this->assertEquals('http://www.foo.com/foo/bar', $url->route('foo')); - } - - - public function testRoutesWithDomains(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('http://www.foo.com/') - ); - - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar', ['as' => 'foo', 'domain' => 'sub.foo.com']); - $routes->add($route); - - /** - * Wildcards & Domains... - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar/{baz}', ['as' => 'bar', 'domain' => 'sub.{foo}.com']); - $routes->add($route); - - $this->assertEquals('http://sub.foo.com/foo/bar', $url->route('foo')); - $this->assertEquals('http://sub.taylor.com/foo/bar/otwell', $url->route('bar', ['taylor', 'otwell'])); - $this->assertEquals('/foo/bar/otwell', $url->route('bar', ['taylor', 'otwell'], false)); - } - - - public function testRoutesWithDomainsAndPorts(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('http://www.foo.com:8080/') - ); - - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar', ['as' => 'foo', 'domain' => 'sub.foo.com']); - $routes->add($route); - - /** - * Wildcards & Domains... - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar/{baz}', ['as' => 'bar', 'domain' => 'sub.{foo}.com']); - $routes->add($route); - - $this->assertEquals('http://sub.foo.com:8080/foo/bar', $url->route('foo')); - $this->assertEquals('http://sub.taylor.com:8080/foo/bar/otwell', $url->route('bar', ['taylor', 'otwell'])); - } - - - public function testHttpsRoutesWithDomains(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('https://foo.com/') - ); - - /** - * When on HTTPS, no need to specify 443 - */ - $route = new Illuminate\Routing\Route(['GET'], 'foo/bar', ['as' => 'baz', 'domain' => 'sub.foo.com']); - $routes->add($route); - - $this->assertEquals('https://sub.foo.com/foo/bar', $url->route('baz')); - } - - - public function testUrlGenerationForControllers(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('http://www.foo.com:8080/') - ); - - $route = new Illuminate\Routing\Route(['GET'], 'foo/{one}/{two?}/{three?}', ['as' => 'foo', function() {}]); - $routes->add($route); - - $this->assertEquals('http://www.foo.com:8080/foo', $url->route('foo')); - } - - - public function testForceRootUrl(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('http://www.foo.com/') - ); - - $url->forceRootUrl('https://www.bar.com'); - $this->assertEquals('http://www.bar.com/foo/bar', $url->to('foo/bar')); - - - /** - * Route Based... - */ - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('http://www.foo.com/') - ); - - $url->forceSchema('https'); - $route = new Illuminate\Routing\Route(['GET'], '/foo', ['as' => 'plain']); - $routes->add($route); - - $this->assertEquals('https://www.foo.com/foo', $url->route('plain')); - - $url->forceRootUrl('https://www.bar.com'); - $this->assertEquals('https://www.bar.com/foo', $url->route('plain')); - } - - - public function testPrevious(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('http://www.foo.com/') - ); - - $url->getRequest()->headers->set('referer', 'http://www.bar.com/'); - $this->assertEquals('http://www.bar.com/', $url->previous()); - - $url->getRequest()->headers->remove('referer'); - $this->assertEquals($url->to('/'), $url->previous()); - } - - - public function testPreviousUrlFromSession(): void - { - $session = m::mock(Store::class); - $request = Illuminate\Http\Request::create('http://www.foo.com/some'); - - $session->shouldReceive('previousUrl')->andReturn('http://www.foo.com/previous-page'); - $request->setLaravelSession($session); - - $url = new UrlGenerator( - new Illuminate\Routing\RouteCollection, - $request - ); - - $this->assertEquals('http://www.foo.com/previous-page', $url->previous()); - } - - - public function testPreviousWithFallback(): void - { - $url = new UrlGenerator( - $routes = new Illuminate\Routing\RouteCollection, - $request = Illuminate\Http\Request::create('http://www.foo.com/') - ); - - $url->getRequest()->headers->set('referer', 'http://www.bar.com/'); - $this->assertEquals('http://www.bar.com/', $url->previous('/some-page')); - - $url->getRequest()->headers->remove('referer'); - $this->assertEquals($url->to('/some-page'), $url->previous('/some-page')); - } - -} diff --git a/tests/Support/SupportFacadeResponseTest.php b/tests/Support/SupportFacadeResponseTest.php deleted file mode 100755 index 8365a9c1..00000000 --- a/tests/Support/SupportFacadeResponseTest.php +++ /dev/null @@ -1,63 +0,0 @@ -instance(ResponseFactoryContract::class, new ResponseFactory(null)); - - Response::clearResolvedInstances(); - Response::setFacadeApplication($app); - } - - protected function tearDown(): void - { - Response::setFacadeApplication(null); - m::close(); - } - - - public function testArrayableSendAsJson() - { - $data = m::mock(ArrayableInterface::class); - $data->shouldReceive('toArray')->andReturn(['foo' => 'bar']); - - $response = Response::json($data); - $this->assertEquals('{"foo":"bar"}', $response->getContent()); - } - - - public function testMakeWorksWithoutViewBinding() - { - $response = Response::make('hello', 201); - - $this->assertEquals('hello', $response->getContent()); - $this->assertEquals(201, $response->getStatusCode()); - } - - - public function testViewResolvesViewFactoryLazilyFromContainer() - { - $viewFactory = m::mock('StdClass'); - $viewFactory->shouldReceive('make')->once()->with('welcome', ['a' => 1])->andReturn('rendered'); - - $container = new Container; - $container->instance('view', $viewFactory); - $factory = new ResponseFactory($container); - - $this->assertEquals('rendered', $factory->view('welcome', ['a' => 1])->getContent()); - } - -}