summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorminstel <minstel@yandex.ru>2016-10-21 00:07:38 +0300
committerminstel <minstel@yandex.ru>2016-10-21 00:07:38 +0300
commitf07a3e06e2338ac481998ed47d98073c806cc268 (patch)
tree74ac4bf2434c311da2f59bf7287acaaf47dfb381
parent18da10400c02d945632c8c7dd49d78d19d9fd9a0 (diff)
downloadcontroller-f07a3e06e2338ac481998ed47d98073c806cc268.zip
controller-f07a3e06e2338ac481998ed47d98073c806cc268.tar.gz
controller-f07a3e06e2338ac481998ed47d98073c806cc268.tar.bz2
Fixes
-rw-r--r--src/Controller/RouteAction.php54
-rw-r--r--tests/Controller/RouteActionTest.php83
-rw-r--r--tests/support/TestController.php18
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;
+ }
}