diff options
author | minstel <minstel@yandex.ru> | 2016-10-21 00:07:38 +0300 |
---|---|---|
committer | minstel <minstel@yandex.ru> | 2016-10-21 00:07:38 +0300 |
commit | f07a3e06e2338ac481998ed47d98073c806cc268 (patch) | |
tree | 74ac4bf2434c311da2f59bf7287acaaf47dfb381 | |
parent | 18da10400c02d945632c8c7dd49d78d19d9fd9a0 (diff) | |
download | controller-f07a3e06e2338ac481998ed47d98073c806cc268.zip controller-f07a3e06e2338ac481998ed47d98073c806cc268.tar.gz controller-f07a3e06e2338ac481998ed47d98073c806cc268.tar.bz2 |
Fixes
-rw-r--r-- | src/Controller/RouteAction.php | 54 | ||||
-rw-r--r-- | tests/Controller/RouteActionTest.php | 83 | ||||
-rw-r--r-- | tests/support/TestController.php | 18 |
3 files changed, 126 insertions, 29 deletions
diff --git a/src/Controller/RouteAction.php b/src/Controller/RouteAction.php index aa6a710..dabd501 100644 --- a/src/Controller/RouteAction.php +++ b/src/Controller/RouteAction.php @@ -2,6 +2,7 @@ namespace Jasny\Controller; +use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; /** @@ -10,26 +11,40 @@ use Psr\Http\Message\ResponseInterface; trait RouteAction { /** + * Get request, set for controller + * + * @return ServerRequestInterface + */ + abstract public function getRequest(); + + /** + * Get response. set for controller + * + * @return ResponseInterface + */ + abstract public function getResponse(); + + /** * Run the controller * * @return ResponseInterface */ public function run() { $request = $this->getRequest(); - if (!$request) { - throw new \RuntimeException("Request object is not set for controller"); - } - $route = $request->getAttribute('route'); - $method = $this->getActionMethod(isset($route->action) ? $route->action : null); + $method = $this->getActionMethod(isset($route->action) ? $route->action : 'default'); if (!method_exists($this, $method)) { - throw new \RuntimeException("No method $method in conrtoller to route to"); + return $this->setResponseError(404, 'Not Found'); } - $args = isset($route->args) ? - $route->args : - $this->getFunctionArgs($route, new \ReflectionMethod($this, $method)); + try { + $args = isset($route->args) ? + $route->args : + $this->getFunctionArgs($route, new \ReflectionMethod($this, $method)); + } catch (\RuntimeException $e) { + return $this->setResponseError(400, 'Bad Request'); + } $response = call_user_func_array([$this, $method], $args); @@ -67,8 +82,8 @@ trait RouteAction } else { if (!$param->isOptional()) { $fn = $refl instanceof \ReflectionMethod - ? $refl->getDeclaringClass()->getName() . ':' . $refl->getName() - : $refl->getName(); + ? $refl->class . ':' . $refl->name + : $refl->name; throw new \RuntimeException("Missing argument '$key' for $fn()"); } @@ -81,5 +96,22 @@ trait RouteAction return $args; } + + /** + * Set response to error state + * + * @param int $code + * @param string $message + * @return ResponseInterface + */ + protected function setResponseError($code, $message) + { + $response = $this->getResponse(); + + $errorResponse = $response->withStatus($code); + $errorResponse->getBody()->write($message); + + return $errorResponse; + } } diff --git a/tests/Controller/RouteActionTest.php b/tests/Controller/RouteActionTest.php index 30f1923..edc4bd7 100644 --- a/tests/Controller/RouteActionTest.php +++ b/tests/Controller/RouteActionTest.php @@ -5,16 +5,20 @@ require_once dirname(__DIR__) . '/support/TestController.php'; use Jasny\Controller\RouteAction; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamInterface; +/** + * @covers Jasny\Controller\RouteAction + */ class RouteActionTest extends PHPUnit_Framework_TestCase { /** * Test running controller action * - * @dataProvider runProvider - * @param [type] $[name] [<description>] + * @dataProvider runPositiveProvider + * @param object $route */ - public function testRun($route, $positive) + public function testRunPositive($route) { $controller = new TestController(); $request = $this->createMock(ServerRequestInterface::class); @@ -22,42 +26,85 @@ class RouteActionTest extends PHPUnit_Framework_TestCase $request->method('getAttribute')->with($this->equalTo('route'))->will($this->returnValue($route)); - if (!$positive) $this->expectException(\RuntimeException::class); - $result = $controller($request, $response); $args = !empty($route->args) ? $route->args : [$route->param1, isset($route->param2) ? $route->param2 : 'defaultValue']; $this->assertEquals(get_class($response), get_class($result), "Controller should return 'ResponseInterface' instance"); - $this->assertTrue($result->actionCalled, "Controller action was not called"); $this->assertEquals($args[0], $result->param1, "First route parameter was not passed correctly"); $this->assertEquals($args[1], $result->param2, "Second route parameter was not passed correctly"); + + if (isset($route->action)) { + $this->assertTrue($result->actionCalled, "Controller action was not called"); + $this->assertFalse(isset($result->defaultActionCalled), "Controller default action was called"); + } else { + $this->assertTrue($result->defaultActionCalled, "Controller default action was not called"); + $this->assertFalse(isset($result->actionCalled), "Controller non-default action was called"); + } } /** * Provide data for testing run method */ - public function runProvider() + public function runPositiveProvider() { return [ - [(object)['controller' => 'TestController'], false], - [(object)['controller' => 'TestController', 'action' => 'nonExistMethod'], false], - [(object)['controller' => 'TestController', 'action' => 'test-run'], false], - [(object)['controller' => 'TestController', 'action' => 'test-run', 'param2' => 'value2'], false], - [(object)['controller' => 'TestController', 'action' => 'test-run', 'param1' => 'value1'], true], - [(object)['controller' => 'TestController', 'action' => 'test-run', 'param1' => 'value1', 'param2' => 'value2'], true], - [(object)['controller' => 'TestController', 'action' => 'test-run', 'args' => ['value1', 'value2']], true] + [(object)['controller' => 'TestController', 'param1' => 'value1']], + [(object)['controller' => 'TestController', 'param1' => 'value1', 'param2' => 'value2']], + [(object)['controller' => 'TestController', 'args' => ['value1', 'value2']]], + [(object)['controller' => 'TestController', 'action' => 'test-run', 'param1' => 'value1']], + [(object)['controller' => 'TestController', 'action' => 'test-run', 'param1' => 'value1', 'param2' => 'value2']], + [(object)['controller' => 'TestController', 'action' => 'test-run', 'args' => ['value1', 'value2']]] ]; } /** - * Test running controller without setting request and response + * Test running controller action + * + * @dataProvider runNegativeProvider + * @param object $route + * @param int $errorCode + * @param string $errorMessage */ - public function testRunNoRequest() + public function testRunNegative($route, $errorCode, $errorMessage) { $controller = new TestController(); + $request = $this->createMock(ServerRequestInterface::class); + $response = $this->createMock(ResponseInterface::class); - $this->expectException(\RuntimeException::class); + $request->method('getAttribute')->with($this->equalTo('route'))->will($this->returnValue($route)); + + $this->expectResponseError($response, $errorCode, $errorMessage); + + $result = $controller($request, $response); + + $this->assertEquals(get_class($response), get_class($result), "Controller should return 'ResponseInterface' instance"); + } + + /** + * Provide data for testing run method + */ + public function runNegativeProvider() + { + return [ + [(object)['controller' => 'TestController', 'action' => 'nonExistMethod'], 404, 'Not Found'], + [(object)['controller' => 'TestController', 'action' => 'test-run'], 400, 'Bad Request'], + [(object)['controller' => 'TestController', 'action' => 'test-run', 'param2' => 'value2'], 400, 'Bad Request'] + ]; + } + + /** + * Expect that response will be set to error state + * + * @param ResponseInterface $response + * @param int $code + * @param string $message + */ + public function expectResponseError($response, $code, $message) + { + $stream = $this->createMock(StreamInterface::class); + $stream->expects($this->once())->method('write')->with($this->equalTo($message)); - $controller->run(); + $response->expects($this->once())->method('getBody')->will($this->returnValue($stream)); + $response->expects($this->once())->method('withStatus')->with($this->equalTo($code))->will($this->returnSelf()); } } diff --git a/tests/support/TestController.php b/tests/support/TestController.php index a2f5b51..e0bdb7b 100644 --- a/tests/support/TestController.php +++ b/tests/support/TestController.php @@ -29,4 +29,22 @@ class TestController extends Controller return $response; } + + /** + * Test action for executing router + * + * @param mixed $param1 + * @param mixed $param2 + * @return ResponseInterface + */ + public function defaultAction($param1, $param2 = 'defaultValue') + { + $response = $this->getResponse(); + + $response->defaultActionCalled = true; + $response->param1 = $param1; + $response->param2 = $param2; + + return $response; + } } |