diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b175ed5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +max_line_length = 120 +tab_width = 4 diff --git a/README.md b/README.md index 1c75577..36d300a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Author](https://img.shields.io/badge/author-@philipobenito-blue.svg?style=flat-square)](https://twitter.com/philipobenito) [![Latest Version](https://img.shields.io/github/release/thephpleague/route.svg?style=flat-square)](https://github.com/thephpleague/route/releases) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) -[![Build Status](https://img.shields.io/travis/thephpleague/route/master.svg?style=flat-square)](https://travis-ci.org/thephpleague/route) +[![Tests](https://github.com/thephpleague/route/actions/workflows/test.yml/badge.svg)](https://github.com/thephpleague/route/actions/workflows/test.yml) [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/route.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/route/code-structure) [![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/route.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/route) [![Total Downloads](https://img.shields.io/packagist/dt/league/route.svg?style=flat-square)](https://packagist.org/packages/league/route) @@ -29,10 +29,10 @@ $ composer require league/route The following versions of PHP are supported by this version. -* PHP 7.2 -* PHP 7.3 -* PHP 7.4 -* PHP 8.0 +* PHP 8.1 +* PHP 8.2 +* PHP 8.3 +* PHP 8.4 ## Documentation diff --git a/composer.json b/composer.json index f6bd888..1c4d931 100644 --- a/composer.json +++ b/composer.json @@ -16,29 +16,29 @@ "authors": [ { "name": "Phil Bennett", - "email": "philipobenito@gmail.com", + "email": "mail@philbennett.co.uk", "role": "Developer" } ], "require": { - "php": "^7.2 || ^8.0", + "php": "^8.1", "nikic/fast-route": "^1.3", - "psr/container": "^1.0|^2.0", + "psr/container": "^2.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0.1", "psr/http-server-handler": "^1.0.1", "psr/http-server-middleware": "^1.0.1", - "opis/closure": "^3.5.5", - "psr/simple-cache": "^1.0" + "opis/closure": "^3.6.3", + "psr/simple-cache": "^3.0" }, "require-dev": { - "laminas/laminas-diactoros": "^2.3", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^8.5", - "roave/security-advisories": "dev-master", + "laminas/laminas-diactoros": "^2.10", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^10.2", + "roave/security-advisories": "dev-latest", "scrutinizer/ocular": "^1.8", - "squizlabs/php_codesniffer": "^3.5" + "squizlabs/php_codesniffer": "^3.7" }, "replace": { "orno/route": "~1.0", @@ -58,6 +58,7 @@ "extra": { "branch-alias": { "dev-master": "5.x-dev", + "dev-6.x": "6.x-dev", "dev-5.x": "5.x-dev", "dev-4.x": "4.x-dev", "dev-3.x": "3.x-dev", diff --git a/phpunit.xml b/phpunit.xml index 1f0d1c0..629fab6 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,29 +1,39 @@ - - - - tests - - - - - src/ - - - - - - - - - + stopOnFailure="false" + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" + cacheDirectory=".phpunit.cache" + backupStaticProperties="false" + testdox="false" + displayDetailsOnIncompleteTests="true" + displayDetailsOnSkippedTests="true" + displayDetailsOnTestsThatTriggerDeprecations="true" + displayDetailsOnTestsThatTriggerErrors="true" + displayDetailsOnTestsThatTriggerNotices="true" + displayDetailsOnTestsThatTriggerWarnings="true" +> + + + + + + + + + + tests + + + + + + + + src/ + + diff --git a/src/Cache/FileCache.php b/src/Cache/FileCache.php index 1ce0b22..7bbd69b 100644 --- a/src/Cache/FileCache.php +++ b/src/Cache/FileCache.php @@ -4,42 +4,30 @@ namespace League\Route\Cache; -use Psr\SimpleCache\CacheInterface; +use Psr\SimpleCache\{CacheInterface, InvalidArgumentException}; class FileCache implements CacheInterface { - /** - * @var string - */ - protected $cacheFilePath; - - /** - * @var integer - */ - protected $ttl; - - public function __construct(string $cacheFilePath, int $ttl) + public function __construct(protected string $cacheFilePath, protected int $ttl) { - $this->cacheFilePath = $cacheFilePath; - $this->ttl = $ttl; } - public function get($key, $default = null) + public function get(string $key, mixed $default = null): mixed { return ($this->has($key)) ? file_get_contents($this->cacheFilePath) : $default; } - public function set($key, $value, $ttl = null): bool + public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool { return (bool) file_put_contents($this->cacheFilePath, $value); } - public function has($key): bool + public function has(string $key): bool { return file_exists($this->cacheFilePath) && time() - filemtime($this->cacheFilePath) < $this->ttl; } - public function delete($key): bool + public function delete(string $key): bool { return unlink($this->cacheFilePath); } @@ -49,17 +37,17 @@ public function clear(): bool return $this->delete($this->cacheFilePath); } - public function getMultiple($keys, $default = null): iterable + public function getMultiple(iterable $keys, mixed $default = null): iterable { return []; } - public function setMultiple($values, $ttl = null): bool + public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool { return false; } - public function deleteMultiple($keys): bool + public function deleteMultiple(iterable $keys): bool { return false; } diff --git a/src/Cache/Router.php b/src/Cache/Router.php index 8130127..f3a9185 100644 --- a/src/Cache/Router.php +++ b/src/Cache/Router.php @@ -26,26 +26,17 @@ class Router */ protected $builder; - /** - * @var CacheInterface - */ - protected $cache; - /** * @var integer */ protected $ttl; - /** - * @var bool - */ - protected $cacheEnabled; - - public function __construct(callable $builder, CacheInterface $cache, bool $cacheEnabled = true) - { + public function __construct( + callable $builder, + protected CacheInterface $cache, + protected bool $cacheEnabled = true + ) { $this->builder = $builder; - $this->cache = $cache; - $this->cacheEnabled = $cacheEnabled; } public function dispatch(ServerRequestInterface $request): ResponseInterface diff --git a/src/ContainerAwareInterface.php b/src/ContainerAwareInterface.php index 8a689d7..9c4cd74 100644 --- a/src/ContainerAwareInterface.php +++ b/src/ContainerAwareInterface.php @@ -9,5 +9,5 @@ interface ContainerAwareInterface { public function getContainer(): ?ContainerInterface; - public function setContainer(ContainerInterface $container): ContainerAwareInterface; + public function setContainer(ContainerInterface $container): self; } diff --git a/src/ContainerAwareTrait.php b/src/ContainerAwareTrait.php index 33c5234..51b7b5d 100644 --- a/src/ContainerAwareTrait.php +++ b/src/ContainerAwareTrait.php @@ -9,10 +9,7 @@ trait ContainerAwareTrait { - /** - * @var ?ContainerInterface - */ - protected $container; + protected ?ContainerInterface $container = null; public function getContainer(): ?ContainerInterface { diff --git a/src/Dispatcher.php b/src/Dispatcher.php index eb651c9..4a8d746 100644 --- a/src/Dispatcher.php +++ b/src/Dispatcher.php @@ -26,8 +26,8 @@ class Dispatcher extends GroupCountBasedDispatcher implements public function dispatchRequest(ServerRequestInterface $request): ResponseInterface { $method = $request->getMethod(); - $uri = $request->getUri()->getPath(); - $match = $this->dispatch($method, $uri); + $uri = $request->getUri()->getPath(); + $match = $this->dispatch($method, $uri); switch ($match[0]) { case FastRoute::NOT_FOUND: diff --git a/src/Http/Exception.php b/src/Http/Exception.php index 0fc8926..020347d 100644 --- a/src/Http/Exception.php +++ b/src/Http/Exception.php @@ -9,33 +9,14 @@ class Exception extends \Exception implements HttpExceptionInterface { - /** - * @var array - */ - protected $headers = []; - - /** - * @var string - */ - protected $message; - - /** - * @var integer - */ - protected $status; - public function __construct( - int $status, - string $message = null, + protected int $status, + protected $message = '', \Exception $previous = null, - array $headers = [], + protected array $headers = [], int $code = 0 ) { - $this->headers = $headers; - $this->message = $message; - $this->status = $status; - - parent::__construct($message, $code, $previous); + parent::__construct($this->message, $code, $previous); } public function getStatusCode(): int @@ -59,7 +40,7 @@ public function buildJsonResponse(ResponseInterface $response): ResponseInterfac if ($response->getBody()->isWritable()) { $response->getBody()->write(json_encode([ - 'status_code' => $this->status, + 'status_code' => $this->status, 'reason_phrase' => $this->message ])); } diff --git a/src/Http/Request.php b/src/Http/Request.php new file mode 100644 index 0000000..84c2808 --- /dev/null +++ b/src/Http/Request.php @@ -0,0 +1,16 @@ +method = $method; - $this->path = $path; + public function __construct( + protected array|string $method, + protected string $path, + callable|string $handler, + protected ?RouteGroup $group = null, + protected array $vars = [] + ) { $this->handler = $handler; } @@ -57,7 +39,7 @@ public function getCallable(?ContainerInterface $container = null): callable { $callable = $this->handler; - if (is_string($callable) && strpos($callable, '::') !== false) { + if (is_string($callable) && str_contains($callable, '::')) { $callable = explode('::', $callable); } @@ -80,7 +62,7 @@ public function getCallable(?ContainerInterface $container = null): callable return $callable; } - public function getMethod(): string + public function getMethod(): array|string { return $this->method; } @@ -122,8 +104,8 @@ public function process( public function setParentGroup(RouteGroup $group): self { $this->group = $group; - $prefix = $this->group->getPrefix(); - $path = $this->getPath(); + $prefix = $this->group->getPrefix(); + $path = $this->getPath(); if (strcmp($prefix, substr($path, 0, strlen($prefix))) !== 0) { $path = $prefix . $path; @@ -139,7 +121,11 @@ public function setVars(array $vars): self return $this; } - protected function resolve(string $class, ?ContainerInterface $container = null) + /** + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + protected function resolve(string $class, ?ContainerInterface $container = null): mixed { if ($container instanceof ContainerInterface && $container->has($class)) { return $container->get($class); diff --git a/src/RouteCollectionInterface.php b/src/RouteCollectionInterface.php index a33e0db..e41e1d1 100644 --- a/src/RouteCollectionInterface.php +++ b/src/RouteCollectionInterface.php @@ -6,12 +6,12 @@ interface RouteCollectionInterface { - public function delete(string $path, $handler): Route; - public function get(string $path, $handler): Route; - public function head(string $path, $handler): Route; - public function map(string $method, string $path, $handler): Route; - public function options(string $path, $handler): Route; - public function patch(string $path, $handler): Route; - public function post(string $path, $handler): Route; - public function put(string $path, $handler): Route; + public function delete(string $path, string|callable $handler): Route; + public function get(string $path, string|callable $handler): Route; + public function head(string $path, string|callable $handler): Route; + public function map(string|array $method, string $path, string|callable $handler): Route; + public function options(string $path, string|callable $handler): Route; + public function patch(string $path, string|callable $handler): Route; + public function post(string $path, string|callable $handler): Route; + public function put(string $path, string|callable $handler): Route; } diff --git a/src/RouteCollectionTrait.php b/src/RouteCollectionTrait.php index f8e3832..150b6da 100644 --- a/src/RouteCollectionTrait.php +++ b/src/RouteCollectionTrait.php @@ -4,42 +4,44 @@ namespace League\Route; +use League\Route\Http\Request; + trait RouteCollectionTrait { - abstract public function map(string $method, string $path, $handler): Route; + abstract public function map(string|array $method, string $path, string|callable $handler): Route; - public function delete(string $path, $handler): Route + public function delete(string $path, string|callable $handler): Route { - return $this->map('DELETE', $path, $handler); + return $this->map(Request::METHOD_DELETE, $path, $handler); } - public function get(string $path, $handler): Route + public function get(string $path, string|callable $handler): Route { - return $this->map('GET', $path, $handler); + return $this->map(Request::METHOD_GET, $path, $handler); } - public function head(string $path, $handler): Route + public function head(string $path, string|callable $handler): Route { - return $this->map('HEAD', $path, $handler); + return $this->map(Request::METHOD_HEAD, $path, $handler); } - public function options(string $path, $handler): Route + public function options(string $path, string|callable $handler): Route { - return $this->map('OPTIONS', $path, $handler); + return $this->map(Request::METHOD_OPTIONS, $path, $handler); } - public function patch(string $path, $handler): Route + public function patch(string $path, string|callable $handler): Route { - return $this->map('PATCH', $path, $handler); + return $this->map(Request::METHOD_PATCH, $path, $handler); } - public function post(string $path, $handler): Route + public function post(string $path, string|callable $handler): Route { - return $this->map('POST', $path, $handler); + return $this->map(Request::METHOD_POST, $path, $handler); } - public function put(string $path, $handler): Route + public function put(string $path, string|callable $handler): Route { - return $this->map('PUT', $path, $handler); + return $this->map(Request::METHOD_PUT, $path, $handler); } } diff --git a/src/RouteConditionHandlerInterface.php b/src/RouteConditionHandlerInterface.php index c46c625..764ab0d 100644 --- a/src/RouteConditionHandlerInterface.php +++ b/src/RouteConditionHandlerInterface.php @@ -10,8 +10,8 @@ public function getHost(): ?string; public function getName(): ?string; public function getPort(): ?int; public function getScheme(): ?string; - public function setHost(string $host): RouteConditionHandlerInterface; - public function setName(string $name): RouteConditionHandlerInterface; - public function setPort(int $port): RouteConditionHandlerInterface; - public function setScheme(string $scheme): RouteConditionHandlerInterface; + public function setHost(string $host): self; + public function setName(string $name): self; + public function setPort(int $port): self; + public function setScheme(string $scheme): self; } diff --git a/src/RouteConditionHandlerTrait.php b/src/RouteConditionHandlerTrait.php index b12635b..29d7528 100644 --- a/src/RouteConditionHandlerTrait.php +++ b/src/RouteConditionHandlerTrait.php @@ -9,25 +9,10 @@ trait RouteConditionHandlerTrait { - /** - * @var ?string - */ - protected $host; - - /** - * @var ?string - */ - protected $name; - - /** - * @var ?int - */ - protected $port; - - /** - * @var ?string - */ - protected $scheme; + protected ?string $host = null; + protected ?string $name = null; + protected ?int $port = null; + protected ?string $scheme = null; public function getHost(): ?string { diff --git a/src/RouteGroup.php b/src/RouteGroup.php index 47fd56b..266a4cc 100644 --- a/src/RouteGroup.php +++ b/src/RouteGroup.php @@ -23,21 +23,13 @@ class RouteGroup implements */ protected $callback; - /** - * @var RouteCollectionInterface - */ - protected $collection; - - /** - * @var string - */ - protected $prefix; - - public function __construct(string $prefix, callable $callback, RouteCollectionInterface $collection) - { - $this->callback = $callback; - $this->collection = $collection; - $this->prefix = sprintf('/%s', ltrim($prefix, '/')); + public function __construct( + protected string $prefix, + callable $callback, + protected RouteCollectionInterface $collection + ) { + $this->callback = $callback; + $this->prefix = sprintf('/%s', ltrim($this->prefix, '/')); } public function __invoke(): void @@ -50,9 +42,9 @@ public function getPrefix(): string return $this->prefix; } - public function map(string $method, string $path, $handler): Route + public function map(string|array $method, string $path, string|callable $handler): Route { - $path = ($path === '/') ? $this->prefix : $this->prefix . sprintf('/%s', ltrim($path, '/')); + $path = ($path === '/') ? $this->prefix : $this->prefix . sprintf('/%s', ltrim($path, '/')); $route = $this->collection->map($method, $path, $handler); $route->setParentGroup($this); diff --git a/src/Router.php b/src/Router.php index 0cabd8e..20afb34 100644 --- a/src/Router.php +++ b/src/Router.php @@ -29,17 +29,14 @@ class Router implements /** * @var RouteGroup[] */ - protected $groups = []; + protected array $groups = []; /** * @var Route[] */ - protected $namedRoutes = []; + protected array $namedRoutes = []; - /** - * @var array - */ - protected $patternMatchers = [ + protected array $patternMatchers = [ '/{(.+?):number}/' => '{$1:[0-9]+}', '/{(.+?):word}/' => '{$1:[a-zA-Z]+}', '/{(.+?):alphanum_dash}/' => '{$1:[a-zA-Z0-9-_]+}', @@ -47,29 +44,18 @@ class Router implements '/{(.+?):uuid}/' => '{$1:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}+}' ]; - /** - * @var RouteCollector - */ - protected $routeCollector; - /** * @var Route[] */ - protected $routes = []; + protected array $routes = []; - /** - * @var bool - */ - protected $routesPrepared = false; + protected bool $routesPrepared = false; - /** - * @var array - */ - protected $routesData = []; + protected array $routesData = []; - public function __construct(?RouteCollector $routeCollector = null) + public function __construct(protected ?RouteCollector $routeCollector = null) { - $this->routeCollector = $routeCollector ?? new RouteCollector( + $this->routeCollector = $this->routeCollector ?? new RouteCollector( new RouteParser\Std(), new DataGenerator\GroupCountBased() ); @@ -131,9 +117,9 @@ public function handle(ServerRequestInterface $request): ResponseInterface return $this->dispatch($request); } - public function map(string $method, string $path, $handler): Route + public function map(string|array $method, string $path, string|callable $handler): Route { - $path = sprintf('/%s', ltrim($path, '/')); + $path = sprintf('/%s', ltrim($path, '/')); $route = new Route($method, $path, $handler); $this->routes[] = $route; diff --git a/src/Strategy/AbstractStrategy.php b/src/Strategy/AbstractStrategy.php index d866907..3c2107b 100644 --- a/src/Strategy/AbstractStrategy.php +++ b/src/Strategy/AbstractStrategy.php @@ -8,10 +8,7 @@ abstract class AbstractStrategy implements StrategyInterface { - /** - * @var array - */ - protected $responseDecorators = []; + protected array $responseDecorators = []; public function addResponseDecorator(callable $decorator): StrategyInterface { diff --git a/src/Strategy/JsonStrategy.php b/src/Strategy/JsonStrategy.php index bbfd389..8a7f546 100644 --- a/src/Strategy/JsonStrategy.php +++ b/src/Strategy/JsonStrategy.php @@ -17,21 +17,8 @@ class JsonStrategy extends AbstractStrategy implements ContainerAwareInterface, { use ContainerAwareTrait; - /** - * @var ResponseFactoryInterface - */ - protected $responseFactory; - - /** - * @var int - */ - protected $jsonFlags; - - public function __construct(ResponseFactoryInterface $responseFactory, int $jsonFlags = 0) + public function __construct(protected ResponseFactoryInterface $responseFactory, protected int $jsonFlags = 0) { - $this->responseFactory = $responseFactory; - $this->jsonFlags = $jsonFlags; - $this->addResponseDecorator(static function (ResponseInterface $response): ResponseInterface { if (false === $response->hasHeader('content-type')) { $response = $response->withHeader('content-type', 'application/json'); diff --git a/src/Strategy/StrategyAwareInterface.php b/src/Strategy/StrategyAwareInterface.php index 7f5b197..22dcdc5 100644 --- a/src/Strategy/StrategyAwareInterface.php +++ b/src/Strategy/StrategyAwareInterface.php @@ -7,5 +7,5 @@ interface StrategyAwareInterface { public function getStrategy(): ?StrategyInterface; - public function setStrategy(StrategyInterface $strategy): StrategyAwareInterface; + public function setStrategy(StrategyInterface $strategy): self; } diff --git a/src/Strategy/StrategyAwareTrait.php b/src/Strategy/StrategyAwareTrait.php index 1b7f3cb..34eb9bb 100644 --- a/src/Strategy/StrategyAwareTrait.php +++ b/src/Strategy/StrategyAwareTrait.php @@ -6,10 +6,7 @@ trait StrategyAwareTrait { - /** - * @var ?StrategyInterface - */ - protected $strategy; + protected ?StrategyInterface $strategy = null; public function setStrategy(StrategyInterface $strategy): StrategyAwareInterface { diff --git a/src/Strategy/StrategyInterface.php b/src/Strategy/StrategyInterface.php index cd4a6e9..71130a8 100644 --- a/src/Strategy/StrategyInterface.php +++ b/src/Strategy/StrategyInterface.php @@ -11,7 +11,7 @@ interface StrategyInterface { - public function addResponseDecorator(callable $decorator): StrategyInterface; + public function addResponseDecorator(callable $decorator): self; public function getMethodNotAllowedDecorator(MethodNotAllowedException $exception): MiddlewareInterface; public function getNotFoundDecorator(NotFoundException $exception): MiddlewareInterface; public function getThrowableHandler(): MiddlewareInterface; diff --git a/tests/DispatchIntegrationTest.php b/tests/DispatchIntegrationTest.php index e5eee56..32cb738 100644 --- a/tests/DispatchIntegrationTest.php +++ b/tests/DispatchIntegrationTest.php @@ -206,14 +206,14 @@ public function testDispatchesExceptionWithJsonStrategyRoute(): void ->expects($this->once()) ->method('withAddedHeader') ->with($this->equalTo('content-type'), $this->equalTo('application/json')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $response ->expects($this->once()) ->method('withStatus') ->with($this->equalTo(500), $this->equalTo('Blah')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $factory = $this->createMock(ResponseFactoryInterface::class); @@ -285,14 +285,14 @@ public function testDispatchesHttpExceptionWithJsonStrategyRoute(): void ->expects($this->once()) ->method('withAddedHeader') ->with($this->equalTo('content-type'), $this->equalTo('application/json')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $response ->expects($this->once()) ->method('withStatus') ->with($this->equalTo(400), $this->equalTo('Bad Request')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $factory = $this->createMock(ResponseFactoryInterface::class); @@ -387,14 +387,14 @@ public function testDispatchesNotFoundRouteWithJsonStrategy(): void ->expects($this->once()) ->method('withAddedHeader') ->with($this->equalTo('content-type'), $this->equalTo('application/json')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $response ->expects($this->once()) ->method('withStatus') ->with($this->equalTo(404), $this->equalTo('Not Found')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $response @@ -491,24 +491,16 @@ public function testDispatchesNotAllowedRouteWithJsonStrategy(): void ; $response - ->expects($this->at(0)) - ->method('withAddedHeader') - ->with($this->equalTo('Allow'), $this->equalTo('GET, OPTIONS')) - ->will($this->returnSelf()) - ; - - $response - ->expects($this->at(1)) + ->expects($this->exactly(2)) ->method('withAddedHeader') - ->with($this->equalTo('content-type'), $this->equalTo('application/json')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $response ->expects($this->once()) ->method('withStatus') ->with($this->equalTo(405), $this->equalTo('Method Not Allowed')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $response @@ -864,33 +856,9 @@ public function process( ; $request - ->expects($this->at(3)) - ->method('withRequestTarget') - ->with($this->equalTo('middleware4')) - ; - - $request - ->expects($this->at(4)) - ->method('withRequestTarget') - ->with($this->equalTo('middleware1')) - ; - - $request - ->expects($this->at(5)) - ->method('withRequestTarget') - ->with($this->equalTo('middleware2')) - ; - - $request - ->expects($this->at(6)) - ->method('withRequestTarget') - ->with($this->equalTo('middleware3')) - ; - - $request - ->expects($this->at(7)) + ->expects($this->exactly(5)) ->method('withRequestTarget') - ->with($this->equalTo('middleware4')) + ->with($this->matchesRegularExpression('/middleware[1-4]/')) ; $uri diff --git a/tests/Http/ExceptionTest.php b/tests/Http/ExceptionTest.php index d5e8a5e..61bcaac 100644 --- a/tests/Http/ExceptionTest.php +++ b/tests/Http/ExceptionTest.php @@ -34,7 +34,7 @@ protected function responseTester(Exception $e): void $response ->method('withAddedHeader') - ->will($this->returnSelf()) + ->willReturnSelf() ; $response @@ -47,7 +47,7 @@ protected function responseTester(Exception $e): void ->expects($this->once()) ->method('withStatus') ->with($e->getStatusCode(), $e->getMessage()) - ->will($this->returnSelf()) + ->willReturnSelf() ; $response = $e->buildJsonResponse($response); diff --git a/tests/Http/Response/DecoratorTest.php b/tests/Http/Response/DecoratorTest.php index 04fb509..77a1311 100644 --- a/tests/Http/Response/DecoratorTest.php +++ b/tests/Http/Response/DecoratorTest.php @@ -13,30 +13,24 @@ public function testDecoratesWithDefaultHeaders(): void { $decorator = new Decorator\DefaultHeaderDecorator([ 'content-type' => 'application/json', - 'custom-key' => 'custom value', + 'custom-key' => 'custom value', ]); $response = $this->createMock(ResponseInterface::class); $response - ->expects($this->at(0)) + ->expects($this->exactly(2)) ->method('hasHeader') - ->with($this->equalTo('content-type')) - ->willReturn(false) - ; - - $response - ->expects($this->at(2)) - ->method('hasHeader') - ->with($this->equalTo('custom-key')) - ->willReturn(true) + ->willReturnCallback(function (string $header) { + return $header !== 'content-type'; + }) ; $response ->expects($this->once()) ->method('withAddedHeader') ->with($this->equalTo('content-type'), $this->equalTo('application/json')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $decorator($response); diff --git a/tests/RouteGroupTest.php b/tests/RouteGroupTest.php index 6db688d..3c8bf89 100644 --- a/tests/RouteGroupTest.php +++ b/tests/RouteGroupTest.php @@ -20,69 +20,31 @@ public function testGroupIsInvokedAndAddsRoutesToCollection(): void ->expects($this->exactly(8)) ->method('setHost') ->with($this->equalTo('example.com')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $route ->expects($this->exactly(8)) ->method('setScheme') ->with($this->equalTo('https')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $route ->expects($this->exactly(8)) ->method('setPort') ->with($this->equalTo(8080)) - ->will($this->returnSelf()) + ->willReturnSelf() ; $router - ->expects($this->at(0)) + ->expects($this->exactly(7)) ->method('map') - ->with($this->equalTo('GET'), $this->equalTo('/acme/route'), $this->equalTo($callback)) - ->willReturn($route) - ; - - $router - ->expects($this->at(1)) - ->method('map') - ->with($this->equalTo('POST'), $this->equalTo('/acme/route'), $this->equalTo($callback)) - ->willReturn($route) - ; - - $router - ->expects($this->at(2)) - ->method('map') - ->with($this->equalTo('PUT'), $this->equalTo('/acme/route'), $this->equalTo($callback)) - ->willReturn($route) - ; - - $router - ->expects($this->at(3)) - ->method('map') - ->with($this->equalTo('PATCH'), $this->equalTo('/acme/route'), $this->equalTo($callback)) - ->willReturn($route) - ; - - $router - ->expects($this->at(4)) - ->method('map') - ->with($this->equalTo('DELETE'), $this->equalTo('/acme/route'), $this->equalTo($callback)) - ->willReturn($route) - ; - - $router - ->expects($this->at(5)) - ->method('map') - ->with($this->equalTo('OPTIONS'), $this->equalTo('/acme/route'), $this->equalTo($callback)) - ->willReturn($route) - ; - - $router - ->expects($this->at(6)) - ->method('map') - ->with($this->equalTo('HEAD'), $this->equalTo('/acme/route'), $this->equalTo($callback)) + ->with( + $this->matchesRegularExpression('/^(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)$/'), + $this->equalTo('/acme/route'), + $this->equalTo($callback) + ) ->willReturn($route) ; @@ -127,7 +89,7 @@ public function testGroupAddsStrategyToRoute(): void ->expects($this->once()) ->method('setStrategy') ->with($this->equalTo($strategy)) - ->will($this->returnSelf()) + ->willReturnSelf() ; $group = new RouteGroup('/acme', function ($route) use ($callback) { diff --git a/tests/RouteTest.php b/tests/RouteTest.php index 4ba77ce..1c04fee 100644 --- a/tests/RouteTest.php +++ b/tests/RouteTest.php @@ -81,13 +81,6 @@ public function testRouteSetsAndResolvesClassMethodCallableAsStringWithoutContai $this->assertEquals('action', $newCallable[1]); } - public function testRouteThrowsExceptionWhenSettingAndResolvingNonCallable(): void - { - $this->expectException(RuntimeException::class); - $route = new Route('GET', '/', new \stdClass()); - $route->getCallable(); - } - public function testRouteCanSetAndGetAllProperties(): void { $route = new Route('GET', '/something', static function () { diff --git a/tests/RouterTest.php b/tests/RouterTest.php index ab49f1b..b02a206 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -67,7 +67,7 @@ public function testNewPatternMatchesCanBeAddedAtRuntime(): void { $router = new class () extends Router { - public $patternMatchers = []; + public array $patternMatchers = []; }; $router->addPatternMatcher('mockMatcher', '[a-zA-Z]'); diff --git a/tests/Strategy/JsonStrategyTest.php b/tests/Strategy/JsonStrategyTest.php index 5c4135d..abd39f5 100644 --- a/tests/Strategy/JsonStrategyTest.php +++ b/tests/Strategy/JsonStrategyTest.php @@ -57,7 +57,7 @@ public function testStrategyInvokesRouteCallable(): void ->expects($this->once()) ->method('withHeader') ->with($this->equalTo('content-type'), $this->equalTo('application/json')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $factory = $this->createMock(ResponseFactoryInterface::class); @@ -86,7 +86,7 @@ public function testStrategyInvokesRouteCallableWithArrayReturn(): void ->expects($this->once()) ->method('withHeader') ->with($this->equalTo('content-type'), $this->equalTo('application/json')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $expectedResponse @@ -223,14 +223,14 @@ public function testStrategyReturnsCorrectThrowableHandler(): void ->expects($this->once()) ->method('withAddedHeader') ->with($this->equalTo('content-type'), $this->equalTo('application/json')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $response ->expects($this->once()) ->method('withStatus') ->with($this->equalTo(500), $this->equalTo('Exception thrown')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $body @@ -311,7 +311,7 @@ public function testStrategyInvokesRouteCallableWithObjectReturn(): void ->expects($this->once()) ->method('withHeader') ->with($this->equalTo('content-type'), $this->equalTo('application/json')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $expectedResponse @@ -369,17 +369,9 @@ public function testStrategyProvidesOptionsRouteCallable(): void $factory = $this->createMock(ResponseFactoryInterface::class); $response - ->expects($this->at(0)) + ->expects($this->exactly(2)) ->method('withHeader') - ->with($this->equalTo('allow'), $this->equalTo('GET, POST')) - ->will($this->returnSelf()) - ; - - $response - ->expects($this->at(1)) - ->method('withHeader') - ->with($this->equalTo('access-control-allow-methods'), $this->equalTo('GET, POST')) - ->will($this->returnSelf()) + ->willReturnSelf() ; $factory