summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold Daniels <arnold@jasny.net>2016-11-18 18:28:24 +0100
committerArnold Daniels <arnold@jasny.net>2016-11-18 18:28:24 +0100
commit43c6d835943b322c036e9ee47800d694cb6bb5de (patch)
treef56809890b4e65c2f4790fbd8be9593a3538a72c
parent934b380f473b4e85e807f07d6bf516f4e227e112 (diff)
downloadcontroller-43c6d835943b322c036e9ee47800d694cb6bb5de.zip
controller-43c6d835943b322c036e9ee47800d694cb6bb5de.tar.gz
controller-43c6d835943b322c036e9ee47800d694cb6bb5de.tar.bz2
Refactored CheckRequest and CheckResponse traits
WIP Controller\Output Restructuring the tests (one test per trait)
-rw-r--r--phpunit.xml.dist2
-rw-r--r--src/Controller.php3
-rw-r--r--src/Controller/CheckResponse.php23
-rw-r--r--src/Controller/Input.php13
-rw-r--r--src/Controller/Output.php (renamed from src/Controller/Respond.php)125
-rw-r--r--tests/Controller/CheckRequestTest.php87
-rw-r--r--tests/Controller/CheckResponseTest.php53
-rw-r--r--tests/Controller/OutputTest.php499
-rw-r--r--tests/Controller/RouteActionTest.php3
-rw-r--r--tests/Controller/Session/FlashTest.php (renamed from tests/FlashTest.php)0
-rw-r--r--tests/Controller/SessionTest.php750
-rw-r--r--tests/Controller/View/TwigTest.php (renamed from tests/View/TwigTest.php)0
-rw-r--r--tests/ControllerTest.php723
-rw-r--r--tests/bootstrap.php4
-rw-r--r--tests/support/RouteActionController.php13
-rw-r--r--tests/support/SessionController.php13
-rw-r--r--tests/support/TestController.php50
-rw-r--r--tests/support/TestHelper.php27
18 files changed, 1592 insertions, 796 deletions
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 1861d7c..e8a1ac3 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -2,7 +2,7 @@
<phpunit
colors="true"
- bootstrap="vendor/autoload.php"
+ bootstrap="tests/bootstrap.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
diff --git a/src/Controller.php b/src/Controller.php
index b3014f9..e928339 100644
--- a/src/Controller.php
+++ b/src/Controller.php
@@ -10,7 +10,8 @@ use Psr\Http\Message\ResponseInterface;
*/
abstract class Controller
{
- use Controller\Respond,
+ use Controller\Input,
+ Controller\Output,
Controller\CheckRequest,
Controller\CheckResponse;
diff --git a/src/Controller/CheckResponse.php b/src/Controller/CheckResponse.php
index 7c02d46..7509778 100644
--- a/src/Controller/CheckResponse.php
+++ b/src/Controller/CheckResponse.php
@@ -18,6 +18,17 @@ trait CheckResponse
/**
+ * Check if response is a 1xx informational
+ *
+ * @return boolean
+ */
+ public function isInformational()
+ {
+ $code = $this->getResponse()->getStatusCode() ?: 200;
+ return $code >= 100 && $code < 200;
+ }
+
+ /**
* Check if response is 2xx succesful, or empty
*
* @return boolean
@@ -25,8 +36,7 @@ trait CheckResponse
public function isSuccessful()
{
$code = $this->getResponse()->getStatusCode() ?: 200;
-
- return !$code || ($code >= 200 && $code < 300);
+ return $code >= 200 && $code < 300;
}
/**
@@ -37,7 +47,6 @@ trait CheckResponse
public function isRedirection()
{
$code = $this->getResponse()->getStatusCode() ?: 200;
-
return $code >= 300 && $code < 400;
}
@@ -49,7 +58,6 @@ trait CheckResponse
public function isClientError()
{
$code = $this->getResponse()->getStatusCode() ?: 200;
-
return $code >= 400 && $code < 500;
}
@@ -60,8 +68,9 @@ trait CheckResponse
*/
public function isServerError()
{
- return $this->getResponse()->getStatusCode() ?: 200 >= 500;
- }
+ $code = $this->getResponse()->getStatusCode() ?: 200;
+ return $code >= 500 && $code < 600;
+ }
/**
* Check if response is 4xx or 5xx error
@@ -71,5 +80,5 @@ trait CheckResponse
public function isError()
{
return $this->isClientError() || $this->isServerError();
- }
+ }
}
diff --git a/src/Controller/Input.php b/src/Controller/Input.php
new file mode 100644
index 0000000..7f5ce35
--- /dev/null
+++ b/src/Controller/Input.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Jasny\Controller;
+
+use Psr\Http\Message\ServerRequestInterface;
+
+/**
+ * Methods for a controller to read from the request
+ */
+trait Input
+{
+
+}
diff --git a/src/Controller/Respond.php b/src/Controller/Output.php
index 02b2cfb..a6160f1 100644
--- a/src/Controller/Respond.php
+++ b/src/Controller/Output.php
@@ -8,9 +8,14 @@ use Dflydev\ApacheMimeTypes\PhpRepository as ApacheMimeTypes;
/**
* Methods for a controller to send a response
*/
-trait Respond
+trait Output
{
/**
+ * @var string
+ */
+ protected $defaultFormat;
+
+ /**
* Get response. set for controller
*
* @return ResponseInterface
@@ -33,6 +38,17 @@ trait Respond
/**
+ * If a non scalar value is passed without an format, use this format
+ *
+ * @param string $format Format by extention or MIME
+ */
+ public function byDefaultSerializeTo($format)
+ {
+ $this->defaultFormat = $format;
+ }
+
+
+ /**
* Set a response header
*
* @param string $header
@@ -96,40 +112,66 @@ trait Respond
}
/**
- * Response with created 201 code, and optionaly redirect to created location
+ * Response with created 201 code, and optionally the created location
*
* @param string $location Url of created resource
*/
- public function created($location = '')
+ public function created($location = null)
{
$this->respondWith(201);
- if ($location) {
+ if (!empty($location)) {
$this->setResponseHeader('Location', $location);
}
}
/**
+ * Response with 203 Accepted
+ */
+ public function accepted()
+ {
+ $this->respondWith(202);
+ }
+
+ /**
* Response with 204 No Content
+ *
+ * @param int $code 204 (No Content) or 205 (Reset Content)
*/
- public function noContent()
+ public function noContent($code = 204)
{
- $this->respondWith(204);
+ $this->respondWith($code);
+ }
+
+ /**
+ * Respond with a 206 Partial content with `Content-Range` header
+ *
+ * @param int $rangeFrom Beginning of the range in bytes
+ * @param int $rangeTo End of the range in bytes
+ * @param int $totalSize Total size in bytes
+ */
+ public function partialContent($rangeFrom, $rangeTo, $totalSize)
+ {
+ $this->respondWith(206);
+
+ $this->setResponseHeader('Content-Range', "bytes {$rangeFrom}-{$rangeTo}/{$totalSize}");
+ $this->setResponseHeader('Content-Length', $rangeTo - $rangeFrom);
}
+
/**
- * Redirect to url
+ * Redirect to url and output a short message with the link
*
* @param string $url
- * @param int $code 301 (Moved Permanently), 303 (See Other) or 307 (Temporary Redirect)
+ * @param int $code 301 (Moved Permanently), 302 (Found), 303 (See Other) or 307 (Temporary Redirect)
*/
public function redirect($url, $code = 303)
{
- $this->respondWith($code, 'text/html');
+ $this->respondWith($code);
$this->setResponseHeader('Location', $url);
$urlHtml = htmlentities($url);
- $this->output('You are being redirected to <a href="' . $urlHtml . '">' . $urlHtml . '</a>');
+ $this->output('You are being redirected to <a href="' . $urlHtml . '">' . $urlHtml . '</a>', 'text/html');
}
/**
@@ -141,6 +183,14 @@ trait Respond
{
$this->redirect($this->getLocalReferer() ?: '/');
}
+
+ /**
+ * Respond with 304 Not Modified
+ */
+ public function notModified()
+ {
+ $this->respondWith(304);
+ }
/**
@@ -188,7 +238,7 @@ trait Respond
*
* @param string $message
*/
- public function forbidden($message = "Forbidden")
+ public function forbidden($message = "Access denied")
{
$this->respondWith(403);
$this->output($message);
@@ -198,7 +248,7 @@ trait Respond
* Respond with 404 Not Found
*
* @param string $message
- * @param int $code HTTP status code (404 or 405)
+ * @param int $code 404 (Not Found), 405 (Method not allowed) or 410 (Gone)
*/
public function notFound($message = "Not found", $code = 404)
{
@@ -273,16 +323,53 @@ trait Respond
*/
protected function serializeData($data, $contentType)
{
- if ($contentType == 'json') {
- return (is_string($data) && (json_decode($data) !== null || !json_last_error()))
- ? $data : json_encode($data);
+ if (is_scalar($data)) {
+ return (string)$data;
+ }
+
+ $format = preg_replace('~^.+/~', '', $contentType);
+ $method = 'serializeDataTo' . $format;
+
+ if (method_exists($this, $method)) {
+ return $this->$method($data);
+ }
+
+ if (is_object($data) && method_exists($data, '__toString')) {
+ return (string)$data;
+ }
+
+ throw new \Exception("Unable to serialize data to $format");
+ }
+
+ /**
+ * Serialize data to JSON
+ *
+ * @param mixed $data
+ * @return string
+ */
+ private function serializeDataToJson($data)
+ {
+ return json_encode($data);
+ }
+
+ /**
+ * Serialize data to XML
+ *
+ * @param mixed $data
+ * @return string
+ */
+ private function serializeDataToXml($data)
+ {
+ if ($data instanceof \SimpleXMLElement) {
+ return $data->asXML();
}
- if (!is_scalar($data)) {
- throw new \Exception("Unable to serialize data to {$contentType}");
+ if ($data instanceof \DOMNode) {
+ return $data->ownerDocument->saveXML($data);
}
- return $data;
+ $type = (is_object($data) ? get_class($data) . ' ' : '') . gettype($data);
+ throw new \Exception("Unable to serialize $type to XML");
}
/**
@@ -300,7 +387,7 @@ trait Respond
$this->setResponseHeader('Content-Type', $contentType);
}
- $content = $this->serializeData($data, $contentType);
+ $content = $this->serializeData($data, $format);
$this->getResponse()->getBody()->write($content);
}
diff --git a/tests/Controller/CheckRequestTest.php b/tests/Controller/CheckRequestTest.php
new file mode 100644
index 0000000..8ba2e23
--- /dev/null
+++ b/tests/Controller/CheckRequestTest.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace Jasny\Controller;
+
+use Psr\Http\Message\ServerRequestInterface;
+use Jasny\Controller\TestHelper;
+
+/**
+ * @covers Jasny\Controller\CheckRequest
+ */
+class CheckRequestTest extends \PHPUnit_Framework_TestCase
+{
+ use TestHelper;
+
+ /**
+ * Provide data for testing functions that determine request method
+ *
+ * @return array
+ */
+ public function requestMethodProvider()
+ {
+ return [
+ ['GET'], ['POST'], ['PUT'], ['DELETE'], ['HEAD']
+ ];
+ }
+
+ /**
+ * Test functions that check request method
+ *
+ * @dataProvider requestMethodProvider
+ * @param string $method
+ */
+ public function testRequestMethod($method)
+ {
+ $request = $this->createMock(ServerRequestInterface::class);
+ $request->method('getMethod')->will($this->returnValue($method));
+
+ $controller = $this->getController(['getRequest']);
+ $controller->method('getRequest')->will($this->returnValue($request));
+
+ $this->assertEquals($method === 'GET', $controller->isGetRequest());
+ $this->assertEquals($method === 'POST', $controller->isPostRequest());
+ $this->assertEquals($method === 'PUT', $controller->isPutRequest());
+ $this->assertEquals($method === 'DELETE', $controller->isDeleteRequest());
+ $this->assertEquals($method === 'HEAD', $controller->isHeadRequest());
+ }
+
+ /**
+ * Provide data fot testing 'getLocalReferer' function
+ *
+ * @return array
+ */
+ public function localRefererProvider()
+ {
+ return [
+ ['http://google.com/path', 'example.com', null],
+ ['http://example.com/', 'example.com', '/'],
+ ['http://www.example.com/path', 'example.com', null],
+ ];
+ }
+
+ /**
+ * Test 'getLocalReferer' funtion
+ *
+ * @dataProvider localRefererProvider
+ * @param string $referer
+ * @param string $host
+ * @param boolean $local
+ */
+ public function testLocalReferer($referer, $host, $local)
+ {
+ $request = $this->createMock(ServerRequestInterface::class);
+ $request->expects($this->exactly(2))->method('getHeaderLine')->withConsecutive(
+ [$this->equalTo('HTTP_REFERER')],
+ [$this->equalTo('HTTP_HOST')]
+ )->willReturnOnConsecutiveCalls($referer, $host);
+
+ $controller = $this->getController(['getRequest']);
+ $controller->method('getRequest')->will($this->returnValue($request));
+
+ $result = $controller->getLocalReferer();
+
+ $local ?
+ $this->assertEquals($referer, $result, "Local referer should be returned") :
+ $this->assertEquals('', $result, "Local referer should not be returned");
+ }
+}
diff --git a/tests/Controller/CheckResponseTest.php b/tests/Controller/CheckResponseTest.php
new file mode 100644
index 0000000..e43b5b5
--- /dev/null
+++ b/tests/Controller/CheckResponseTest.php
@@ -0,0 +1,53 @@
+<?php
+
+use Psr\Http\Message\ResponseInterface;
+use Jasny\Controller\TestHelper;
+
+/**
+ * @covers Jasny\Controller\CheckResponse
+ */
+class ControllerTest extends PHPUnit_Framework_TestCase
+{
+ use TestHelper;
+
+ /**
+ * Provide data for testing status methods
+ *
+ * @return array
+ */
+ public function responseStatusProvider()
+ {
+ return [
+ [null, 'successful'],
+ [100, 'informational'], [199, 'informational'],
+ [200, 'successful'], [201, 'successful'], [299, 'successful'],
+ [300, 'redirect'], [304, 'redirect'], [399, 'redirect'],
+ [400, 'client error'], [403, 'client error'], [499, 'client error'],
+ [500, 'server error'], [503, 'server error'],
+ [999, 'unkown']
+ ];
+ }
+
+ /**
+ * Test functions that check response status code
+ * @dataProvider responseStatusProvider
+ *
+ * @param int $code status code
+ * @param string $type
+ */
+ public function testResponseStatus($code, $type)
+ {
+ $response = $this->createMock(ResponseInterface::class);
+ $response->method('getStatusCode')->will($this->returnValue($code));
+
+ $controller = $this->getController(['getResponse']);
+ $controller->method('getResponse')->willReturn($response);
+
+ $this->assertSame($type === 'informational', $controller->isInformational(), 'isInformational');
+ $this->assertSame($type === 'successful', $controller->isSuccessful(), 'isSuccessful');
+ $this->assertSame($type === 'redirect', $controller->isRedirection(), 'isRedirection');
+ $this->assertSame($type === 'client error', $controller->isClientError(), 'isClientError');
+ $this->assertSame($type === 'server error', $controller->isServerError(), 'isServerError');
+ $this->assertSame(in_array($type, ['client error', 'server error']), $controller->isError(), 'isError');
+ }
+}
diff --git a/tests/Controller/OutputTest.php b/tests/Controller/OutputTest.php
new file mode 100644
index 0000000..9952d6f
--- /dev/null
+++ b/tests/Controller/OutputTest.php
@@ -0,0 +1,499 @@
+<?php
+
+namespace Jasny\Controller;
+
+use Jasny\Controller;
+use Jasny\Flash;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+use Jasny\Controller\TestHelper;
+
+/**
+ * @covers Jasny\Controller\Output
+ */
+class OutputTest extends \PHPUnit_Framework_TestCase
+{
+ use TestHelper;
+
+ /**
+ * Provide data for testing error messages functions
+ *
+ * @return array
+ */
+ public function statusProvider()
+ {
+ return [
+ ['ok', 200],
+ ['created', 201],
+ ['accepted', 202],
+ ['noContent', 204],
+ ['partialContent', 206],
+
+ ['redirect', 303, ['example.com']],
+ ['back', 303],
+ ['notModified', 304],
+
+ ['badRequest', 400],
+ ['requireAuth', 401],
+ ['requireLogin', 401],
+ ['paymentRequired', 402],
+ ['forbidden', 403],
+ ['notFound', 404],
+ ['conflict', 409],
+ ['tooManyRequests', 429]
+ ];
+ }
+
+ /**
+ * Test functions that deal with error messages
+ * @dataProvider statusProvider
+ *
+ * @param string $function
+ * @param int $code Status code
+ * @param array $args
+ */
+ public function testImplicitStatus($function, $code, $args = [])
+ {
+ $response = $this->createMock(ResponseInterface::class);
+ $response->expects($this->once())->method('withStatus')->with($code)->willReturnSelf();
+ $response->expects($this->any())->method('withHeader')->willReturnSelf();
+
+ $controller = $this->getController(['getResponse']);
+ $controller->method('getResponse')->willReturn($response);
+
+ $controller->$function(...$args);
+ }
+
+
+ /**
+ * Test functions that deal with error messages
+ * @dataProvider statusProvider
+ *
+ * @param string $function
+ * @param int $code Status code
+ */
+ public function testImplicitStatusMessage($function, $code, $args)
+ {
+ $message = 'Test message';
+
+ $stream = $this->createMock(StreamInterface::class);
+ $stream->expects($this->once())->method('write')->with($message);
+
+ $response = $this->createMock(ResponseInterface::class);
+ $response->expects($this->once())->method('withStatus')->with($code)->willReturnSelf();
+ $response->expects($this->once())->method('getBody')->willReturn($stream);
+
+ $controller = $this->getController(['getResponse']);
+ $controller->method('getResponse')->willReturn($response);
+
+
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Test setting flash
+ *
+ * @dataProvider flashProvider
+ * @param object $data
+ */
+ public function testFlash($data)
+ {
+ $controller = $this->getMockBuilder(Controller::class)->disableOriginalConstructor()->getMockForAbstractClass();
+
+ $flash = $controller->flash();
+ $this->assertInstanceOf(Flash::class, $flash, "Flash is not set");
+ $this->assertEmpty($flash->get(), "Flash data should be empty");
+
+ $flash = $controller->flash($data->type, $data->message);
+ $this->assertInstanceOf(Flash::class, $flash, "Flash is not set");
+ $this->assertEquals($data, $flash->get(), "Flash data is incorrect");
+
+ $flash = $controller->flash();
+ $this->assertInstanceOf(Flash::class, $flash, "Flash is not set");
+ $this->assertEquals($data, $flash->get(), "Flash data is incorrect");
+
+ $flash->clear();
+ }
+
+ /**
+ * Test setting flash
+ *
+ * @return array
+ */
+ public function flashProvider()
+ {
+ return [
+ [(object)['type' => 'test_type', 'message' => 'Test message']]
+ ];
+ }
+
+ /**
+ * Test respondWith function
+ *
+ * @dataProvider respondWithProvider
+ * @param int|string $code
+ * @param string $format
+ * @param int $setCode Actual code that will be set in response
+ * @param string $contentType
+ */
+ public function testRespondWith($code, $format, $setCode, $contentType)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $this->expectResponseWith($response, $setCode, $contentType);
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->respondWith($code, $format);
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Test function respondWith
+ *
+ * @return array
+ */
+ public function respondWithProvider()
+ {
+ return [
+ [200, 'json', 200, 'application/json'],
+ [200, 'application/json', 200, 'application/json'],
+ [204, null, 204, null],
+ ['204 Created', null, 204, null],
+ ['json', null, null, 'application/json']
+ ];
+ }
+
+ /**
+ * Test functions that are simple wrappers around respondWith function
+ *
+ * @dataProvider respondWithWrappersProvider
+ * @param string $function
+ * @param int $code
+ */
+ public function testResponseWithWrappers($function, $code)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $this->expectResponseWith($response, $code);
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->{$function}();
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data for testing respondWith wrappers
+ *
+ * @return array
+ */
+ public function respondWithWrappersProvider()
+ {
+ return [
+ ['ok', 200],
+ ['noContent', 204]
+ ];
+ }
+
+ /**
+ * Test 'created' function
+ *
+ * @dataProvider createdProvider
+ * @param string $location
+ */
+ public function testCreated($location)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $response->expects($this->once())->method('withStatus')->with($this->equalTo(201))->will($this->returnSelf());
+ if ($location) {
+ $response->expects($this->once())->method('withHeader')->with($this->equalTo('Location'), $this->equalTo($location))->will($this->returnSelf());
+ }
+
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->created($location);
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data for testing 'created' function
+ *
+ * @return array
+ */
+ public function createdProvider()
+ {
+ return [
+ [''], ['/some-path/test']
+ ];
+ }
+
+ /**
+ * Test 'redirect' function
+ *
+ * @dataProvider redirectProvider
+ * @param string $url
+ * @param int $code
+ * @param boolean $default
+ */
+ public function testRedirect($url, $code, $default)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $this->expectRedirect($response, $url, $code);
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $default ?
+ $controller->redirect($url) :
+ $controller->redirect($url, $code);
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data for testing 'redirect' function
+ *
+ * @return array
+ */
+ public function redirectProvider()
+ {
+ return [
+ ['/test-url', 303, true],
+ ['/test-url', 301, false]
+ ];
+ }
+
+ /**
+ * Test 'requireLogin' function
+ *
+ * @dataProvider requireLoginProvider
+ * @param string $function
+ */
+ public function testRequireLogin($function)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $this->expectRedirect($response, '/401', 303);
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->{$function}();
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data for testing 'requireLogon' function
+ *
+ * @return array
+ */
+ public function requireLoginProvider()
+ {
+ return [
+ ['requireLogin'], ['requireAuth']
+ ];
+ }
+
+ /**
+ * Test 'getLocalReferer' funtion
+ *
+ * @dataProvider localRefererProvider
+ * @param string $referer
+ * @param string $host
+ * @param boolean $local
+ */
+ public function testLocalReferer($referer, $host, $local)
+ {
+ $controller = $this->getController(['getRequest']);
+ list($request) = $this->getRequests();
+
+ $this->expectLocalReferer($request, $referer, $host);
+ $controller->method('getRequest')->will($this->returnValue($request));
+
+ $result = $controller->getLocalReferer();
+
+ $local ?
+ $this->assertEquals($referer, $result, "Local referer should be returned") :
+ $this->assertEquals('', $result, "Local referer should not be returned");
+ }
+
+ /**
+ * Test 'back' function
+ *
+ * @dataProvider localRefererProvider
+ * @param string $referer
+ * @param string $host
+ * @param boolean $local
+ */
+ public function testBack($referer, $host, $local)
+ {
+ $controller = $this->getController(['getRequest', 'getResponse']);
+ list($request, $response) = $this->getRequests();
+
+ $this->expectLocalReferer($request, $referer, $host);
+ $this->expectRedirect($response, $local ? $referer : '/', 303);
+
+ $controller->method('getRequest')->will($this->returnValue($request));
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->back();
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data fot testing 'getLocalReferer' function
+ *
+ * @return array
+ */
+ public function localRefererProvider()
+ {
+ return [
+ ['http://not-local-host.com/path', 'local-host.com', false],
+ ['http://local-host.com/path', 'local-host.com', true]
+ ];
+ }
+
+ /**
+ * Expect for 'getLocalReferer' function to work correctly
+ *
+ * @param ServerRequestInterface $request
+ * @param string $referer
+ * @param string $host
+ */
+ public function expectLocalReferer($request, $referer, $host)
+ {
+ $request->expects($this->exactly(2))->method('getHeaderLine')->withConsecutive(
+ [$this->equalTo('HTTP_REFERER')],
+ [$this->equalTo('HTTP_HOST')]
+ )->will($this->returnCallback(function($header) use ($referer, $host) {
+ return $header === 'HTTP_REFERER' ? $referer : $host;
+ }));
+ }
+
+ /**
+ * Expect for redirect
+ *
+ * @param ResponseInterface $response
+ * @param string $url
+ * @param int $code
+ */
+ public function expectRedirect($response, $url, $code)
+ {
+ $stream = $this->createMock(StreamInterface::class);
+ $stream->expects($this->once())->method('write')->with($this->equalTo('You are being redirected to <a href="' . $url . '">' . $url . '</a>'));
+
+ $response->expects($this->once())->method('getBody')->will($this->returnValue($stream));
+ $response->expects($this->once())->method('withStatus')->with($this->equalTo($code))->will($this->returnSelf());
+ $response->expects($this->exactly(2))->method('withHeader')->withConsecutive(
+ [$this->equalTo('Content-Type'), $this->equalTo('text/html')],
+ [$this->equalTo('Location'), $this->equalTo($url)]
+ )->will($this->returnSelf());
+ }
+
+ /**
+ * Expect correct work of respondWith function
+ *
+ * @param ResponseInterface $response
+ * @param int $code
+ * @param string $contentType
+ */
+ public function expectResponseWith($response, $code, $contentType = null)
+ {
+ $code ?
+ $response->expects($this->once())->method('withStatus')->with($this->equalTo($code))->will($this->returnSelf()) :
+ $response->expects($this->never())->method('withStatus')->with($this->equalTo($code));
+
+ $contentType ?
+ $response->expects($this->once())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo($contentType))->will($this->returnSelf()) :
+ $response->expects($this->never())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo($contentType));
+ }
+
+ /**
+ * Expects that output will be set to content
+ *
+ * @param ResponseInterface $response
+ * @param string $content
+ * @param string $contentType
+ */
+ public function expectOutput($response, $content, $contentType)
+ {
+ $stream = $this->createMock(StreamInterface::class);
+ $stream->expects($this->once())->method('write')->with($this->equalTo($content));
+
+ $response->expects($this->once())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo($contentType))->will($this->returnSelf());
+ $response->expects($this->once())->method('getBody')->will($this->returnValue($stream));
+ }
+
+ /**
+ * Provide data for testing output
+ *
+ * @return array
+ */
+ public function outputProvider()
+ {
+ $xml = simplexml_load_string(
+ "<?xml version='1.0'?>
+ <document>
+ <tag1>Test tag</tag1>
+ <tag2>Test</tag2>
+ </document>"
+ );
+
+ return [
+ ['test_string', 'text', 'text/plain'],
+ ['javascript:test_call();', 'js', 'application/javascript'],
+ ['test {}', 'css', 'text/css'],
+ ['{ "testKey": "testValue" }', 'json', 'application/json'],
+ [['testKey' => 'testValue'], 'json', 'application/json'],
+ [$xml, 'xml', 'application/xml']
+ ];
+ }
+
+ /**
+ * Test output
+ *
+ * @dataProvider outputProvider
+ * @param mixed $data
+ * @param string $format
+ * @param string $contentType
+ */
+ public function testOutput($data, $format, $contentType)
+ {
+ $response = $this->createMock(ResponseInterface::class);
+
+ $controller = $this->getController(['getResponse']);
+ $controller->method('getResponse')->willReturn($response);
+
+ if (is_scalar($data)) {
+ $content = $data;
+ } elseif ($format === 'json') {
+ $content = json_encode($data);
+
+ if ($callback) $content = "$callback($content)";
+ } elseif ($format === 'xml') {
+ $content = $data->asXML();
+ }
+
+ $this->expectOutput($response, $content, $contentType);
+
+ if ($callback) {
+ $request->method('getQueryParams')->will($this->returnValue(['callback' => $callback]));
+ }
+
+ $controller->method('getRequest')->will($this->returnValue($request));
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->output($data, $format);
+
+ $this->assertEquals($result, $response, "Output should return response instance");
+ }
+}
diff --git a/tests/Controller/RouteActionTest.php b/tests/Controller/RouteActionTest.php
index edc4bd7..cd630e0 100644
--- a/tests/Controller/RouteActionTest.php
+++ b/tests/Controller/RouteActionTest.php
@@ -1,7 +1,6 @@
<?php
-require_once dirname(__DIR__) . '/support/TestController.php';
-
+use Jasny\Controller;
use Jasny\Controller\RouteAction;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
diff --git a/tests/FlashTest.php b/tests/Controller/Session/FlashTest.php
index c17c446..c17c446 100644
--- a/tests/FlashTest.php
+++ b/tests/Controller/Session/FlashTest.php
diff --git a/tests/Controller/SessionTest.php b/tests/Controller/SessionTest.php
new file mode 100644
index 0000000..b6a6b2d
--- /dev/null
+++ b/tests/Controller/SessionTest.php
@@ -0,0 +1,750 @@
+<?php
+
+use Jasny\Controller;
+use Jasny\Flash;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * @covers Jasny\Controller
+ */
+class ControllerTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * Get mock for controller
+ *
+ * @param array $methods Methods to mock
+ * @return Controller
+ */
+ public function getController($methods = [])
+ {
+ $builder = $this->getMockBuilder(Controller::class)->disableOriginalConstructor();
+ if ($methods) {
+ $builder->setMethods($methods);
+ }
+
+ return $builder->getMockForAbstractClass();
+ }
+
+ /**
+ * Test running controller
+ */
+ public function testInvoke()
+ {
+ $test = $this;
+ $controller = $this->getController();
+
+ $request = $this->createMock(ServerRequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
+ $finalResponse = $this->createMock(ResponseInterface::class);
+
+ $controller->expects($this->once())->method('run')
+ ->willReturnCallback(Closure::bind(function() use ($test, $request, $response, $finalResponse) {
+ $test->assertSame($request, $this->getRequest());
+ $test->assertSame($response, $this->getResponse());
+
+ return $finalResponse;
+ }, $controller, Controller::class));
+
+ $result = $controller($request, $response);
+
+ $this->assertEquals($finalResponse, $result);
+ }
+
+ /**
+ * Test response status functions if response object is not set
+ */
+ public function testResponseStatusEmptyResponse()
+ {
+ $controller = $this->getController();
+ $data = $this->getStatusCodesMap(null);
+
+ foreach ($data as $func => $value) {
+ $this->assertEquals($value, $controller->$func(), "Method '$func' returns incorrect value");
+ }
+ }
+
+ /**
+ * Test functions that check response status code
+ *
+ * @dataProvider responseStatusProvider
+ * @param int status code
+ */
+ public function testResponseStatus($code)
+ {
+ $controller = $this->getController();
+ list($request, $response) = $this->getRequests();
+ $response->method('getStatusCode')->will($this->returnValue($code));
+
+ $controller($request, $response);
+
+ $data = $this->getStatusCodesMap($code);
+
+ foreach ($data as $func => $value) {
+ $this->assertEquals($value, $controller->$func(), "Method '$func' returns incorrect value");
+ }
+
+ $this->assertEquals($data['isClientError'] || $data['isServerError'], $controller->isError()
+ , "Method 'isError' returns incorrect value");
+ }
+
+ /**
+ * Provide data for testing status methods
+ *
+ * @return array
+ */
+ public function responseStatusProvider()
+ {
+ return [
+ [null], [199],
+ [200], [201], [299],
+ [300], [304], [399],
+ [400], [403], [499],
+ [500], [503]
+ ];
+ }
+
+ /**
+ * Test functions that check request method
+ *
+ * @dataProvider requestMethodProvider
+ * @param string $method
+ */
+ public function testRequestMethod($method)
+ {
+ $controller = $this->getController();
+ list($request, $response) = $this->getRequests();
+ $request->method('getMethod')->will($this->returnValue($method));
+
+ $controller($request, $response);
+
+ $data = $this->getMethodsMap($method);
+
+ foreach ($data as $func => $value) {
+ $this->assertEquals($value, $controller->$func(), "Method '$func' returns incorrect value");
+ }
+ }
+
+ /**
+ * Provide data for testing functions that determine request method
+ *
+ * @return array
+ */
+ public function requestMethodProvider()
+ {
+ return [
+ ['GET'], ['POST'], ['PUT'], ['DELETE'], ['HEAD']
+ ];
+ }
+
+ /**
+ * Test encodeData method, positive tests
+ *
+ * @dataProvider encodeDataPositiveProvider
+ * @param mixed $data
+ * @param string $format
+ * @param string $callback Callback name for testing jsonp request
+ */
+ public function testEncodeDataPositive($data, $format, $callback = null)
+ {
+ $this->markTestSkipped();
+
+ $controller = $this->getController(['getRequest']);
+ list($request) = $this->getRequests();
+
+ if ($callback) {
+ $request->method('getQueryParams')->will($this->returnValue(['callback' => $callback]));
+ }
+
+ $controller->method('getRequest')->will($this->returnValue($request));
+
+ $result = $controller->encodeData($data, $format);
+ $expect = null;
+
+ if ($format === 'json') {
+ $expect = json_encode($data);
+
+ if ($callback) $expect = "$callback($expect)";
+ } else {
+ $expect = $data->asXML();
+ }
+
+ $this->assertNotEmpty($result, "Result should not be empty");
+ $this->assertEquals($expect, $result, "Data was not encoded correctly");
+ }
+
+ /**
+ * Provide data for testing encodeData method
+ *
+ * @return array
+ */
+ public function encodeDataPositiveProvider()
+ {
+ $xml = simplexml_load_string(
+ "<?xml version='1.0'?>
+ <document>
+ <tag1>Test tag</tag1>
+ <tag2>Test</tag2>
+ </document>"
+ );
+
+ return [
+ ['test_string', 'json'],
+ [['testKey' => 'testValue'], 'json'],
+ [['testKey' => 'testValue'], 'json', 'test_callback'],
+ ['', 'json'],
+ ['', 'json', 'test_callback'],
+ [$xml, 'xml']
+ ];
+ }
+
+ /**
+ * Test encodeData method, negative tests
+ *
+ * @dataProvider encodeDataNegativeProvider
+ * @param mixed $data
+ * @param string $format
+ */
+ public function testEncodeDataNegative($data, $format)
+ {
+ $this->markTestSkipped();
+
+ $controller = $this->getController(['getRequest']);
+ list($request) = $this->getRequests();
+
+ $controller->method('getRequest')->will($this->returnValue($request));
+ $this->expectException(\InvalidArgumentException::class);
+
+ $result = $controller->encodeData($data, $format);
+ }
+
+ /**
+ * Provide data for testing encodeData method
+ *
+ * @return array
+ */
+ public function encodeDataNegativeProvider()
+ {
+ return [
+ ['test_string', 'html'],
+ ['test_string', 'jpg']
+ ];
+ }
+
+ /**
+ * Test output
+ *
+ * @dataProvider outputProvider
+ * @param mixed $data
+ * @param string $format
+ * @param string $contentType
+ * @param string $callback Callback name for testing jsonp request
+ */
+ public function testOutput($data, $format, $contentType, $callback = '')
+ {
+ $controller = $this->getController(['getRequest', 'getResponse']);
+ list($request, $response) = $this->getRequests();
+
+ if (is_scalar($data)) {
+ $content = $data;
+ } elseif ($format === 'json') {
+ $content = json_encode($data);
+
+ if ($callback) $content = "$callback($content)";
+ } elseif ($format === 'xml') {
+ $content = $data->asXML();
+ }
+
+ $this->expectOutput($response, $content, $contentType);
+
+ if ($callback) {
+ $request->method('getQueryParams')->will($this->returnValue(['callback' => $callback]));
+ }
+
+ $controller->method('getRequest')->will($this->returnValue($request));
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->output($data, $format);
+
+ $this->assertEquals($result, $response, "Output should return response instance");
+ }
+
+ /**
+ * Provide data for testing output
+ *
+ * @return array
+ */
+ public function outputProvider()
+ {
+ $xml = simplexml_load_string(
+ "<?xml version='1.0'?>
+ <document>
+ <tag1>Test tag</tag1>
+ <tag2>Test</tag2>
+ </document>"
+ );
+
+ return [
+ ['test_string', 'text', 'text/plain'],
+ ['javascript:test_call();', 'js', 'application/javascript'],
+ ['test {}', 'css', 'text/css'],
+ ['test_string', 'json', 'application/json'],
+ [['testKey' => 'testValue'], 'json', 'application/json'],
+ [['testKey' => 'testValue'], 'json', 'application/json', 'test_callback'],
+ ['', 'json', 'application/json'],
+ ['', 'json', 'application/json', 'test_callback'],
+ [$xml, 'xml', 'application/xml']
+ ];
+ }
+
+ /**
+ * Test functions that deal with error messages
+ *
+ * @dataProvider errorMessagesProvider
+ * @param string $function
+ * @param int $code
+ * @param boolean $default Is code default for this function
+ */
+ public function testErrorMessages($function, $code, $default)
+ {
+ $message = 'Test message';
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $this->expectErrorMessage($response, $message, $code);
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $default ?
+ $controller->{$function}($message) :
+ $controller->{$function}($message, $code);
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data for testing error messages functions
+ *
+ * @return array
+ */
+ public function errorMessagesProvider()
+ {
+ return [
+ ['error', 400, true],
+ ['error', 403, false],
+ ['tooManyRequests', 429, true],
+ ['tooManyRequests', 400, false],
+ ['conflict', 409, true],
+ ['conflict', 403, false],
+ ['notFound', 404, true],
+ ['notFound', 400, false],
+ ['forbidden', 403, true],
+ ['forbidden', 409, false],
+ ['badRequest', 400, true],
+ ['badRequest', 403, false]
+ ];
+ }
+
+ /**
+ * Test setting flash
+ *
+ * @dataProvider flashProvider
+ * @param object $data
+ */
+ public function testFlash($data)
+ {
+ $controller = $this->getMockBuilder(Controller::class)->disableOriginalConstructor()->getMockForAbstractClass();
+
+ $flash = $controller->flash();
+ $this->assertInstanceOf(Flash::class, $flash, "Flash is not set");
+ $this->assertEmpty($flash->get(), "Flash data should be empty");
+
+ $flash = $controller->flash($data->type, $data->message);
+ $this->assertInstanceOf(Flash::class, $flash, "Flash is not set");
+ $this->assertEquals($data, $flash->get(), "Flash data is incorrect");
+
+ $flash = $controller->flash();
+ $this->assertInstanceOf(Flash::class, $flash, "Flash is not set");
+ $this->assertEquals($data, $flash->get(), "Flash data is incorrect");
+
+ $flash->clear();
+ }
+
+ /**
+ * Test setting flash
+ *
+ * @return array
+ */
+ public function flashProvider()
+ {
+ return [
+ [(object)['type' => 'test_type', 'message' => 'Test message']]
+ ];
+ }
+
+ /**
+ * Test respondWith function
+ *
+ * @dataProvider respondWithProvider
+ * @param int|string $code
+ * @param string $format
+ * @param int $setCode Actual code that will be set in response
+ * @param string $contentType
+ */
+ public function testRespondWith($code, $format, $setCode, $contentType)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $this->expectResponseWith($response, $setCode, $contentType);
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->respondWith($code, $format);
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Test function respondWith
+ *
+ * @return array
+ */
+ public function respondWithProvider()
+ {
+ return [
+ [200, 'json', 200, 'application/json'],
+ [200, 'application/json', 200, 'application/json'],
+ [204, null, 204, null],
+ ['204 Created', null, 204, null],
+ ['json', null, null, 'application/json']
+ ];
+ }
+
+ /**
+ * Test functions that are simple wrappers around respondWith function
+ *
+ * @dataProvider respondWithWrappersProvider
+ * @param string $function
+ * @param int $code
+ */
+ public function testResponseWithWrappers($function, $code)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $this->expectResponseWith($response, $code);
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->{$function}();
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data for testing respondWith wrappers
+ *
+ * @return array
+ */
+ public function respondWithWrappersProvider()
+ {
+ return [
+ ['ok', 200],
+ ['noContent', 204]
+ ];
+ }
+
+ /**
+ * Test 'created' function
+ *
+ * @dataProvider createdProvider
+ * @param string $location
+ */
+ public function testCreated($location)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $response->expects($this->once())->method('withStatus')->with($this->equalTo(201))->will($this->returnSelf());
+ if ($location) {
+ $response->expects($this->once())->method('withHeader')->with($this->equalTo('Location'), $this->equalTo($location))->will($this->returnSelf());
+ }
+
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->created($location);
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data for testing 'created' function
+ *
+ * @return array
+ */
+ public function createdProvider()
+ {
+ return [
+ [''], ['/some-path/test']
+ ];
+ }
+
+ /**
+ * Test 'redirect' function
+ *
+ * @dataProvider redirectProvider
+ * @param string $url
+ * @param int $code
+ * @param boolean $default
+ */
+ public function testRedirect($url, $code, $default)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $this->expectRedirect($response, $url, $code);
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $default ?
+ $controller->redirect($url) :
+ $controller->redirect($url, $code);
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data for testing 'redirect' function
+ *
+ * @return array
+ */
+ public function redirectProvider()
+ {
+ return [
+ ['/test-url', 303, true],
+ ['/test-url', 301, false]
+ ];
+ }
+
+ /**
+ * Test 'requireLogin' function
+ *
+ * @dataProvider requireLoginProvider
+ * @param string $function
+ */
+ public function testRequireLogin($function)
+ {
+ $controller = $this->getController(['getResponse']);
+ list(, $response) = $this->getRequests();
+
+ $this->expectRedirect($response, '/401', 303);
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->{$function}();
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data for testing 'requireLogon' function
+ *
+ * @return array
+ */
+ public function requireLoginProvider()
+ {
+ return [
+ ['requireLogin'], ['requireAuth']
+ ];
+ }
+
+ /**
+ * Test 'getLocalReferer' funtion
+ *
+ * @dataProvider localRefererProvider
+ * @param string $referer
+ * @param string $host
+ * @param boolean $local
+ */
+ public function testLocalReferer($referer, $host, $local)
+ {
+ $controller = $this->getController(['getRequest']);
+ list($request) = $this->getRequests();
+
+ $this->expectLocalReferer($request, $referer, $host);
+ $controller->method('getRequest')->will($this->returnValue($request));
+
+ $result = $controller->getLocalReferer();
+
+ $local ?
+ $this->assertEquals($referer, $result, "Local referer should be returned") :
+ $this->assertEquals('', $result, "Local referer should not be returned");
+ }
+
+ /**
+ * Test 'back' function
+ *
+ * @dataProvider localRefererProvider
+ * @param string $referer
+ * @param string $host
+ * @param boolean $local
+ */
+ public function testBack($referer, $host, $local)
+ {
+ $controller = $this->getController(['getRequest', 'getResponse']);
+ list($request, $response) = $this->getRequests();
+
+ $this->expectLocalReferer($request, $referer, $host);
+ $this->expectRedirect($response, $local ? $referer : '/', 303);
+
+ $controller->method('getRequest')->will($this->returnValue($request));
+ $controller->method('getResponse')->will($this->returnValue($response));
+
+ $result = $controller->back();
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Provide data fot testing 'getLocalReferer' function
+ *
+ * @return array
+ */
+ public function localRefererProvider()
+ {
+ return [
+ ['http://not-local-host.com/path', 'local-host.com', false],
+ ['http://local-host.com/path', 'local-host.com', true]
+ ];
+ }
+
+ /**
+ * Expect for 'getLocalReferer' function to work correctly
+ *
+ * @param ServerRequestInterface $request
+ * @param string $referer
+ * @param string $host
+ */
+ public function expectLocalReferer($request, $referer, $host)
+ {
+ $request->expects($this->exactly(2))->method('getHeaderLine')->withConsecutive(
+ [$this->equalTo('HTTP_REFERER')],
+ [$this->equalTo('HTTP_HOST')]
+ )->will($this->returnCallback(function($header) use ($referer, $host) {
+ return $header === 'HTTP_REFERER' ? $referer : $host;
+ }));
+ }
+
+ /**
+ * Expect for redirect
+ *
+ * @param ResponseInterface $response
+ * @param string $url
+ * @param int $code
+ */
+ public function expectRedirect($response, $url, $code)
+ {
+ $stream = $this->createMock(StreamInterface::class);
+ $stream->expects($this->once())->method('write')->with($this->equalTo('You are being redirected to <a href="' . $url . '">' . $url . '</a>'));
+
+ $response->expects($this->once())->method('getBody')->will($this->returnValue($stream));
+ $response->expects($this->once())->method('withStatus')->with($this->equalTo($code))->will($this->returnSelf());
+ $response->expects($this->exactly(2))->method('withHeader')->withConsecutive(
+ [$this->equalTo('Content-Type'), $this->equalTo('text/html')],
+ [$this->equalTo('Location'), $this->equalTo($url)]
+ )->will($this->returnSelf());
+ }
+
+ /**
+ * Expect correct work of respondWith function
+ *
+ * @param ResponseInterface $response
+ * @param int $code
+ * @param string $contentType
+ */
+ public function expectResponseWith($response, $code, $contentType = null)
+ {
+ $code ?
+ $response->expects($this->once())->method('withStatus')->with($this->equalTo($code))->will($this->returnSelf()) :
+ $response->expects($this->never())->method('withStatus')->with($this->equalTo($code));
+
+ $contentType ?
+ $response->expects($this->once())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo($contentType))->will($this->returnSelf()) :
+ $response->expects($this->never())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo($contentType));
+ }
+
+ /**
+ * Expect for correct work of error message functions
+ *
+ * @param ResponseInterface $response
+ * @param string $message
+ * @param int $code
+ */
+ public function expectErrorMessage($response, $message, $code)
+ {
+ $stream = $this->createMock(StreamInterface::class);
+ $stream->expects($this->once())->method('write')->with($this->equalTo($message));
+
+ $response->expects($this->once())->method('withStatus')->with($this->equalTo($code))->will($this->returnSelf());
+ $response->expects($this->once())->method('getBody')->will($this->returnValue($stream));
+ }
+
+ /**
+ * Expects that output will be set to content
+ *
+ * @param ResponseInterface $response
+ * @param string $content
+ * @param string $contentType
+ */
+ public function expectOutput($response, $content, $contentType)
+ {
+ $stream = $this->createMock(StreamInterface::class);
+ $stream->expects($this->once())->method('write')->with($this->equalTo($content));
+
+ $response->expects($this->once())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo($contentType))->will($this->returnSelf());
+ $response->expects($this->once())->method('getBody')->will($this->returnValue($stream));
+ }
+
+ /**
+ * Get request and response instances
+ *
+ * @return array
+ */
+ public function getRequests()
+ {
+ return [
+ $this->createMock(ServerRequestInterface::class),
+ $this->createMock(ResponseInterface::class)
+ ];
+ }
+
+ /**
+ * Get map of status codes to states
+ *
+ * @param int $code
+ * @return []
+ */
+ public function getStatusCodesMap($code)
+ {
+ return [
+ 'isSuccessful' => !$code || ($code >= 200 && $code < 300),
+ 'isRedirection' => $code >= 300 && $code < 400,
+ 'isClientError' => $code >= 400 && $code < 500,
+ 'isServerError' => $code >= 500
+ ];
+ }
+
+ /**
+ * Get map of request methods
+ *
+ * @param string $method
+ * @return array
+ */
+ public function getMethodsMap($method)
+ {
+ return [
+ 'isGetRequest' => $method === 'GET',
+ 'isPostRequest' => $method === 'POST',
+ 'isPutRequest' => $method === 'PUT',
+ 'isDeleteRequest' => $method === 'DELETE',
+ 'isHeadRequest' => $method === 'HEAD'
+ ];
+ }
+}
diff --git a/tests/View/TwigTest.php b/tests/Controller/View/TwigTest.php
index 662681d..662681d 100644
--- a/tests/View/TwigTest.php
+++ b/tests/Controller/View/TwigTest.php
diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php
index b6a6b2d..3e3b39c 100644
--- a/tests/ControllerTest.php
+++ b/tests/ControllerTest.php
@@ -1,32 +1,19 @@
<?php
+namespace Jasny;
+
use Jasny\Controller;
-use Jasny\Flash;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\StreamInterface;
+use Jasny\Controller\TestHelper;
/**
* @covers Jasny\Controller
*/
-class ControllerTest extends PHPUnit_Framework_TestCase
+class ControllerTest extends \PHPUnit_Framework_TestCase
{
- /**
- * Get mock for controller
- *
- * @param array $methods Methods to mock
- * @return Controller
- */
- public function getController($methods = [])
- {
- $builder = $this->getMockBuilder(Controller::class)->disableOriginalConstructor();
- if ($methods) {
- $builder->setMethods($methods);
- }
-
- return $builder->getMockForAbstractClass();
- }
-
+ use TestHelper;
+
/**
* Test running controller
*/
@@ -40,7 +27,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase
$finalResponse = $this->createMock(ResponseInterface::class);
$controller->expects($this->once())->method('run')
- ->willReturnCallback(Closure::bind(function() use ($test, $request, $response, $finalResponse) {
+ ->willReturnCallback(\Closure::bind(function() use ($test, $request, $response, $finalResponse) {
$test->assertSame($request, $this->getRequest());
$test->assertSame($response, $this->getResponse());
@@ -51,700 +38,4 @@ class ControllerTest extends PHPUnit_Framework_TestCase
$this->assertEquals($finalResponse, $result);
}
-
- /**
- * Test response status functions if response object is not set
- */
- public function testResponseStatusEmptyResponse()
- {
- $controller = $this->getController();
- $data = $this->getStatusCodesMap(null);
-
- foreach ($data as $func => $value) {
- $this->assertEquals($value, $controller->$func(), "Method '$func' returns incorrect value");
- }
- }
-
- /**
- * Test functions that check response status code
- *
- * @dataProvider responseStatusProvider
- * @param int status code
- */
- public function testResponseStatus($code)
- {
- $controller = $this->getController();
- list($request, $response) = $this->getRequests();
- $response->method('getStatusCode')->will($this->returnValue($code));
-
- $controller($request, $response);
-
- $data = $this->getStatusCodesMap($code);
-
- foreach ($data as $func => $value) {
- $this->assertEquals($value, $controller->$func(), "Method '$func' returns incorrect value");
- }
-
- $this->assertEquals($data['isClientError'] || $data['isServerError'], $controller->isError()
- , "Method 'isError' returns incorrect value");
- }
-
- /**
- * Provide data for testing status methods
- *
- * @return array
- */
- public function responseStatusProvider()
- {
- return [
- [null], [199],
- [200], [201], [299],
- [300], [304], [399],
- [400], [403], [499],
- [500], [503]
- ];
- }
-
- /**
- * Test functions that check request method
- *
- * @dataProvider requestMethodProvider
- * @param string $method
- */
- public function testRequestMethod($method)
- {
- $controller = $this->getController();
- list($request, $response) = $this->getRequests();
- $request->method('getMethod')->will($this->returnValue($method));
-
- $controller($request, $response);
-
- $data = $this->getMethodsMap($method);
-
- foreach ($data as $func => $value) {
- $this->assertEquals($value, $controller->$func(), "Method '$func' returns incorrect value");
- }
- }
-
- /**
- * Provide data for testing functions that determine request method
- *
- * @return array
- */
- public function requestMethodProvider()
- {
- return [
- ['GET'], ['POST'], ['PUT'], ['DELETE'], ['HEAD']
- ];
- }
-
- /**
- * Test encodeData method, positive tests
- *
- * @dataProvider encodeDataPositiveProvider
- * @param mixed $data
- * @param string $format
- * @param string $callback Callback name for testing jsonp request
- */
- public function testEncodeDataPositive($data, $format, $callback = null)
- {
- $this->markTestSkipped();
-
- $controller = $this->getController(['getRequest']);
- list($request) = $this->getRequests();
-
- if ($callback) {
- $request->method('getQueryParams')->will($this->returnValue(['callback' => $callback]));
- }
-
- $controller->method('getRequest')->will($this->returnValue($request));
-
- $result = $controller->encodeData($data, $format);
- $expect = null;
-
- if ($format === 'json') {
- $expect = json_encode($data);
-
- if ($callback) $expect = "$callback($expect)";
- } else {
- $expect = $data->asXML();
- }
-
- $this->assertNotEmpty($result, "Result should not be empty");
- $this->assertEquals($expect, $result, "Data was not encoded correctly");
- }
-
- /**
- * Provide data for testing encodeData method
- *
- * @return array
- */
- public function encodeDataPositiveProvider()
- {
- $xml = simplexml_load_string(
- "<?xml version='1.0'?>
- <document>
- <tag1>Test tag</tag1>
- <tag2>Test</tag2>
- </document>"
- );
-
- return [
- ['test_string', 'json'],
- [['testKey' => 'testValue'], 'json'],
- [['testKey' => 'testValue'], 'json', 'test_callback'],
- ['', 'json'],
- ['', 'json', 'test_callback'],
- [$xml, 'xml']
- ];
- }
-
- /**
- * Test encodeData method, negative tests
- *
- * @dataProvider encodeDataNegativeProvider
- * @param mixed $data
- * @param string $format
- */
- public function testEncodeDataNegative($data, $format)
- {
- $this->markTestSkipped();
-
- $controller = $this->getController(['getRequest']);
- list($request) = $this->getRequests();
-
- $controller->method('getRequest')->will($this->returnValue($request));
- $this->expectException(\InvalidArgumentException::class);
-
- $result = $controller->encodeData($data, $format);
- }
-
- /**
- * Provide data for testing encodeData method
- *
- * @return array
- */
- public function encodeDataNegativeProvider()
- {
- return [
- ['test_string', 'html'],
- ['test_string', 'jpg']
- ];
- }
-
- /**
- * Test output
- *
- * @dataProvider outputProvider
- * @param mixed $data
- * @param string $format
- * @param string $contentType
- * @param string $callback Callback name for testing jsonp request
- */
- public function testOutput($data, $format, $contentType, $callback = '')
- {
- $controller = $this->getController(['getRequest', 'getResponse']);
- list($request, $response) = $this->getRequests();
-
- if (is_scalar($data)) {
- $content = $data;
- } elseif ($format === 'json') {
- $content = json_encode($data);
-
- if ($callback) $content = "$callback($content)";
- } elseif ($format === 'xml') {
- $content = $data->asXML();
- }
-
- $this->expectOutput($response, $content, $contentType);
-
- if ($callback) {
- $request->method('getQueryParams')->will($this->returnValue(['callback' => $callback]));
- }
-
- $controller->method('getRequest')->will($this->returnValue($request));
- $controller->method('getResponse')->will($this->returnValue($response));
-
- $result = $controller->output($data, $format);
-
- $this->assertEquals($result, $response, "Output should return response instance");
- }
-
- /**
- * Provide data for testing output
- *
- * @return array
- */
- public function outputProvider()
- {
- $xml = simplexml_load_string(
- "<?xml version='1.0'?>
- <document>
- <tag1>Test tag</tag1>
- <tag2>Test</tag2>
- </document>"
- );
-
- return [
- ['test_string', 'text', 'text/plain'],
- ['javascript:test_call();', 'js', 'application/javascript'],
- ['test {}', 'css', 'text/css'],
- ['test_string', 'json', 'application/json'],
- [['testKey' => 'testValue'], 'json', 'application/json'],
- [['testKey' => 'testValue'], 'json', 'application/json', 'test_callback'],
- ['', 'json', 'application/json'],
- ['', 'json', 'application/json', 'test_callback'],
- [$xml, 'xml', 'application/xml']
- ];
- }
-
- /**
- * Test functions that deal with error messages
- *
- * @dataProvider errorMessagesProvider
- * @param string $function
- * @param int $code
- * @param boolean $default Is code default for this function
- */
- public function testErrorMessages($function, $code, $default)
- {
- $message = 'Test message';
- $controller = $this->getController(['getResponse']);
- list(, $response) = $this->getRequests();
-
- $this->expectErrorMessage($response, $message, $code);
- $controller->method('getResponse')->will($this->returnValue($response));
-
- $result = $default ?
- $controller->{$function}($message) :
- $controller->{$function}($message, $code);
-
- $this->assertEquals($result, $response, "Response object should be returned");
- }
-
- /**
- * Provide data for testing error messages functions
- *
- * @return array
- */
- public function errorMessagesProvider()
- {
- return [
- ['error', 400, true],
- ['error', 403, false],
- ['tooManyRequests', 429, true],
- ['tooManyRequests', 400, false],
- ['conflict', 409, true],
- ['conflict', 403, false],
- ['notFound', 404, true],
- ['notFound', 400, false],
- ['forbidden', 403, true],
- ['forbidden', 409, false],
- ['badRequest', 400, true],
- ['badRequest', 403, false]
- ];
- }
-
- /**
- * Test setting flash
- *
- * @dataProvider flashProvider
- * @param object $data
- */
- public function testFlash($data)
- {
- $controller = $this->getMockBuilder(Controller::class)->disableOriginalConstructor()->getMockForAbstractClass();
-
- $flash = $controller->flash();
- $this->assertInstanceOf(Flash::class, $flash, "Flash is not set");
- $this->assertEmpty($flash->get(), "Flash data should be empty");
-
- $flash = $controller->flash($data->type, $data->message);
- $this->assertInstanceOf(Flash::class, $flash, "Flash is not set");
- $this->assertEquals($data, $flash->get(), "Flash data is incorrect");
-
- $flash = $controller->flash();
- $this->assertInstanceOf(Flash::class, $flash, "Flash is not set");
- $this->assertEquals($data, $flash->get(), "Flash data is incorrect");
-
- $flash->clear();
- }
-
- /**
- * Test setting flash
- *
- * @return array
- */
- public function flashProvider()
- {
- return [
- [(object)['type' => 'test_type', 'message' => 'Test message']]
- ];
- }
-
- /**
- * Test respondWith function
- *
- * @dataProvider respondWithProvider
- * @param int|string $code
- * @param string $format
- * @param int $setCode Actual code that will be set in response
- * @param string $contentType
- */
- public function testRespondWith($code, $format, $setCode, $contentType)
- {
- $controller = $this->getController(['getResponse']);
- list(, $response) = $this->getRequests();
-
- $this->expectResponseWith($response, $setCode, $contentType);
- $controller->method('getResponse')->will($this->returnValue($response));
-
- $result = $controller->respondWith($code, $format);
-
- $this->assertEquals($result, $response, "Response object should be returned");
- }
-
- /**
- * Test function respondWith
- *
- * @return array
- */
- public function respondWithProvider()
- {
- return [
- [200, 'json', 200, 'application/json'],
- [200, 'application/json', 200, 'application/json'],
- [204, null, 204, null],
- ['204 Created', null, 204, null],
- ['json', null, null, 'application/json']
- ];
- }
-
- /**
- * Test functions that are simple wrappers around respondWith function
- *
- * @dataProvider respondWithWrappersProvider
- * @param string $function
- * @param int $code
- */
- public function testResponseWithWrappers($function, $code)
- {
- $controller = $this->getController(['getResponse']);
- list(, $response) = $this->getRequests();
-
- $this->expectResponseWith($response, $code);
- $controller->method('getResponse')->will($this->returnValue($response));
-
- $result = $controller->{$function}();
-
- $this->assertEquals($result, $response, "Response object should be returned");
- }
-
- /**
- * Provide data for testing respondWith wrappers
- *
- * @return array
- */
- public function respondWithWrappersProvider()
- {
- return [
- ['ok', 200],
- ['noContent', 204]
- ];
- }
-
- /**
- * Test 'created' function
- *
- * @dataProvider createdProvider
- * @param string $location
- */
- public function testCreated($location)
- {
- $controller = $this->getController(['getResponse']);
- list(, $response) = $this->getRequests();
-
- $response->expects($this->once())->method('withStatus')->with($this->equalTo(201))->will($this->returnSelf());
- if ($location) {
- $response->expects($this->once())->method('withHeader')->with($this->equalTo('Location'), $this->equalTo($location))->will($this->returnSelf());
- }
-
- $controller->method('getResponse')->will($this->returnValue($response));
-
- $result = $controller->created($location);
-
- $this->assertEquals($result, $response, "Response object should be returned");
- }
-
- /**
- * Provide data for testing 'created' function
- *
- * @return array
- */
- public function createdProvider()
- {
- return [
- [''], ['/some-path/test']
- ];
- }
-
- /**
- * Test 'redirect' function
- *
- * @dataProvider redirectProvider
- * @param string $url
- * @param int $code
- * @param boolean $default
- */
- public function testRedirect($url, $code, $default)
- {
- $controller = $this->getController(['getResponse']);
- list(, $response) = $this->getRequests();
-
- $this->expectRedirect($response, $url, $code);
- $controller->method('getResponse')->will($this->returnValue($response));
-
- $result = $default ?
- $controller->redirect($url) :
- $controller->redirect($url, $code);
-
- $this->assertEquals($result, $response, "Response object should be returned");
- }
-
- /**
- * Provide data for testing 'redirect' function
- *
- * @return array
- */
- public function redirectProvider()
- {
- return [
- ['/test-url', 303, true],
- ['/test-url', 301, false]
- ];
- }
-
- /**
- * Test 'requireLogin' function
- *
- * @dataProvider requireLoginProvider
- * @param string $function
- */
- public function testRequireLogin($function)
- {
- $controller = $this->getController(['getResponse']);
- list(, $response) = $this->getRequests();
-
- $this->expectRedirect($response, '/401', 303);
- $controller->method('getResponse')->will($this->returnValue($response));
-
- $result = $controller->{$function}();
-
- $this->assertEquals($result, $response, "Response object should be returned");
- }
-
- /**
- * Provide data for testing 'requireLogon' function
- *
- * @return array
- */
- public function requireLoginProvider()
- {
- return [
- ['requireLogin'], ['requireAuth']
- ];
- }
-
- /**
- * Test 'getLocalReferer' funtion
- *
- * @dataProvider localRefererProvider
- * @param string $referer
- * @param string $host
- * @param boolean $local
- */
- public function testLocalReferer($referer, $host, $local)
- {
- $controller = $this->getController(['getRequest']);
- list($request) = $this->getRequests();
-
- $this->expectLocalReferer($request, $referer, $host);
- $controller->method('getRequest')->will($this->returnValue($request));
-
- $result = $controller->getLocalReferer();
-
- $local ?
- $this->assertEquals($referer, $result, "Local referer should be returned") :
- $this->assertEquals('', $result, "Local referer should not be returned");
- }
-
- /**
- * Test 'back' function
- *
- * @dataProvider localRefererProvider
- * @param string $referer
- * @param string $host
- * @param boolean $local
- */
- public function testBack($referer, $host, $local)
- {
- $controller = $this->getController(['getRequest', 'getResponse']);
- list($request, $response) = $this->getRequests();
-
- $this->expectLocalReferer($request, $referer, $host);
- $this->expectRedirect($response, $local ? $referer : '/', 303);
-
- $controller->method('getRequest')->will($this->returnValue($request));
- $controller->method('getResponse')->will($this->returnValue($response));
-
- $result = $controller->back();
-
- $this->assertEquals($result, $response, "Response object should be returned");
- }
-
- /**
- * Provide data fot testing 'getLocalReferer' function
- *
- * @return array
- */
- public function localRefererProvider()
- {
- return [
- ['http://not-local-host.com/path', 'local-host.com', false],
- ['http://local-host.com/path', 'local-host.com', true]
- ];
- }
-
- /**
- * Expect for 'getLocalReferer' function to work correctly
- *
- * @param ServerRequestInterface $request
- * @param string $referer
- * @param string $host
- */
- public function expectLocalReferer($request, $referer, $host)
- {
- $request->expects($this->exactly(2))->method('getHeaderLine')->withConsecutive(
- [$this->equalTo('HTTP_REFERER')],
- [$this->equalTo('HTTP_HOST')]
- )->will($this->returnCallback(function($header) use ($referer, $host) {
- return $header === 'HTTP_REFERER' ? $referer : $host;
- }));
- }
-
- /**
- * Expect for redirect
- *
- * @param ResponseInterface $response
- * @param string $url
- * @param int $code
- */
- public function expectRedirect($response, $url, $code)
- {
- $stream = $this->createMock(StreamInterface::class);
- $stream->expects($this->once())->method('write')->with($this->equalTo('You are being redirected to <a href="' . $url . '">' . $url . '</a>'));
-
- $response->expects($this->once())->method('getBody')->will($this->returnValue($stream));
- $response->expects($this->once())->method('withStatus')->with($this->equalTo($code))->will($this->returnSelf());
- $response->expects($this->exactly(2))->method('withHeader')->withConsecutive(
- [$this->equalTo('Content-Type'), $this->equalTo('text/html')],
- [$this->equalTo('Location'), $this->equalTo($url)]
- )->will($this->returnSelf());
- }
-
- /**
- * Expect correct work of respondWith function
- *
- * @param ResponseInterface $response
- * @param int $code
- * @param string $contentType
- */
- public function expectResponseWith($response, $code, $contentType = null)
- {
- $code ?
- $response->expects($this->once())->method('withStatus')->with($this->equalTo($code))->will($this->returnSelf()) :
- $response->expects($this->never())->method('withStatus')->with($this->equalTo($code));
-
- $contentType ?
- $response->expects($this->once())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo($contentType))->will($this->returnSelf()) :
- $response->expects($this->never())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo($contentType));
- }
-
- /**
- * Expect for correct work of error message functions
- *
- * @param ResponseInterface $response
- * @param string $message
- * @param int $code
- */
- public function expectErrorMessage($response, $message, $code)
- {
- $stream = $this->createMock(StreamInterface::class);
- $stream->expects($this->once())->method('write')->with($this->equalTo($message));
-
- $response->expects($this->once())->method('withStatus')->with($this->equalTo($code))->will($this->returnSelf());
- $response->expects($this->once())->method('getBody')->will($this->returnValue($stream));
- }
-
- /**
- * Expects that output will be set to content
- *
- * @param ResponseInterface $response
- * @param string $content
- * @param string $contentType
- */
- public function expectOutput($response, $content, $contentType)
- {
- $stream = $this->createMock(StreamInterface::class);
- $stream->expects($this->once())->method('write')->with($this->equalTo($content));
-
- $response->expects($this->once())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo($contentType))->will($this->returnSelf());
- $response->expects($this->once())->method('getBody')->will($this->returnValue($stream));
- }
-
- /**
- * Get request and response instances
- *
- * @return array
- */
- public function getRequests()
- {
- return [
- $this->createMock(ServerRequestInterface::class),
- $this->createMock(ResponseInterface::class)
- ];
- }
-
- /**
- * Get map of status codes to states
- *
- * @param int $code
- * @return []
- */
- public function getStatusCodesMap($code)
- {
- return [
- 'isSuccessful' => !$code || ($code >= 200 && $code < 300),
- 'isRedirection' => $code >= 300 && $code < 400,
- 'isClientError' => $code >= 400 && $code < 500,
- 'isServerError' => $code >= 500
- ];
- }
-
- /**
- * Get map of request methods
- *
- * @param string $method
- * @return array
- */
- public function getMethodsMap($method)
- {
- return [
- 'isGetRequest' => $method === 'GET',
- 'isPostRequest' => $method === 'POST',
- 'isPutRequest' => $method === 'PUT',
- 'isDeleteRequest' => $method === 'DELETE',
- 'isHeadRequest' => $method === 'HEAD'
- ];
- }
}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
new file mode 100644
index 0000000..7648e13
--- /dev/null
+++ b/tests/bootstrap.php
@@ -0,0 +1,4 @@
+<?php
+
+$loader = require __DIR__ . '/../vendor/autoload.php';
+$loader->addPsr4('Jasny\\Controller\\', __DIR__ . '/support');
diff --git a/tests/support/RouteActionController.php b/tests/support/RouteActionController.php
new file mode 100644
index 0000000..66625a9
--- /dev/null
+++ b/tests/support/RouteActionController.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Jasny\Controller;
+
+use Jasny\Controller;
+
+/**
+ * Class for testing 'RouteAction' trait
+ */
+class RouteActionController extends Controller
+{
+ use Controller\RouteAction;
+}
diff --git a/tests/support/SessionController.php b/tests/support/SessionController.php
new file mode 100644
index 0000000..6758419
--- /dev/null
+++ b/tests/support/SessionController.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Jasny\Controller;
+
+use Jasny\Controller;
+
+/**
+ * Class for testing 'Session' trait
+ */
+abstract class SessionController extends Controller
+{
+ use Controller\Session;
+}
diff --git a/tests/support/TestController.php b/tests/support/TestController.php
deleted file mode 100644
index e0bdb7b..0000000
--- a/tests/support/TestController.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-use Jasny\Controller;
-use Jasny\Controller\RouteAction;
-use Psr\Http\Message\ServerRequestInterface;
-use Psr\Http\Message\ResponseInterface;
-
-/**
- * Class for testing 'RouteAction' trait
- */
-class TestController extends Controller
-{
- use RouteAction;
-
- /**
- * Test action for executing router
- *
- * @param mixed $param1
- * @param mixed $param2
- * @return ResponseInterface
- */
- public function testRunAction($param1, $param2 = 'defaultValue')
- {
- $response = $this->getResponse();
-
- $response->actionCalled = true;
- $response->param1 = $param1;
- $response->param2 = $param2;
-
- 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;
- }
-}
diff --git a/tests/support/TestHelper.php b/tests/support/TestHelper.php
new file mode 100644
index 0000000..01347f4
--- /dev/null
+++ b/tests/support/TestHelper.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Jasny\Controller;
+
+use Jasny\Controller;
+
+/**
+ * Additional test methods
+ */
+trait TestHelper
+{
+ /**
+ * Get mock for controller
+ *
+ * @param array $methods Methods to mock
+ * @return Controller|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getController($methods = [])
+ {
+ $builder = $this->getMockBuilder(Controller::class)->disableOriginalConstructor();
+ if ($methods) {
+ $builder->setMethods($methods);
+ }
+
+ return $builder->getMockForAbstractClass();
+ }
+}