diff --git a/.gitignore b/.gitignore index 4a45ef5..af40440 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ vendor composer.lock .php_cs.cache +coverage diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f0d8807..df4cef1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,3 +45,11 @@ Good pull requests – patches, improvements, new features – are a fantastic h ```sh composer test ``` + +To get code coverage information execute the following comand: + +```sh +composer coverage +``` + +Then, open the `./coverage/index.html` file in your browser. diff --git a/composer.json b/composer.json index ca1722e..5676f25 100644 --- a/composer.json +++ b/composer.json @@ -41,9 +41,10 @@ }, "scripts": { "test": [ - "phpunit", + "phpunit --coverage-text", "phpcs" ], - "cs-fix": "php-cs-fixer fix ." + "cs-fix": "php-cs-fixer fix .", + "coverage": "phpunit --coverage-html=coverage" } } diff --git a/src/Factory.php b/src/Factory.php index 48330cd..fc10b98 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -39,6 +39,7 @@ abstract class Factory /** * Set a custom ResponseFactory. + * @codeCoverageIgnore */ public static function setResponseFactory(ResponseFactoryInterface $responseFactory) { @@ -47,6 +48,7 @@ public static function setResponseFactory(ResponseFactoryInterface $responseFact /** * Set a custom StreamFactory. + * @codeCoverageIgnore */ public static function setStreamFactory(StreamFactoryInterface $streamFactory) { @@ -55,6 +57,7 @@ public static function setStreamFactory(StreamFactoryInterface $streamFactory) /** * Set a custom UriFactory. + * @codeCoverageIgnore */ public static function setUriFactory(UriFactoryInterface $uriFactory) { @@ -63,6 +66,7 @@ public static function setUriFactory(UriFactoryInterface $uriFactory) /** * Set a custom ServerRequestFactory. + * @codeCoverageIgnore */ public static function setServerRequestFactory(ServerRequestFactoryInterface $serverRequestFactory) { diff --git a/src/RequestHandlerContainer.php b/src/RequestHandlerContainer.php index 8505111..f550dd8 100644 --- a/src/RequestHandlerContainer.php +++ b/src/RequestHandlerContainer.php @@ -10,7 +10,6 @@ use Psr\Http\Server\RequestHandlerInterface; use ReflectionClass; use ReflectionMethod; -use RuntimeException; /** * Resolve a callable using a container. @@ -50,23 +49,19 @@ public function get($id) { try { $handler = $this->resolve($id); + + if ($handler instanceof RequestHandlerInterface) { + return $handler; + } + + return new CallableHandler($handler); + } catch (NotFoundExceptionInterface $exception) { + throw $exception; } catch (Exception $exception) { throw new class("Error getting the handler $id", 0, $exception) extends Exception implements ContainerExceptionInterface { }; } - - if ($handler instanceof RequestHandlerInterface) { - return $handler; - } - - if (is_callable($handler)) { - return new CallableHandler($handler); - } - - throw new class("Handler $id not found or has not valid type", 0, $exception) - extends Exception implements NotFoundExceptionInterface { - }; } /** @@ -84,10 +79,6 @@ protected function resolve(string $handler) return function_exists($handler) ? $handler : $this->createClass($handler); } - if (!is_array($handler) || !is_string($handler[0])) { - return $handler; - } - list($class, $method) = $handler; if ((new ReflectionMethod($class, $method))->isStatic()) { @@ -105,7 +96,9 @@ protected function resolve(string $handler) protected function createClass(string $className) { if (!class_exists($className)) { - throw new RuntimeException("The class {$className} does not exists"); + throw new class("The class $className does not exists") + extends Exception implements NotFoundExceptionInterface { + }; } $reflection = new ReflectionClass($className); @@ -120,7 +113,7 @@ protected function createClass(string $className) /** * Slit a string to an array * - * @return string|array + * @return string|string[] */ protected function split(string $string) { diff --git a/tests/ControllerStub.php b/tests/Assets/Controller.php similarity index 52% rename from tests/ControllerStub.php rename to tests/Assets/Controller.php index 3d0ab33..aafa3f0 100644 --- a/tests/ControllerStub.php +++ b/tests/Assets/Controller.php @@ -1,10 +1,14 @@ assertEquals('Hello World', (string) $response->getBody()); } + public function testExecuteHandler() + { + $callable = new CallableHandler(function ($request) { + echo $request->getHeaderLine('Foo'); + }); + + $request = Factory::createServerRequest()->withHeader('Foo', 'Bar'); + $response = $callable->handle($request); + + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertEquals('Bar', (string) $response->getBody()); + } + public function testOb() { $callable = new CallableHandler(function () { diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index 7c3540a..7d1be97 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -36,6 +36,20 @@ public function testStream() $this->assertTrue($stream->isSeekable()); } + public function testStreamWithResource() + { + $resource = fopen('php://temp', 'r+'); + fwrite($resource, 'Hello world'); + + $stream = Factory::createStream($resource); + + $this->assertInstanceOf(StreamInterface::class, $stream); + $this->assertInstanceOf(Stream::class, $stream); + $this->assertTrue($stream->isWritable()); + $this->assertTrue($stream->isSeekable()); + $this->assertEquals('Hello world', (string) $stream); + } + public function testUri() { $uri = Factory::createUri('http://example.com/my-path'); diff --git a/tests/RequestHandlerContainerTest.php b/tests/RequestHandlerContainerTest.php index cebed0f..77ec86a 100644 --- a/tests/RequestHandlerContainerTest.php +++ b/tests/RequestHandlerContainerTest.php @@ -3,8 +3,13 @@ namespace Middlewares\Tests; +use Middlewares\Tests\Assets\Controller; +use Middlewares\Tests\Assets\ErrorController; +use Middlewares\Tests\Assets\RequestHandlerController; use Middlewares\Utils\RequestHandlerContainer; use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; use Psr\Http\Server\RequestHandlerInterface; final class ReflectionResolverTest extends TestCase @@ -13,9 +18,9 @@ public function testResolveClass() { $resolver = new RequestHandlerContainer(); - $this->assertTrue($resolver->has(ControllerStub::class)); + $this->assertTrue($resolver->has(Controller::class)); - $callable = $resolver->get(ControllerStub::class); + $callable = $resolver->get(Controller::class); $this->assertInstanceOf(RequestHandlerInterface::class, $callable); } @@ -24,9 +29,31 @@ public function testResolveClassCallable() { $resolver = new RequestHandlerContainer(); - $this->assertTrue($resolver->has(ControllerStub::class.'::action')); + $this->assertTrue($resolver->has(Controller::class.'::action')); - $callable = $resolver->get(ControllerStub::class.'::action'); + $callable = $resolver->get(Controller::class.'::action'); + + $this->assertInstanceOf(RequestHandlerInterface::class, $callable); + } + + public function testResolveClassStaticCallable() + { + $resolver = new RequestHandlerContainer(); + + $this->assertTrue($resolver->has(Controller::class.'::staticAction')); + + $callable = $resolver->get(Controller::class.'::staticAction'); + + $this->assertInstanceOf(RequestHandlerInterface::class, $callable); + } + + public function testResolveRequestHandler() + { + $resolver = new RequestHandlerContainer(); + + $this->assertTrue($resolver->has(RequestHandlerController::class)); + + $callable = $resolver->get(RequestHandlerController::class); $this->assertInstanceOf(RequestHandlerInterface::class, $callable); } @@ -41,4 +68,26 @@ public function testResolveFunction() $this->assertInstanceOf(RequestHandlerInterface::class, $callable); } + + public function testContainerExceptionInterface() + { + $resolver = new RequestHandlerContainer(); + + $this->assertTrue($resolver->has(ErrorController::class)); + + $this->expectException(ContainerExceptionInterface::class); + + $callable = $resolver->get(ErrorController::class); + } + + public function testNotFoundException() + { + $resolver = new RequestHandlerContainer(); + + $this->assertFalse($resolver->has('foo')); + + $this->expectException(NotFoundExceptionInterface::class); + + $resolver->get('foo'); + } }