summaryrefslogtreecommitdiffstats
path: root/tests/ControllerTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ControllerTest.php')
-rw-r--r--tests/ControllerTest.php612
1 files changed, 603 insertions, 9 deletions
diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php
index 8cdbf7d..e0ebdc2 100644
--- a/tests/ControllerTest.php
+++ b/tests/ControllerTest.php
@@ -3,7 +3,11 @@
use Jasny\Controller;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+/**
+ * @covers Jasny\Controller
+ */
class ControllerTest extends PHPUnit_Framework_TestCase
{
/**
@@ -11,7 +15,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase
*/
public function testInvoke()
{
- $controller = $this->getMockBuilder(Controller::class)->disableOriginalConstructor()->getMockForAbstractClass();
+ $controller = $this->getController();
list($request, $response) = $this->getRequests();
$controller->expects($this->once())->method('run')->will($this->returnValue($response));
@@ -28,7 +32,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase
*/
public function testResponseStatusEmptyResponse()
{
- $controller = $this->getMockBuilder(Controller::class)->disableOriginalConstructor()->getMockForAbstractClass();
+ $controller = $this->getController();
$data = $this->getStatusCodesMap(null);
foreach ($data as $func => $value) {
@@ -40,11 +44,11 @@ class ControllerTest extends PHPUnit_Framework_TestCase
* Test functions that check response status code
*
* @dataProvider responseStatusProvider
- * @param int $statusCode
+ * @param int status code
*/
public function testResponseStatus($code)
{
- $controller = $this->getMockBuilder(Controller::class)->disableOriginalConstructor()->getMockForAbstractClass();
+ $controller = $this->getController();
list($request, $response) = $this->getRequests();
$response->method('getStatusCode')->will($this->returnValue($code));
@@ -56,7 +60,8 @@ class ControllerTest extends PHPUnit_Framework_TestCase
$this->assertEquals($value, $controller->$func(), "Method '$func' returns incorrect value");
}
- $this->assertEquals($data['isClientError'] || $data['isServerError'], $controller->isError(), "Method 'isError' returns incorrect value");
+ $this->assertEquals($data['isClientError'] || $data['isServerError'], $controller->isError()
+ , "Method 'isError' returns incorrect value");
}
/**
@@ -76,6 +81,591 @@ class ControllerTest extends PHPUnit_Framework_TestCase
}
/**
+ * 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)
+ {
+ $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)
+ {
+ $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 responseWith function
+ *
+ * @dataProvider responseWithProvider
+ * @param int|string $code
+ * @param string $format
+ * @param int $setCode Actual code that will be set in response
+ * @param string $contentType
+ */
+ public function testResponseWith($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->responseWith($code, $format);
+
+ $this->assertEquals($result, $response, "Response object should be returned");
+ }
+
+ /**
+ * Test function responseWith
+ *
+ * @return array
+ */
+ public function responseWithProvider()
+ {
+ 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 responseWith function
+ *
+ * @dataProvider responseWithWrappersProvider
+ * @param string $functino
+ * @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 responseWith wrappers
+ *
+ * @return array
+ */
+ public function responseWithWrappersProvider()
+ {
+ 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 responseWith 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 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();
+ }
+
+ /**
+ * 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
@@ -92,15 +682,19 @@ class ControllerTest extends PHPUnit_Framework_TestCase
}
/**
- * Get request and response instances
+ * Get map of request methods
*
+ * @param string $method
* @return array
*/
- public function getRequests()
+ public function getMethodsMap($method)
{
return [
- $this->createMock(ServerRequestInterface::class),
- $this->createMock(ResponseInterface::class)
+ 'isGetRequest' => $method === 'GET',
+ 'isPostRequest' => $method === 'POST',
+ 'isPutRequest' => $method === 'PUT',
+ 'isDeleteRequest' => $method === 'DELETE',
+ 'isHeadRequest' => $method === 'HEAD'
];
}
}