Added middleware tests

This commit is contained in:
Igor Scheller 2018-08-11 23:46:28 +02:00
parent f3f05f6cc4
commit f3b3b6683c
15 changed files with 811 additions and 185 deletions

View File

@ -16,6 +16,8 @@
"require": { "require": {
"php": ">=7.0.0", "php": ">=7.0.0",
"ext-gettext": "*", "ext-gettext": "*",
"ext-json": "*",
"ext-PDO": "*",
"erusev/parsedown": "^1.6", "erusev/parsedown": "^1.6",
"illuminate/container": "5.5.*", "illuminate/container": "5.5.*",
"illuminate/database": "5.5.*", "illuminate/database": "5.5.*",

View File

@ -73,8 +73,6 @@ function success($msg, $immediately = false)
*/ */
function alert($class, $msg, $immediately = false) function alert($class, $msg, $immediately = false)
{ {
$session = session();
if (empty($msg)) { if (empty($msg)) {
return ''; return '';
} }
@ -83,6 +81,7 @@ function alert($class, $msg, $immediately = false)
return '<div class="alert alert-' . $class . '">' . $msg . '</div>'; return '<div class="alert alert-' . $class . '">' . $msg . '</div>';
} }
$session = session();
$message = $session->get('msg', ''); $message = $session->get('msg', '');
$message .= alert($class, $msg, true); $message .= alert($class, $msg, true);
$session->set('msg', $message); $session->set('msg', $message);

View File

@ -12,7 +12,7 @@ use Psr\Http\Server\RequestHandlerInterface;
class Dispatcher implements MiddlewareInterface, RequestHandlerInterface class Dispatcher implements MiddlewareInterface, RequestHandlerInterface
{ {
/** @var MiddlewareInterface[] */ /** @var MiddlewareInterface[]|string[] */
protected $stack; protected $stack;
/** @var Application */ /** @var Application */
@ -22,7 +22,7 @@ class Dispatcher implements MiddlewareInterface, RequestHandlerInterface
protected $next; protected $next;
/** /**
* @param MiddlewareInterface[] $stack * @param MiddlewareInterface[]|string[] $stack
* @param Application|null $container * @param Application|null $container
*/ */
public function __construct($stack = [], Application $container = null) public function __construct($stack = [], Application $container = null)

View File

@ -3,6 +3,7 @@
namespace Engelsystem\Middleware; namespace Engelsystem\Middleware;
use Engelsystem\Http\Request; use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
@ -61,10 +62,6 @@ class LegacyMiddleware implements MiddlewareInterface
/** @var Request $appRequest */ /** @var Request $appRequest */
$appRequest = $this->container->get('request'); $appRequest = $this->container->get('request');
// Default page content
$content = '';
$page = $appRequest->query->get('p'); $page = $appRequest->query->get('p');
if (empty($page)) { if (empty($page)) {
$page = $appRequest->path(); $page = $appRequest->path();
@ -74,187 +71,202 @@ class LegacyMiddleware implements MiddlewareInterface
$page = isset($user) ? 'news' : 'login'; $page = isset($user) ? 'news' : 'login';
} }
$title = $content = '';
if ( if (
preg_match('/^\w+$/i', $page) preg_match('~^\w+$~i', $page)
&& ( && (
in_array($page, $this->free_pages) in_array($page, $this->free_pages)
|| (isset($privileges) && in_array($page, $privileges)) || (isset($privileges) && in_array($page, $privileges))
) )
) { ) {
$title = $page; list($title, $content) = $this->loadPage($page);
switch ($page) {
case 'api':
error('Api disabled temporarily.');
redirect(page_link_to());
break;
case 'ical':
require_once realpath(__DIR__ . '/../includes/pages/user_ical.php');
user_ical();
break;
case 'atom':
require_once realpath(__DIR__ . '/../includes/pages/user_atom.php');
user_atom();
break;
case 'shifts_json_export':
require_once realpath(__DIR__ . '/../includes/controller/shifts_controller.php');
shifts_json_export_controller();
break;
case 'shifts_json_export_all':
require_once realpath(__DIR__ . '/../includes/controller/shifts_controller.php');
shifts_json_export_all_controller();
break;
case 'stats':
require_once realpath(__DIR__ . '/../includes/pages/guest_stats.php');
guest_stats();
break;
case 'user_password_recovery':
require_once realpath(__DIR__ . '/../includes/controller/users_controller.php');
$title = user_password_recovery_title();
$content = user_password_recovery_controller();
break;
case 'public_dashboard':
list($title, $content) = public_dashboard_controller();
break;
case 'angeltypes':
list($title, $content) = angeltypes_controller();
break;
case 'shift_entries':
list($title, $content) = shift_entries_controller();
break;
case 'shifts':
list($title, $content) = shifts_controller();
break;
case 'users':
list($title, $content) = users_controller();
break;
case 'user_angeltypes':
list($title, $content) = user_angeltypes_controller();
break;
case 'user_driver_licenses':
list($title, $content) = user_driver_licenses_controller();
break;
case 'shifttypes':
list($title, $content) = shifttypes_controller();
break;
case 'admin_event_config':
list($title, $content) = event_config_edit_controller();
break;
case 'rooms':
list($title, $content) = rooms_controller();
break;
case 'news':
$title = news_title();
$content = user_news();
break;
case 'news_comments':
require_once realpath(__DIR__ . '/../includes/pages/user_news.php');
$title = user_news_comments_title();
$content = user_news_comments();
break;
case 'user_meetings':
$title = meetings_title();
$content = user_meetings();
break;
case 'user_myshifts':
$title = myshifts_title();
$content = user_myshifts();
break;
case 'user_shifts':
$title = shifts_title();
$content = user_shifts();
break;
case 'user_worklog':
list($title, $content) = user_worklog_controller();
break;
case 'user_messages':
$title = messages_title();
$content = user_messages();
break;
case 'user_questions':
$title = questions_title();
$content = user_questions();
break;
case 'user_settings':
$title = settings_title();
$content = user_settings();
break;
case 'login':
$title = login_title();
$content = guest_login();
break;
case 'register':
$title = register_title();
$content = guest_register();
break;
case 'logout':
$title = logout_title();
$content = guest_logout();
break;
case 'admin_questions':
$title = admin_questions_title();
$content = admin_questions();
break;
case 'admin_user':
$title = admin_user_title();
$content = admin_user();
break;
case 'admin_arrive':
$title = admin_arrive_title();
$content = admin_arrive();
break;
case 'admin_active':
$title = admin_active_title();
$content = admin_active();
break;
case 'admin_free':
$title = admin_free_title();
$content = admin_free();
break;
case 'admin_news':
require_once realpath(__DIR__ . '/../includes/pages/admin_news.php');
$content = admin_news();
break;
case 'admin_rooms':
$title = admin_rooms_title();
$content = admin_rooms();
break;
case 'admin_groups':
$title = admin_groups_title();
$content = admin_groups();
break;
case 'admin_import':
$title = admin_import_title();
$content = admin_import();
break;
case 'admin_shifts':
$title = admin_shifts_title();
$content = admin_shifts();
break;
case 'admin_log':
$title = admin_log_title();
$content = admin_log();
break;
case 'credits':
require_once realpath(__DIR__ . '/../includes/pages/guest_credits.php');
$title = credits_title();
$content = guest_credits();
break;
default:
require_once realpath(__DIR__ . '/../includes/pages/guest_start.php');
$content = guest_start();
break;
}
} else {
return $handler->handle($request);
} }
if (empty($title) and empty($content)) { if (empty($title) and empty($content)) {
return $handler->handle($request); return $handler->handle($request);
} }
$event_config = EventConfig(); return $this->renderPage($page, $title, $content);
}
/**
* Get the legacy page content and title
*
* @param string $page
* @return array ['title', 'content']
* @codeCoverageIgnore
*/
protected function loadPage($page)
{
$title = ucfirst($page);
switch ($page) {
/** @noinspection PhpMissingBreakStatementInspection */
case 'api':
error('Api disabled temporarily.');
redirect(page_link_to());
/** @noinspection PhpMissingBreakStatementInspection */
case 'ical':
require_once realpath(__DIR__ . '/../../includes/pages/user_ical.php');
user_ical();
/** @noinspection PhpMissingBreakStatementInspection */
case 'atom':
require_once realpath(__DIR__ . '/../../includes/pages/user_atom.php');
user_atom();
/** @noinspection PhpMissingBreakStatementInspection */
case 'shifts_json_export':
require_once realpath(__DIR__ . '/../../includes/controller/shifts_controller.php');
shifts_json_export_controller();
/** @noinspection PhpMissingBreakStatementInspection */
case 'shifts_json_export_all':
require_once realpath(__DIR__ . '/../../includes/controller/shifts_controller.php');
shifts_json_export_all_controller();
/** @noinspection PhpMissingBreakStatementInspection */
case 'stats':
require_once realpath(__DIR__ . '/../../includes/pages/guest_stats.php');
guest_stats();
case 'user_password_recovery':
require_once realpath(__DIR__ . '/../../includes/controller/users_controller.php');
$title = user_password_recovery_title();
$content = user_password_recovery_controller();
return [$title, $content];
case 'public_dashboard':
return public_dashboard_controller();
case 'angeltypes':
return angeltypes_controller();
case 'shift_entries':
return shift_entries_controller();
case 'shifts':
return shifts_controller();
case 'users':
return users_controller();
case 'user_angeltypes':
return user_angeltypes_controller();
case 'user_driver_licenses':
return user_driver_licenses_controller();
case 'shifttypes':
list($title, $content) = shifttypes_controller();
return [$title, $content];
case 'admin_event_config':
list($title, $content) = event_config_edit_controller();
return [$title, $content];
case 'rooms':
return rooms_controller();
case 'news':
$title = news_title();
$content = user_news();
return [$title, $content];
case 'news_comments':
require_once realpath(__DIR__ . '/../../includes/pages/user_news.php');
$title = user_news_comments_title();
$content = user_news_comments();
return [$title, $content];
case 'user_meetings':
$title = meetings_title();
$content = user_meetings();
return [$title, $content];
case 'user_myshifts':
$title = myshifts_title();
$content = user_myshifts();
return [$title, $content];
case 'user_shifts':
$title = shifts_title();
$content = user_shifts();
return [$title, $content];
case 'user_worklog':
return user_worklog_controller();
case 'user_messages':
$title = messages_title();
$content = user_messages();
return [$title, $content];
case 'user_questions':
$title = questions_title();
$content = user_questions();
return [$title, $content];
case 'user_settings':
$title = settings_title();
$content = user_settings();
return [$title, $content];
case 'login':
$title = login_title();
$content = guest_login();
return [$title, $content];
case 'register':
$title = register_title();
$content = guest_register();
return [$title, $content];
case 'logout':
$title = logout_title();
$content = guest_logout();
return [$title, $content];
case 'admin_questions':
$title = admin_questions_title();
$content = admin_questions();
return [$title, $content];
case 'admin_user':
$title = admin_user_title();
$content = admin_user();
return [$title, $content];
case 'admin_arrive':
$title = admin_arrive_title();
$content = admin_arrive();
return [$title, $content];
case 'admin_active':
$title = admin_active_title();
$content = admin_active();
return [$title, $content];
case 'admin_free':
$title = admin_free_title();
$content = admin_free();
return [$title, $content];
case 'admin_news':
require_once realpath(__DIR__ . '/../../includes/pages/admin_news.php');
$content = admin_news();
return [$title, $content];
case 'admin_rooms':
$title = admin_rooms_title();
$content = admin_rooms();
return [$title, $content];
case 'admin_groups':
$title = admin_groups_title();
$content = admin_groups();
return [$title, $content];
case 'admin_import':
$title = admin_import_title();
$content = admin_import();
return [$title, $content];
case 'admin_shifts':
$title = admin_shifts_title();
$content = admin_shifts();
return [$title, $content];
case 'admin_log':
$title = admin_log_title();
$content = admin_log();
return [$title, $content];
case 'credits':
require_once realpath(__DIR__ . '/../../includes/pages/guest_credits.php');
$title = credits_title();
$content = guest_credits();
return [$title, $content];
}
require_once realpath(__DIR__ . '/../../includes/pages/guest_start.php');
$content = guest_start();
return [$title, $content];
}
/**
* Render the template
*
* @param string $page
* @param string $title
* @param string $content
* @return Response
* @codeCoverageIgnore
*/
protected function renderPage($page, $title, $content)
{
global $user;
$event_config = EventConfig();
$parameters = [ $parameters = [
'key' => (isset($user) ? $user['api_key'] : ''), 'key' => (isset($user) ? $user['api_key'] : ''),
]; ];

View File

@ -2,6 +2,7 @@
namespace Engelsystem\Middleware; namespace Engelsystem\Middleware;
use Engelsystem\Http\Response;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\MiddlewareInterface;
@ -22,12 +23,20 @@ class NotFoundResponse implements MiddlewareInterface
ServerRequestInterface $request, ServerRequestInterface $request,
RequestHandlerInterface $handler RequestHandlerInterface $handler
): ResponseInterface { ): ResponseInterface {
$info = _('This page could not be found or you don\'t have permission to view it. You probably have to sign in or register in order to gain access!');
return $this->renderPage($info);
}
/**
* @param string $content
* @return Response
* @codeCoverageIgnore
*/
protected function renderPage($content)
{
global $user; global $user;
$event_config = EventConfig(); $event_config = EventConfig();
$content = info(
_('This page could not be found or you don\'t have permission to view it. You probably have to sign in or register in order to gain access!'),
true
);
return response(view(__DIR__ . '/../../templates/layout.html', [ return response(view(__DIR__ . '/../../templates/layout.html', [
'theme' => isset($user) ? $user['color'] : config('theme'), 'theme' => isset($user) ? $user['color'] : config('theme'),
@ -36,7 +45,7 @@ class NotFoundResponse implements MiddlewareInterface
'start_page_url' => page_link_to('/'), 'start_page_url' => page_link_to('/'),
'credits_url' => page_link_to('credits'), 'credits_url' => page_link_to('credits'),
'menu' => make_menu(), 'menu' => make_menu(),
'content' => msg() . $content, 'content' => msg() . info($content),
'header_toolbar' => header_toolbar(), 'header_toolbar' => header_toolbar(),
'faq_url' => config('faq_url'), 'faq_url' => config('faq_url'),
'contact_email' => config('contact_email'), 'contact_email' => config('contact_email'),

View File

@ -24,8 +24,8 @@ class SendResponseHandler implements MiddlewareInterface
): ResponseInterface { ): ResponseInterface {
$response = $handler->handle($request); $response = $handler->handle($request);
if (!headers_sent()) { if (!$this->headersSent()) {
header(sprintf( $this->sendHeader(sprintf(
'HTTP/%s %s %s', 'HTTP/%s %s %s',
$response->getProtocolVersion(), $response->getProtocolVersion(),
$response->getStatusCode(), $response->getStatusCode(),
@ -34,7 +34,7 @@ class SendResponseHandler implements MiddlewareInterface
foreach ($response->getHeaders() as $name => $values) { foreach ($response->getHeaders() as $name => $values) {
foreach ($values as $value) { foreach ($values as $value) {
header($name . ': ' . $value, false); $this->sendHeader($name . ': ' . $value, false);
} }
} }
} }
@ -42,4 +42,28 @@ class SendResponseHandler implements MiddlewareInterface
echo $response->getBody(); echo $response->getBody();
return $response; return $response;
} }
/**
* Checks if headers have been sent
*
* @return bool
* @codeCoverageIgnore
*/
protected function headersSent()
{
return headers_sent();
}
/**
* Send a raw HTTP header
*
* @param string $content
* @param bool $replace
* @param int $code
* @codeCoverageIgnore
*/
protected function sendHeader($content, $replace = true, $code = null)
{
header($content, $replace, $code);
}
} }

View File

@ -0,0 +1,230 @@
<?php
namespace Engelsystem\Test\Unit\Middleware;
use Engelsystem\Application;
use Engelsystem\Middleware\Dispatcher;
use Engelsystem\Test\Unit\Middleware\Stub\NotARealMiddleware;
use Engelsystem\Test\Unit\Middleware\Stub\ReturnResponseMiddleware;
use InvalidArgumentException;
use LogicException;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use ReflectionClass as Reflection;
class DispatcherTest extends TestCase
{
/**
* @covers \Engelsystem\Middleware\Dispatcher::__construct
*/
public function testInit()
{
/** @var Application|MockObject $container */
$container = $this->createMock(Application::class);
$dispatcher = new Dispatcher([], $container);
$this->assertInstanceOf(MiddlewareInterface::class, $dispatcher);
$this->assertInstanceOf(RequestHandlerInterface::class, $dispatcher);
$reflection = new Reflection(get_class($dispatcher));
$property = $reflection->getProperty('container');
$property->setAccessible(true);
$this->assertEquals($container, $property->getValue($dispatcher));
}
/**
* @covers \Engelsystem\Middleware\Dispatcher::process
*/
public function testProcess()
{
/** @var ServerRequestInterface|MockObject $request */
$request = $this->createMock(ServerRequestInterface::class);
/** @var ResponseInterface|MockObject $response */
$response = $this->createMock(ResponseInterface::class);
/** @var RequestHandlerInterface|MockObject $handler */
$handler = $this->createMock(RequestHandlerInterface::class);
/** @var Dispatcher|MockObject $dispatcher */
$dispatcher = $this->getMockBuilder(Dispatcher::class)
->setMethods(['handle'])
->getMock();
$dispatcher->expects($this->once())
->method('handle')
->willReturn($response);
$return = $dispatcher->process($request, $handler);
$this->assertEquals($response, $return);
$reflection = new Reflection(get_class($dispatcher));
$property = $reflection->getProperty('next');
$property->setAccessible(true);
$this->assertEquals($handler, $property->getValue($dispatcher));
}
/**
* @covers \Engelsystem\Middleware\Dispatcher::handle
*/
public function testHandle()
{
/** @var ServerRequestInterface|MockObject $request */
$request = $this->createMock(ServerRequestInterface::class);
/** @var ResponseInterface|MockObject $response */
$response = $this->createMock(ResponseInterface::class);
/** @var MiddlewareInterface|MockObject $middleware */
$middleware = $this->createMock(MiddlewareInterface::class);
$dispatcher = new Dispatcher([$middleware]);
$middleware->expects($this->once())
->method('process')
->with($request, $dispatcher)
->willReturn($response);
$return = $dispatcher->handle($request);
$this->assertEquals($response, $return);
}
/**
* @covers \Engelsystem\Middleware\Dispatcher::handle
*/
public function testHandleNext()
{
/** @var ServerRequestInterface|MockObject $request */
$request = $this->createMock(ServerRequestInterface::class);
/** @var ResponseInterface|MockObject $response */
$response = $this->createMock(ResponseInterface::class);
/** @var RequestHandlerInterface|MockObject $handler */
$handler = $this->createMock(RequestHandlerInterface::class);
$dispatcher = new Dispatcher();
$handler->expects($this->once())
->method('handle')
->with($request)
->willReturn($response);
$reflection = new Reflection(get_class($dispatcher));
$property = $reflection->getProperty('next');
$property->setAccessible(true);
$property->setValue($dispatcher, $handler);
$return = $dispatcher->handle($request);
$this->assertEquals($response, $return);
}
/**
* @covers \Engelsystem\Middleware\Dispatcher::handle
*/
public function testHandleNoMiddleware()
{
/** @var ServerRequestInterface|MockObject $request */
$request = $this->createMock(ServerRequestInterface::class);
$this->expectException(LogicException::class);
$dispatcher = new Dispatcher();
$dispatcher->handle($request);
}
/**
* @covers \Engelsystem\Middleware\Dispatcher::handle
*/
public function testHandleNoRealMiddleware()
{
/** @var ServerRequestInterface|MockObject $request */
$request = $this->createMock(ServerRequestInterface::class);
$this->expectException(InvalidArgumentException::class);
$dispatcher = new Dispatcher([new NotARealMiddleware()]);
$dispatcher->handle($request);
}
/**
* @covers \Engelsystem\Middleware\Dispatcher::handle
*/
public function testHandleCallResolve()
{
/** @var ServerRequestInterface|MockObject $request */
$request = $this->createMock(ServerRequestInterface::class);
/** @var ResponseInterface|MockObject $response */
$response = $this->createMock(ResponseInterface::class);
/** @var MiddlewareInterface|MockObject $middleware */
$middleware = $this->createMock(MiddlewareInterface::class);
/** @var Dispatcher|MockObject $dispatcher */
$dispatcher = $this->getMockBuilder(Dispatcher::class)
->setConstructorArgs([[MiddlewareInterface::class]])
->setMethods(['resolveMiddleware'])
->getMock();
$dispatcher->expects($this->once())
->method('resolveMiddleware')
->with(MiddlewareInterface::class)
->willReturn($middleware);
$middleware->expects($this->once())
->method('process')
->with($request, $dispatcher)
->willReturn($response);
$return = $dispatcher->handle($request);
$this->assertEquals($response, $return);
}
/**
* @covers \Engelsystem\Middleware\Dispatcher::resolveMiddleware
* @covers \Engelsystem\Middleware\Dispatcher::setContainer
*/
public function testResolveMiddleware()
{
/** @var Application|MockObject $container */
$container = $this->createMock(Application::class);
/** @var ServerRequestInterface|MockObject $request */
$request = $this->createMock(ServerRequestInterface::class);
/** @var ResponseInterface|MockObject $response */
$response = $this->createMock(ResponseInterface::class);
$returnResponseMiddleware = new ReturnResponseMiddleware($response);
$container->expects($this->exactly(2))
->method('has')
->withConsecutive([ReturnResponseMiddleware::class], ['middleware'])
->willReturnOnConsecutiveCalls(false, true);
$container->expects($this->once())
->method('make')
->with(ReturnResponseMiddleware::class)
->willReturn($returnResponseMiddleware);
$container->expects($this->once())
->method('get')
->with('middleware')
->willReturn($returnResponseMiddleware);
$dispatcher = new Dispatcher([ReturnResponseMiddleware::class]);
$dispatcher->setContainer($container);
$dispatcher->handle($request);
$dispatcher = new Dispatcher(['middleware'], $container);
$dispatcher->handle($request);
}
/**
* @covers \Engelsystem\Middleware\Dispatcher::resolveMiddleware
*/
public function testResolveMiddlewareNoContainer()
{
/** @var ServerRequestInterface|MockObject $request */
$request = $this->createMock(ServerRequestInterface::class);
$this->expectException(InvalidArgumentException::class);
$dispatcher = new Dispatcher([ReturnResponseMiddleware::class]);
$dispatcher->handle($request);
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace Engelsystem\Test\Unit\Middleware;
use Engelsystem\Application;
use Engelsystem\Exceptions\Handler;
use Engelsystem\Http\Response;
use Engelsystem\Middleware\ExceptionHandler;
use Engelsystem\Test\Unit\Middleware\Stub\ExceptionMiddlewareHandler;
use Engelsystem\Test\Unit\Middleware\Stub\ReturnResponseMiddlewareHandler;
use Illuminate\Contracts\Container\Container as ContainerInterface;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class ExceptionHandlerTest extends TestCase
{
/**
* @covers \Engelsystem\Middleware\ExceptionHandler::__construct
* @covers \Engelsystem\Middleware\ExceptionHandler::process
*/
public function testRegister()
{
/** @var MockObject|ContainerInterface $container */
$container = $this->getMockForAbstractClass(ContainerInterface::class);
/** @var MockObject|ServerRequestInterface $request */
$request = $this->getMockBuilder(ServerRequestInterface::class)->getMock();
/** @var MockObject|ResponseInterface $response */
$response = $this->getMockBuilder(Response::class)->getMock();
/** @var MockObject|Handler $errorHandler */
$errorHandler = $this->getMockBuilder(Handler::class)->getMock();
$returnResponseHandler = new ReturnResponseMiddlewareHandler($response);
$throwExceptionHandler = new ExceptionMiddlewareHandler();
Application::setInstance($container);
$container->expects($this->exactly(2))
->method('get')
->withConsecutive(['error.handler'], ['psr7.response'])
->willReturnOnConsecutiveCalls($errorHandler, $response);
$response->expects($this->once())
->method('withContent')
->willReturn($response);
$response->expects($this->once())
->method('withStatus')
->with(500)
->willReturn($response);
$handler = new ExceptionHandler($container);
$return = $handler->process($request, $returnResponseHandler);
$this->assertEquals($response, $return);
$return = $handler->process($request, $throwExceptionHandler);
$this->assertEquals($response, $return);
}
}

View File

@ -0,0 +1,85 @@
<?php
namespace Engelsystem\Test\Unit\Middleware;
use Engelsystem\Http\Request;
use Engelsystem\Middleware\LegacyMiddleware;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
class LegacyMiddlewareTest extends TestCase
{
/**
* @covers \Engelsystem\Middleware\LegacyMiddleware::__construct
* @covers \Engelsystem\Middleware\LegacyMiddleware::process
*/
public function testRegister()
{
/** @var ContainerInterface|MockObject $container */
$container = $this->getMockForAbstractClass(ContainerInterface::class);
/** @var LegacyMiddleware|MockObject $middleware */
$middleware = $this->getMockBuilder(LegacyMiddleware::class)
->setConstructorArgs([$container])
->setMethods(['loadPage', 'renderPage'])
->getMock();
/** @var Request|MockObject $defaultRequest */
$defaultRequest = $this->createMock(Request::class);
/** @var ParameterBag|MockObject $parameters */
$parameters = $this->createMock(ParameterBag::class);
/** @var ResponseInterface|MockObject $response */
$response = $this->getMockForAbstractClass(ResponseInterface::class);
/** @var RequestHandlerInterface|MockObject $handler */
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
/** @var ServerRequestInterface|MockObject $request */
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
$middleware->expects($this->exactly(2))
->method('loadPage')
->withConsecutive(['user_worklog'], ['login'])
->willReturnOnConsecutiveCalls(
['title', 'content'],
['title2', 'content2']
);
$middleware->expects($this->exactly(2))
->method('renderPage')
->withConsecutive(
['user_worklog', 'title', 'content'],
['login', 'title2', 'content2']
)
->willReturn($response);
$container->expects($this->atLeastOnce())
->method('get')
->with('request')
->willReturn($defaultRequest);
$defaultRequest->query = $parameters;
$defaultRequest->expects($this->once())
->method('path')
->willReturn('user-worklog');
$parameters->expects($this->exactly(3))
->method('get')
->with('p')
->willReturnOnConsecutiveCalls(
null,
'foo',
'/'
);
$handler->expects($this->once())
->method('handle')
->with($request)
->willReturn($response);
$middleware->process($request, $handler);
$middleware->process($request, $handler);
$middleware->process($request, $handler);
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace Engelsystem\Test\Unit\Middleware;
use Engelsystem\Middleware\NotFoundResponse;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class NotFoundResponseTest extends TestCase
{
/**
* @covers \Engelsystem\Middleware\NotFoundResponse::process
*/
public function testRegister()
{
/** @var NotFoundResponse|MockObject $middleware */
$middleware = $this->getMockBuilder(NotFoundResponse::class)
->setMethods(['renderPage'])
->getMock();
/** @var ResponseInterface|MockObject $response */
$response = $this->getMockForAbstractClass(ResponseInterface::class);
/** @var RequestHandlerInterface|MockObject $handler */
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
/** @var ServerRequestInterface|MockObject $request */
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
$middleware->expects($this->once())
->method('renderPage')
->willReturn($response);
$handler->expects($this->never())
->method('handle');
$middleware->process($request, $handler);
}
}

View File

@ -0,0 +1,71 @@
<?php
namespace Engelsystem\Test\Unit\Middleware;
use Engelsystem\Middleware\SendResponseHandler;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class SendResponseHandlerTest extends TestCase
{
/**
* @covers \Engelsystem\Middleware\SendResponseHandler::process
*/
public function testRegister()
{
/** @var SendResponseHandler|MockObject $middleware */
$middleware = $this->getMockBuilder(SendResponseHandler::class)
->setMethods(['headersSent', 'sendHeader'])
->getMock();
/** @var ServerRequestInterface|MockObject $request */
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
/** @var ResponseInterface|MockObject $response */
$response = $this->getMockForAbstractClass(ResponseInterface::class);
/** @var RequestHandlerInterface|MockObject $handler */
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
$middleware->expects($this->atLeastOnce())
->method('headersSent')
->willReturnOnConsecutiveCalls(true, false);
$middleware->expects($this->exactly(4))
->method('sendHeader')
->withConsecutive(
['HTTP/0.7 505 Something went wrong!', true, 505],
['Foo: bar', false],
['lorem: ipsum', false],
['lorem: dolor', false]
);
$handler->expects($this->exactly(2))
->method('handle')
->with($request)
->willReturn($response);
$response->expects($this->exactly(2))
->method('getBody')
->willReturn('Lorem Ipsum!');
$response->expects($this->atLeastOnce())
->method('getProtocolVersion')
->willReturn('0.7');
$response->expects($this->atLeastOnce())
->method('getStatusCode')
->willReturn(505);
$response->expects($this->once())
->method('getReasonPhrase')
->willReturn('Something went wrong!');
$response->expects($this->once())
->method('getHeaders')
->willReturn(['Foo' => ['bar'], 'lorem' => ['ipsum', 'dolor']]);
$this->expectOutputString('Lorem Ipsum!Lorem Ipsum!');
$middleware->process($request, $handler);
$middleware->process($request, $handler);
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace Engelsystem\Test\Unit\Middleware\Stub;
use Exception;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ExceptionMiddlewareHandler implements RequestHandlerInterface
{
/**
* Throws an exception
*
* @param ServerRequestInterface $request
* @return ResponseInterface
* @throws Exception
*/
public function handle(ServerRequestInterface $request): ResponseInterface
{
throw new Exception('Boooom!');
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace Engelsystem\Test\Unit\Middleware\Stub;
class NotARealMiddleware
{
// I'm not a middleware!
}

View File

@ -0,0 +1,36 @@
<?php
namespace Engelsystem\Test\Unit\Middleware\Stub;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ReturnResponseMiddleware implements MiddlewareInterface
{
/** @var ResponseInterface */
protected $response;
public function __construct(ResponseInterface $response)
{
$this->response = $response;
}
/**
* Process an incoming server request and return a response, optionally delegating
* response creation to a handler.
*
* Could be used to group middleware
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
return $this->response;
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace Engelsystem\Test\Unit\Middleware\Stub;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ReturnResponseMiddlewareHandler implements RequestHandlerInterface
{
/** @var ResponseInterface */
protected $response;
public function __construct(ResponseInterface $response)
{
$this->response = $response;
}
/**
* Returns a given response
*
* @param ServerRequestInterface $request
* @return ResponseInterface
* @throws \Exception
*/
public function handle(ServerRequestInterface $request): ResponseInterface
{
return $this->response;
}
}