summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authormsquare <msquare@notrademark.de>2019-07-21 13:32:45 +0200
committerGitHub <noreply@github.com>2019-07-21 13:32:45 +0200
commitd4d4b409b6fd96ca297af323936b8922d45b6eda (patch)
tree6c8efa1a1e429f3965820838796cb4b97cd2df11 /tests
parentd5bf7fd065a5ea93dea9fd55e6ac225ee062a3db (diff)
parent51a3c6eb44a5dbdf9d7a3cfac678f0d29b0d3eef (diff)
Merge pull request #622 from MyIgel/controllers
AuthController (login, logout), use templating, replaced gettext, input validation
Diffstat (limited to 'tests')
-rw-r--r--tests/Unit/Controllers/AuthControllerTest.php142
-rw-r--r--tests/Unit/Controllers/BaseControllerTest.php2
-rw-r--r--tests/Unit/Controllers/Metrics/MetricsEngineTest.php11
-rw-r--r--tests/Unit/Controllers/Stub/ControllerImplementation.php8
-rw-r--r--tests/Unit/Helpers/AuthenticatorServiceProviderTest.php9
-rw-r--r--tests/Unit/Helpers/AuthenticatorTest.php125
-rw-r--r--tests/Unit/Helpers/Translation/Assets/fo_OO/default.mobin0 -> 73 bytes
-rw-r--r--tests/Unit/Helpers/Translation/Assets/fo_OO/default.po3
-rw-r--r--tests/Unit/Helpers/Translation/GettextTranslatorTest.php67
-rw-r--r--tests/Unit/Helpers/Translation/TranslationServiceProviderTest.php (renamed from tests/Unit/Helpers/TranslationServiceProviderTest.php)62
-rw-r--r--tests/Unit/Helpers/Translation/TranslatorTest.php134
-rw-r--r--tests/Unit/Helpers/TranslatorTest.php90
-rw-r--r--tests/Unit/HelpersTest.php2
-rw-r--r--tests/Unit/Http/Exceptions/ValidationExceptionTest.php25
-rw-r--r--tests/Unit/Http/UrlGeneratorServiceProviderTest.php5
-rw-r--r--tests/Unit/Http/Validation/Rules/InTest.php19
-rw-r--r--tests/Unit/Http/Validation/Rules/NotInTest.php20
-rw-r--r--tests/Unit/Http/Validation/Stub/ValidatesRequestImplementation.php27
-rw-r--r--tests/Unit/Http/Validation/ValidatesRequestTest.php46
-rw-r--r--tests/Unit/Http/Validation/ValidationServiceProviderTest.php34
-rw-r--r--tests/Unit/Http/Validation/ValidatorTest.php142
-rw-r--r--tests/Unit/Middleware/ErrorHandlerTest.php74
-rw-r--r--tests/Unit/Middleware/LegacyMiddlewareTest.php2
-rw-r--r--tests/Unit/Middleware/SetLocaleTest.php2
-rw-r--r--tests/Unit/Renderer/EngineTest.php25
-rw-r--r--tests/Unit/Renderer/HtmlEngineTest.php5
-rw-r--r--tests/Unit/Renderer/Stub/EngineImplementation.php32
-rw-r--r--tests/Unit/Renderer/Twig/Extensions/TranslationTest.php2
-rw-r--r--tests/Unit/Renderer/TwigEngineTest.php12
29 files changed, 971 insertions, 156 deletions
diff --git a/tests/Unit/Controllers/AuthControllerTest.php b/tests/Unit/Controllers/AuthControllerTest.php
index c5349cda..c3d9659c 100644
--- a/tests/Unit/Controllers/AuthControllerTest.php
+++ b/tests/Unit/Controllers/AuthControllerTest.php
@@ -3,40 +3,166 @@
namespace Engelsystem\Test\Unit\Controllers;
use Engelsystem\Controllers\AuthController;
+use Engelsystem\Helpers\Authenticator;
+use Engelsystem\Http\Exceptions\ValidationException;
+use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
use Engelsystem\Http\UrlGeneratorInterface;
+use Engelsystem\Http\Validation\Validator;
+use Engelsystem\Models\User\Settings;
+use Engelsystem\Models\User\User;
+use Engelsystem\Test\Unit\HasDatabase;
+use Illuminate\Support\Collection;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
+use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
class AuthControllerTest extends TestCase
{
+ use HasDatabase;
+
/**
* @covers \Engelsystem\Controllers\AuthController::__construct
- * @covers \Engelsystem\Controllers\AuthController::logout
+ * @covers \Engelsystem\Controllers\AuthController::login
+ * @covers \Engelsystem\Controllers\AuthController::showLogin
*/
- public function testLogout()
+ public function testLogin()
{
/** @var Response|MockObject $response */
$response = $this->createMock(Response::class);
/** @var SessionInterface|MockObject $session */
- $session = $this->getMockForAbstractClass(SessionInterface::class);
/** @var UrlGeneratorInterface|MockObject $url */
- $url = $this->getMockForAbstractClass(UrlGeneratorInterface::class);
+ /** @var Authenticator|MockObject $auth */
+ list(, $session, $url, $auth) = $this->getMocks();
$session->expects($this->once())
- ->method('invalidate');
+ ->method('get')
+ ->with('errors', [])
+ ->willReturn(['foo' => 'bar']);
+ $response->expects($this->once())
+ ->method('withView')
+ ->with('pages/login')
+ ->willReturn($response);
+
+ $controller = new AuthController($response, $session, $url, $auth);
+ $controller->login();
+ }
+
+ /**
+ * @covers \Engelsystem\Controllers\AuthController::postLogin
+ */
+ public function testPostLogin()
+ {
+ $this->initDatabase();
+ $request = new Request();
+ /** @var Response|MockObject $response */
+ $response = $this->createMock(Response::class);
+ /** @var UrlGeneratorInterface|MockObject $url */
+ /** @var Authenticator|MockObject $auth */
+ list(, , $url, $auth) = $this->getMocks();
+ $session = new Session(new MockArraySessionStorage());
+ /** @var Validator|MockObject $validator */
+ $validator = new Validator();
+
+ $user = new User([
+ 'name' => 'foo',
+ 'password' => '',
+ 'email' => '',
+ 'api_key' => '',
+ 'last_login_at' => null,
+ ]);
+ $user->forceFill(['id' => 42]);
+ $user->save();
+
+ $settings = new Settings(['language' => 'de_DE', 'theme' => '']);
+ $settings->user()
+ ->associate($user)
+ ->save();
+
+ $auth->expects($this->exactly(2))
+ ->method('authenticate')
+ ->with('foo', 'bar')
+ ->willReturnOnConsecutiveCalls(null, $user);
+
+ $response->expects($this->once())
+ ->method('withView')
+ ->with('pages/login', ['errors' => Collection::make(['auth.not-found']), 'show_password_recovery' => true])
+ ->willReturn($response);
$response->expects($this->once())
->method('redirectTo')
- ->with('https://foo.bar/');
+ ->with('news')
+ ->willReturn($response);
+
+ // No credentials
+ $controller = new AuthController($response, $session, $url, $auth);
+ $controller->setValidator($validator);
+ try {
+ $controller->postLogin($request);
+ $this->fail('Login without credentials possible');
+ } catch (ValidationException $e) {
+ }
+
+ // Missing password
+ $request = new Request([], ['login' => 'foo']);
+ try {
+ $controller->postLogin($request);
+ $this->fail('Login without password possible');
+ } catch (ValidationException $e) {
+ }
+
+ // No user found
+ $request = new Request([], ['login' => 'foo', 'password' => 'bar']);
+ $controller->postLogin($request);
+ $this->assertEquals([], $session->all());
+
+ // Authenticated user
+ $controller->postLogin($request);
+
+ $this->assertNotNull($user->last_login_at);
+ $this->assertEquals(['user_id' => 42, 'locale' => 'de_DE'], $session->all());
+ }
+
+ /**
+ * @covers \Engelsystem\Controllers\AuthController::logout
+ */
+ public function testLogout()
+ {
+ /** @var Response $response */
+ /** @var SessionInterface|MockObject $session */
+ /** @var UrlGeneratorInterface|MockObject $url */
+ /** @var Authenticator|MockObject $auth */
+ list($response, $session, $url, $auth) = $this->getMocks();
+
+ $session->expects($this->once())
+ ->method('invalidate');
$url->expects($this->once())
->method('to')
->with('/')
->willReturn('https://foo.bar/');
- $controller = new AuthController($response, $session, $url);
- $controller->logout();
+ $controller = new AuthController($response, $session, $url, $auth);
+ $return = $controller->logout();
+
+ $this->assertEquals(['https://foo.bar/'], $return->getHeader('location'));
+ }
+
+ /**
+ * @return array
+ */
+ protected function getMocks()
+ {
+ $response = new Response();
+ /** @var SessionInterface|MockObject $session */
+ $session = $this->getMockForAbstractClass(SessionInterface::class);
+ /** @var UrlGeneratorInterface|MockObject $url */
+ $url = $this->getMockForAbstractClass(UrlGeneratorInterface::class);
+ /** @var Authenticator|MockObject $auth */
+ $auth = $this->createMock(Authenticator::class);
+
+ return [$response, $session, $url, $auth];
}
}
diff --git a/tests/Unit/Controllers/BaseControllerTest.php b/tests/Unit/Controllers/BaseControllerTest.php
index 738b538f..2adc9dc7 100644
--- a/tests/Unit/Controllers/BaseControllerTest.php
+++ b/tests/Unit/Controllers/BaseControllerTest.php
@@ -21,5 +21,7 @@ class BaseControllerTest extends TestCase
'dolor',
],
], $controller->getPermissions());
+
+ $this->assertTrue(method_exists($controller, 'setValidator'));
}
}
diff --git a/tests/Unit/Controllers/Metrics/MetricsEngineTest.php b/tests/Unit/Controllers/Metrics/MetricsEngineTest.php
index 38817b36..87a7dc88 100644
--- a/tests/Unit/Controllers/Metrics/MetricsEngineTest.php
+++ b/tests/Unit/Controllers/Metrics/MetricsEngineTest.php
@@ -66,4 +66,15 @@ class MetricsEngineTest extends TestCase
$this->assertFalse($engine->canRender('/metrics.foo'));
$this->assertTrue($engine->canRender('/metrics'));
}
+
+ /**
+ * @covers \Engelsystem\Controllers\Metrics\MetricsEngine::share
+ */
+ public function testShare()
+ {
+ $engine = new MetricsEngine();
+
+ $engine->share('foo', 42);
+ $this->assertEquals('', $engine->get('/metrics'));
+ }
}
diff --git a/tests/Unit/Controllers/Stub/ControllerImplementation.php b/tests/Unit/Controllers/Stub/ControllerImplementation.php
index 01d9f250..a8bf538c 100644
--- a/tests/Unit/Controllers/Stub/ControllerImplementation.php
+++ b/tests/Unit/Controllers/Stub/ControllerImplementation.php
@@ -14,12 +14,4 @@ class ControllerImplementation extends BaseController
'dolor',
],
];
-
- /**
- * @param array $permissions
- */
- public function setPermissions(array $permissions)
- {
- $this->permissions = $permissions;
- }
}
diff --git a/tests/Unit/Helpers/AuthenticatorServiceProviderTest.php b/tests/Unit/Helpers/AuthenticatorServiceProviderTest.php
index b1767ebc..ab9b23ec 100644
--- a/tests/Unit/Helpers/AuthenticatorServiceProviderTest.php
+++ b/tests/Unit/Helpers/AuthenticatorServiceProviderTest.php
@@ -3,6 +3,7 @@
namespace Engelsystem\Test\Unit\Helpers;
use Engelsystem\Application;
+use Engelsystem\Config\Config;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Helpers\AuthenticatorServiceProvider;
use Engelsystem\Http\Request;
@@ -19,11 +20,19 @@ class AuthenticatorServiceProviderTest extends ServiceProviderTest
$app = new Application();
$app->bind(ServerRequestInterface::class, Request::class);
+ $config = new Config();
+ $config->set('password_algorithm', PASSWORD_DEFAULT);
+ $app->instance('config', $config);
+
$serviceProvider = new AuthenticatorServiceProvider($app);
$serviceProvider->register();
$this->assertInstanceOf(Authenticator::class, $app->get(Authenticator::class));
$this->assertInstanceOf(Authenticator::class, $app->get('authenticator'));
$this->assertInstanceOf(Authenticator::class, $app->get('auth'));
+
+ /** @var Authenticator $auth */
+ $auth = $app->get(Authenticator::class);
+ $this->assertEquals(PASSWORD_DEFAULT, $auth->getPasswordAlgorithm());
}
}
diff --git a/tests/Unit/Helpers/AuthenticatorTest.php b/tests/Unit/Helpers/AuthenticatorTest.php
index 400278f2..83dc72ad 100644
--- a/tests/Unit/Helpers/AuthenticatorTest.php
+++ b/tests/Unit/Helpers/AuthenticatorTest.php
@@ -4,6 +4,7 @@ namespace Engelsystem\Test\Unit\Helpers;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Models\User\User;
+use Engelsystem\Test\Unit\HasDatabase;
use Engelsystem\Test\Unit\Helpers\Stub\UserModelImplementation;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit\Framework\MockObject\MockObject;
@@ -12,6 +13,8 @@ use Symfony\Component\HttpFoundation\Session\Session;
class AuthenticatorTest extends ServiceProviderTest
{
+ use HasDatabase;
+
/**
* @covers \Engelsystem\Helpers\Authenticator::__construct(
* @covers \Engelsystem\Helpers\Authenticator::user
@@ -29,7 +32,7 @@ class AuthenticatorTest extends ServiceProviderTest
$session->expects($this->exactly(3))
->method('get')
- ->with('uid')
+ ->with('user_id')
->willReturnOnConsecutiveCalls(
null,
42,
@@ -114,16 +117,13 @@ class AuthenticatorTest extends ServiceProviderTest
/** @var User|MockObject $user */
$user = $this->createMock(User::class);
- $user->expects($this->once())
- ->method('save');
-
- $session->expects($this->exactly(2))
+ $session->expects($this->once())
->method('get')
- ->with('uid')
+ ->with('user_id')
->willReturn(42);
$session->expects($this->once())
->method('remove')
- ->with('uid');
+ ->with('user_id');
/** @var Authenticator|MockObject $auth */
$auth = $this->getMockBuilder(Authenticator::class)
@@ -151,4 +151,115 @@ class AuthenticatorTest extends ServiceProviderTest
// Permissions cached
$this->assertTrue($auth->can('bar'));
}
+
+ /**
+ * @covers \Engelsystem\Helpers\Authenticator::authenticate
+ */
+ public function testAuthenticate()
+ {
+ $this->initDatabase();
+
+ /** @var ServerRequestInterface|MockObject $request */
+ $request = $this->getMockForAbstractClass(ServerRequestInterface::class);
+ /** @var Session|MockObject $session */
+ $session = $this->createMock(Session::class);
+ $userRepository = new User();
+
+ (new User([
+ 'name' => 'lorem',
+ 'password' => password_hash('testing', PASSWORD_DEFAULT),
+ 'email' => 'lorem@foo.bar',
+ 'api_key' => '',
+ ]))->save();
+ (new User([
+ 'name' => 'ipsum',
+ 'password' => '',
+ 'email' => 'ipsum@foo.bar',
+ 'api_key' => '',
+ ]))->save();
+
+ $auth = new Authenticator($request, $session, $userRepository);
+ $this->assertNull($auth->authenticate('not-existing', 'foo'));
+ $this->assertNull($auth->authenticate('ipsum', 'wrong-password'));
+ $this->assertInstanceOf(User::class, $auth->authenticate('lorem', 'testing'));
+ $this->assertInstanceOf(User::class, $auth->authenticate('lorem@foo.bar', 'testing'));
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Authenticator::verifyPassword
+ */
+ public function testVerifyPassword()
+ {
+ $this->initDatabase();
+ $password = password_hash('testing', PASSWORD_ARGON2I);
+ $user = new User([
+ 'name' => 'lorem',
+ 'password' => $password,
+ 'email' => 'lorem@foo.bar',
+ 'api_key' => '',
+ ]);
+ $user->save();
+
+ /** @var Authenticator|MockObject $auth */
+ $auth = $this->getMockBuilder(Authenticator::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setPassword'])
+ ->getMock();
+
+ $auth->expects($this->once())
+ ->method('setPassword')
+ ->with($user, 'testing');
+ $auth->setPasswordAlgorithm(PASSWORD_BCRYPT);
+
+ $this->assertFalse($auth->verifyPassword($user, 'randomStuff'));
+ $this->assertTrue($auth->verifyPassword($user, 'testing'));
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Authenticator::setPassword
+ */
+ public function testSetPassword()
+ {
+ $this->initDatabase();
+ $user = new User([
+ 'name' => 'ipsum',
+ 'password' => '',
+ 'email' => 'ipsum@foo.bar',
+ 'api_key' => '',
+ ]);
+ $user->save();
+
+ $auth = $this->getAuthenticator();
+ $auth->setPasswordAlgorithm(PASSWORD_ARGON2I);
+
+ $auth->setPassword($user, 'FooBar');
+ $this->assertTrue($user->isClean());
+
+ $this->assertTrue(password_verify('FooBar', $user->password));
+ $this->assertFalse(password_needs_rehash($user->password, PASSWORD_ARGON2I));
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Authenticator::setPasswordAlgorithm
+ * @covers \Engelsystem\Helpers\Authenticator::getPasswordAlgorithm
+ */
+ public function testPasswordAlgorithm()
+ {
+ $auth = $this->getAuthenticator();
+
+ $auth->setPasswordAlgorithm(PASSWORD_ARGON2I);
+ $this->assertEquals(PASSWORD_ARGON2I, $auth->getPasswordAlgorithm());
+ }
+
+ /**
+ * @return Authenticator
+ */
+ protected function getAuthenticator()
+ {
+ return new class extends Authenticator
+ {
+ /** @noinspection PhpMissingParentConstructorInspection */
+ public function __construct() { }
+ };
+ }
}
diff --git a/tests/Unit/Helpers/Translation/Assets/fo_OO/default.mo b/tests/Unit/Helpers/Translation/Assets/fo_OO/default.mo
new file mode 100644
index 00000000..96f1f3ca
--- /dev/null
+++ b/tests/Unit/Helpers/Translation/Assets/fo_OO/default.mo
Binary files differ
diff --git a/tests/Unit/Helpers/Translation/Assets/fo_OO/default.po b/tests/Unit/Helpers/Translation/Assets/fo_OO/default.po
new file mode 100644
index 00000000..015bc36d
--- /dev/null
+++ b/tests/Unit/Helpers/Translation/Assets/fo_OO/default.po
@@ -0,0 +1,3 @@
+# Testing content
+msgid "foo.bar"
+msgstr "Foo Bar!"
diff --git a/tests/Unit/Helpers/Translation/GettextTranslatorTest.php b/tests/Unit/Helpers/Translation/GettextTranslatorTest.php
new file mode 100644
index 00000000..825cf5b7
--- /dev/null
+++ b/tests/Unit/Helpers/Translation/GettextTranslatorTest.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Helpers\Translation;
+
+use Engelsystem\Helpers\Translation\GettextTranslator;
+use Engelsystem\Helpers\Translation\TranslationNotFound;
+use Engelsystem\Test\Unit\ServiceProviderTest;
+use Gettext\Translation;
+use Gettext\Translations;
+
+class GettextTranslatorTest extends ServiceProviderTest
+{
+ /**
+ * @covers \Engelsystem\Helpers\Translation\GettextTranslator::assertHasTranslation()
+ */
+ public function testNoTranslation()
+ {
+ $translations = $this->getTranslations();
+
+ $translator = new GettextTranslator();
+ $translator->loadTranslations($translations);
+
+ $this->assertEquals('Translation!', $translator->gettext('test.value'));
+
+ $this->expectException(TranslationNotFound::class);
+ $this->expectExceptionMessage('//foo.bar');
+
+ $translator->gettext('foo.bar');
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Translation\GettextTranslator::dpgettext()
+ */
+ public function testDpgettext()
+ {
+ $translations = $this->getTranslations();
+
+ $translator = new GettextTranslator();
+ $translator->loadTranslations($translations);
+
+ $this->assertEquals('Translation!', $translator->dpgettext(null, null, 'test.value'));
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Translation\GettextTranslator::dnpgettext()
+ */
+ public function testDnpgettext()
+ {
+ $translations = $this->getTranslations();
+
+ $translator = new GettextTranslator();
+ $translator->loadTranslations($translations);
+
+ $this->assertEquals('Translations!', $translator->dnpgettext(null, null, 'test.value', 'test.values', 2));
+ }
+
+ protected function getTranslations(): Translations
+ {
+ $translations = new Translations();
+ $translations[] =
+ (new Translation(null, 'test.value', 'test.values'))
+ ->setTranslation('Translation!')
+ ->setPluralTranslations(['Translations!']);
+
+ return $translations;
+ }
+}
diff --git a/tests/Unit/Helpers/TranslationServiceProviderTest.php b/tests/Unit/Helpers/Translation/TranslationServiceProviderTest.php
index 41c08aa5..91307bdd 100644
--- a/tests/Unit/Helpers/TranslationServiceProviderTest.php
+++ b/tests/Unit/Helpers/Translation/TranslationServiceProviderTest.php
@@ -1,10 +1,10 @@
<?php
-namespace Engelsystem\Test\Unit\Helpers;
+namespace Engelsystem\Test\Unit\Helpers\Translation;
use Engelsystem\Config\Config;
-use Engelsystem\Helpers\TranslationServiceProvider;
-use Engelsystem\Helpers\Translator;
+use Engelsystem\Helpers\Translation\TranslationServiceProvider;
+use Engelsystem\Helpers\Translation\Translator;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\HttpFoundation\Session\Session;
@@ -12,13 +12,16 @@ use Symfony\Component\HttpFoundation\Session\Session;
class TranslationServiceProviderTest extends ServiceProviderTest
{
/**
- * @covers \Engelsystem\Helpers\TranslationServiceProvider::register()
+ * @covers \Engelsystem\Helpers\Translation\TranslationServiceProvider::register()
*/
- public function testRegister()
+ public function testRegister(): void
{
+ $defaultLocale = 'fo_OO';
+ $locale = 'te_ST.WTF-9';
+ $locales = ['fo_OO' => 'Foo', 'fo_OO.BAR' => 'Foo (Bar)', 'te_ST.WTF-9' => 'WTF\'s Testing?'];
+ $config = new Config(['locales' => $locales, 'default_locale' => $defaultLocale]);
+
$app = $this->getApp(['make', 'instance', 'get']);
- /** @var Config|MockObject $config */
- $config = $this->createMock(Config::class);
/** @var Session|MockObject $session */
$session = $this->createMock(Session::class);
/** @var Translator|MockObject $translator */
@@ -27,31 +30,14 @@ class TranslationServiceProviderTest extends ServiceProviderTest
/** @var TranslationServiceProvider|MockObject $serviceProvider */
$serviceProvider = $this->getMockBuilder(TranslationServiceProvider::class)
->setConstructorArgs([$app])
- ->setMethods(['initGettext', 'setLocale'])
+ ->setMethods(['setLocale'])
->getMock();
- $serviceProvider->expects($this->once())
- ->method('initGettext');
-
$app->expects($this->exactly(2))
->method('get')
->withConsecutive(['config'], ['session'])
->willReturnOnConsecutiveCalls($config, $session);
- $defaultLocale = 'fo_OO';
- $locale = 'te_ST.WTF-9';
- $locales = ['fo_OO' => 'Foo', 'fo_OO.BAR' => 'Foo (Bar)', 'te_ST.WTF-9' => 'WTF\'s Testing?'];
- $config->expects($this->exactly(2))
- ->method('get')
- ->withConsecutive(
- ['locales'],
- ['default_locale']
- )
- ->willReturnOnConsecutiveCalls(
- $locales,
- $defaultLocale
- );
-
$session->expects($this->once())
->method('get')
->with('locale', $defaultLocale)
@@ -65,9 +51,11 @@ class TranslationServiceProviderTest extends ServiceProviderTest
->with(
Translator::class,
[
- 'locale' => $locale,
- 'locales' => $locales,
- 'localeChangeCallback' => [$serviceProvider, 'setLocale'],
+ 'locale' => $locale,
+ 'locales' => $locales,
+ 'fallbackLocale' => 'en_US',
+ 'getTranslatorCallback' => [$serviceProvider, 'getTranslator'],
+ 'localeChangeCallback' => [$serviceProvider, 'setLocale'],
]
)
->willReturn($translator);
@@ -81,4 +69,22 @@ class TranslationServiceProviderTest extends ServiceProviderTest
$serviceProvider->register();
}
+
+ /**
+ * @covers \Engelsystem\Helpers\Translation\TranslationServiceProvider::getTranslator()
+ */
+ public function testGetTranslator(): void
+ {
+ $app = $this->getApp(['get']);
+ $serviceProvider = new TranslationServiceProvider($app);
+
+ $this->setExpects($app, 'get', ['path.lang'], __DIR__ . '/Assets');
+
+ // Get translator
+ $translator = $serviceProvider->getTranslator('fo_OO');
+ $this->assertEquals('Foo Bar!', $translator->gettext('foo.bar'));
+
+ // Retry from cache
+ $serviceProvider->getTranslator('fo_OO');
+ }
}
diff --git a/tests/Unit/Helpers/Translation/TranslatorTest.php b/tests/Unit/Helpers/Translation/TranslatorTest.php
new file mode 100644
index 00000000..c173209a
--- /dev/null
+++ b/tests/Unit/Helpers/Translation/TranslatorTest.php
@@ -0,0 +1,134 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Helpers\Translation;
+
+use Engelsystem\Helpers\Translation\GettextTranslator;
+use Engelsystem\Helpers\Translation\TranslationNotFound;
+use Engelsystem\Helpers\Translation\Translator;
+use Engelsystem\Test\Unit\ServiceProviderTest;
+use PHPUnit\Framework\MockObject\MockObject;
+use stdClass;
+
+class TranslatorTest extends ServiceProviderTest
+{
+ /**
+ * @covers \Engelsystem\Helpers\Translation\Translator::__construct
+ * @covers \Engelsystem\Helpers\Translation\Translator::getLocale
+ * @covers \Engelsystem\Helpers\Translation\Translator::getLocales
+ * @covers \Engelsystem\Helpers\Translation\Translator::hasLocale
+ * @covers \Engelsystem\Helpers\Translation\Translator::setLocale
+ * @covers \Engelsystem\Helpers\Translation\Translator::setLocales
+ */
+ public function testInit()
+ {
+ $locales = ['te_ST' => 'Tests', 'fo_OO' => 'SomeFOO'];
+ $locale = 'te_ST';
+
+ /** @var callable|MockObject $localeChange */
+ $localeChange = $this->getMockBuilder(stdClass::class)
+ ->setMethods(['__invoke'])
+ ->getMock();
+ $localeChange->expects($this->exactly(2))
+ ->method('__invoke')
+ ->withConsecutive(['te_ST'], ['fo_OO']);
+
+ $translator = new Translator($locale, 'fo_OO', function () { }, $locales, $localeChange);
+
+ $this->assertEquals($locales, $translator->getLocales());
+ $this->assertEquals($locale, $translator->getLocale());
+
+ $translator->setLocale('fo_OO');
+ $this->assertEquals('fo_OO', $translator->getLocale());
+
+ $newLocales = ['lo_RM' => 'Lorem', 'ip_SU-M' => 'Ipsum'];
+ $translator->setLocales($newLocales);
+ $this->assertEquals($newLocales, $translator->getLocales());
+
+ $this->assertTrue($translator->hasLocale('ip_SU-M'));
+ $this->assertFalse($translator->hasLocale('te_ST'));
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Translation\Translator::translate
+ */
+ public function testTranslate()
+ {
+ /** @var Translator|MockObject $translator */
+ $translator = $this->getMockBuilder(Translator::class)
+ ->setConstructorArgs(['de_DE', 'en_US', function () { }, ['de_DE' => 'Deutsch']])
+ ->setMethods(['translateText'])
+ ->getMock();
+ $translator->expects($this->exactly(2))
+ ->method('translateText')
+ ->withConsecutive(['gettext', ['Hello!'], []], ['gettext', ['My favourite number is %u!'], [3]])
+ ->willReturnOnConsecutiveCalls('Hallo!', 'Meine Lieblingszahl ist die 3!');
+
+ $return = $translator->translate('Hello!');
+ $this->assertEquals('Hallo!', $return);
+
+ $return = $translator->translate('My favourite number is %u!', [3]);
+ $this->assertEquals('Meine Lieblingszahl ist die 3!', $return);
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Translation\Translator::translatePlural
+ */
+ public function testTranslatePlural()
+ {
+ /** @var Translator|MockObject $translator */
+ $translator = $this->getMockBuilder(Translator::class)
+ ->setConstructorArgs(['de_DE', 'en_US', function () { }, ['de_DE' => 'Deutsch']])
+ ->setMethods(['translateText'])
+ ->getMock();
+ $translator->expects($this->once())
+ ->method('translateText')
+ ->with('ngettext', ['%s apple', '%s apples', 2], [2])
+ ->willReturn('2 Äpfel');
+
+ $return = $translator->translatePlural('%s apple', '%s apples', 2, [2]);
+ $this->assertEquals('2 Äpfel', $return);
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Translation\Translator::translatePlural
+ * @covers \Engelsystem\Helpers\Translation\Translator::translateText
+ * @covers \Engelsystem\Helpers\Translation\Translator::replaceText
+ */
+ public function testReplaceText()
+ {
+ /** @var GettextTranslator|MockObject $gtt */
+ $gtt = $this->createMock(GettextTranslator::class);
+ /** @var callable|MockObject $getTranslator */
+ $getTranslator = $this->getMockBuilder(stdClass::class)
+ ->setMethods(['__invoke'])
+ ->getMock();
+ $getTranslator->expects($this->exactly(5))
+ ->method('__invoke')
+ ->withConsecutive(['te_ST'], ['fo_OO'], ['te_ST'], ['fo_OO'], ['te_ST'])
+ ->willReturn($gtt);
+
+ $i = 0;
+ $gtt->expects($this->exactly(4))
+ ->method('gettext')
+ ->willReturnCallback(function () use (&$i) {
+ $i++;
+ if ($i != 4) {
+ throw new TranslationNotFound();
+ }
+
+ return 'Lorem %s???';
+ });
+ $this->setExpects($gtt, 'ngettext', ['foo.barf'], 'Lorem %s!');
+
+ $translator = new Translator('te_ST', 'fo_OO', $getTranslator, ['te_ST' => 'Test', 'fo_OO' => 'Foo']);
+
+ // No translation
+ $this->assertEquals('foo.bar', $translator->translate('foo.bar'));
+
+ // Fallback translation
+ $this->assertEquals('Lorem test2???', $translator->translate('foo.batz', ['test2']));
+
+ // Successful translation
+ $this->assertEquals('Lorem test3!', $translator->translatePlural('foo.barf', 'foo.bar2', 3, ['test3']));
+ }
+}
diff --git a/tests/Unit/Helpers/TranslatorTest.php b/tests/Unit/Helpers/TranslatorTest.php
deleted file mode 100644
index 45ca769b..00000000
--- a/tests/Unit/Helpers/TranslatorTest.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-namespace Engelsystem\Test\Unit\Helpers;
-
-use Engelsystem\Helpers\Translator;
-use Engelsystem\Test\Unit\ServiceProviderTest;
-use PHPUnit\Framework\MockObject\MockObject;
-use stdClass;
-
-class TranslatorTest extends ServiceProviderTest
-{
- /**
- * @covers \Engelsystem\Helpers\Translator::__construct
- * @covers \Engelsystem\Helpers\Translator::getLocale
- * @covers \Engelsystem\Helpers\Translator::getLocales
- * @covers \Engelsystem\Helpers\Translator::hasLocale
- * @covers \Engelsystem\Helpers\Translator::setLocale
- * @covers \Engelsystem\Helpers\Translator::setLocales
- */
- public function testInit()
- {
- $locales = ['te_ST.ER-01' => 'Tests', 'fo_OO' => 'SomeFOO'];
- $locale = 'te_ST.ER-01';
-
- /** @var callable|MockObject $callable */
- $callable = $this->getMockBuilder(stdClass::class)
- ->setMethods(['__invoke'])
- ->getMock();
- $callable->expects($this->exactly(2))
- ->method('__invoke')
- ->withConsecutive(['te_ST.ER-01'], ['fo_OO']);
-
- $translator = new Translator($locale, $locales, $callable);
-
- $this->assertEquals($locales, $translator->getLocales());
- $this->assertEquals($locale, $translator->getLocale());
-
- $translator->setLocale('fo_OO');
- $this->assertEquals('fo_OO', $translator->getLocale());
-
- $newLocales = ['lo_RM' => 'Lorem', 'ip_SU-M' => 'Ipsum'];
- $translator->setLocales($newLocales);
- $this->assertEquals($newLocales, $translator->getLocales());
-
- $this->assertTrue($translator->hasLocale('ip_SU-M'));
- $this->assertFalse($translator->hasLocale('te_ST.ER-01'));
- }
-
- /**
- * @covers \Engelsystem\Helpers\Translator::replaceText
- * @covers \Engelsystem\Helpers\Translator::translate
- */
- public function testTranslate()
- {
- /** @var Translator|MockObject $translator */
- $translator = $this->getMockBuilder(Translator::class)
- ->setConstructorArgs(['de_DE.UTF-8', ['de_DE.UTF-8' => 'Deutsch']])
- ->setMethods(['translateGettext'])
- ->getMock();
- $translator->expects($this->exactly(2))
- ->method('translateGettext')
- ->withConsecutive(['Hello!'], ['My favourite number is %u!'])
- ->willReturnOnConsecutiveCalls('Hallo!', 'Meine Lieblingszahl ist die %u!');
-
- $return = $translator->translate('Hello!');
- $this->assertEquals('Hallo!', $return);
-
- $return = $translator->translate('My favourite number is %u!', [3]);
- $this->assertEquals('Meine Lieblingszahl ist die 3!', $return);
- }
-
- /**
- * @covers \Engelsystem\Helpers\Translator::translatePlural
- */
- public function testTranslatePlural()
- {
- /** @var Translator|MockObject $translator */
- $translator = $this->getMockBuilder(Translator::class)
- ->setConstructorArgs(['de_DE.UTF-8', ['de_DE.UTF-8' => 'Deutsch']])
- ->setMethods(['translateGettextPlural'])
- ->getMock();
- $translator->expects($this->once())
- ->method('translateGettextPlural')
- ->with('%s apple', '%s apples', 2)
- ->willReturn('2 Äpfel');
-
- $return = $translator->translatePlural('%s apple', '%s apples', 2, [2]);
- $this->assertEquals('2 Äpfel', $return);
- }
-}
diff --git a/tests/Unit/HelpersTest.php b/tests/Unit/HelpersTest.php
index ad677cb3..09362a90 100644
--- a/tests/Unit/HelpersTest.php
+++ b/tests/Unit/HelpersTest.php
@@ -6,7 +6,7 @@ use Engelsystem\Application;
use Engelsystem\Config\Config;
use Engelsystem\Container\Container;
use Engelsystem\Helpers\Authenticator;
-use Engelsystem\Helpers\Translator;
+use Engelsystem\Helpers\Translation\Translator;
use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
use Engelsystem\Http\UrlGeneratorInterface;
diff --git a/tests/Unit/Http/Exceptions/ValidationExceptionTest.php b/tests/Unit/Http/Exceptions/ValidationExceptionTest.php
new file mode 100644
index 00000000..c5a38b5a
--- /dev/null
+++ b/tests/Unit/Http/Exceptions/ValidationExceptionTest.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Http\Exceptions;
+
+use Engelsystem\Http\Exceptions\ValidationException;
+use Engelsystem\Http\Validation\Validator;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+class ValidationExceptionTest extends TestCase
+{
+ /**
+ * @covers \Engelsystem\Http\Exceptions\ValidationException::__construct
+ * @covers \Engelsystem\Http\Exceptions\ValidationException::getValidator
+ */
+ public function testConstruct()
+ {
+ /** @var Validator|MockObject $validator */
+ $validator = $this->createMock(Validator::class);
+
+ $exception = new ValidationException($validator);
+
+ $this->assertEquals($validator, $exception->getValidator());
+ }
+}
diff --git a/tests/Unit/Http/UrlGeneratorServiceProviderTest.php b/tests/Unit/Http/UrlGeneratorServiceProviderTest.php
index 61bf3e7c..6d18f160 100644
--- a/tests/Unit/Http/UrlGeneratorServiceProviderTest.php
+++ b/tests/Unit/Http/UrlGeneratorServiceProviderTest.php
@@ -19,7 +19,7 @@ class UrlGeneratorServiceProviderTest extends ServiceProviderTest
$urlGenerator = $this->getMockBuilder(UrlGenerator::class)
->getMock();
- $app = $this->getApp();
+ $app = $this->getApp(['make', 'instance', 'bind']);
$this->setExpects($app, 'make', [UrlGenerator::class], $urlGenerator);
$app->expects($this->exactly(2))
@@ -29,6 +29,9 @@ class UrlGeneratorServiceProviderTest extends ServiceProviderTest
['http.urlGenerator', $urlGenerator],
[UrlGeneratorInterface::class, $urlGenerator]
);
+ $app->expects($this->once())
+ ->method('bind')
+ ->with(UrlGeneratorInterface::class, UrlGenerator::class);
$serviceProvider = new UrlGeneratorServiceProvider($app);
$serviceProvider->register();
diff --git a/tests/Unit/Http/Validation/Rules/InTest.php b/tests/Unit/Http/Validation/Rules/InTest.php
new file mode 100644
index 00000000..e5688d90
--- /dev/null
+++ b/tests/Unit/Http/Validation/Rules/InTest.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Http\Validation\Rules;
+
+use Engelsystem\Http\Validation\Rules\In;
+use Engelsystem\Test\Unit\TestCase;
+
+class InTest extends TestCase
+{
+ /**
+ * @covers \Engelsystem\Http\Validation\Rules\In::__construct
+ */
+ public function testConstruct()
+ {
+ $rule = new In('foo,bar');
+
+ $this->assertEquals(['foo', 'bar'], $rule->haystack);
+ }
+}
diff --git a/tests/Unit/Http/Validation/Rules/NotInTest.php b/tests/Unit/Http/Validation/Rules/NotInTest.php
new file mode 100644
index 00000000..9be12336
--- /dev/null
+++ b/tests/Unit/Http/Validation/Rules/NotInTest.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Http\Validation\Rules;
+
+use Engelsystem\Http\Validation\Rules\NotIn;
+use Engelsystem\Test\Unit\TestCase;
+
+class NotInTest extends TestCase
+{
+ /**
+ * @covers \Engelsystem\Http\Validation\Rules\NotIn::validate
+ */
+ public function testConstruct()
+ {
+ $rule = new NotIn('foo,bar');
+
+ $this->assertTrue($rule->validate('lorem'));
+ $this->assertFalse($rule->validate('foo'));
+ }
+}
diff --git a/tests/Unit/Http/Validation/Stub/ValidatesRequestImplementation.php b/tests/Unit/Http/Validation/Stub/ValidatesRequestImplementation.php
new file mode 100644
index 00000000..772b1dc9
--- /dev/null
+++ b/tests/Unit/Http/Validation/Stub/ValidatesRequestImplementation.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Http\Validation\Stub;
+
+use Engelsystem\Controllers\BaseController;
+use Engelsystem\Http\Request;
+
+class ValidatesRequestImplementation extends BaseController
+{
+ /**
+ * @param Request $request
+ * @param array $rules
+ * @return array
+ */
+ public function validateData(Request $request, array $rules)
+ {
+ return $this->validate($request, $rules);
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasValidator()
+ {
+ return !is_null($this->validator);
+ }
+}
diff --git a/tests/Unit/Http/Validation/ValidatesRequestTest.php b/tests/Unit/Http/Validation/ValidatesRequestTest.php
new file mode 100644
index 00000000..8011bd03
--- /dev/null
+++ b/tests/Unit/Http/Validation/ValidatesRequestTest.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Http\Validation;
+
+use Engelsystem\Http\Exceptions\ValidationException;
+use Engelsystem\Http\Request;
+use Engelsystem\Http\Validation\Validator;
+use Engelsystem\Test\Unit\Http\Validation\Stub\ValidatesRequestImplementation;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+class ValidatesRequestTest extends TestCase
+{
+ /**
+ * @covers \Engelsystem\Http\Validation\ValidatesRequest::validate
+ * @covers \Engelsystem\Http\Validation\ValidatesRequest::setValidator
+ */
+ public function testValidate()
+ {
+ /** @var Validator|MockObject $validator */
+ $validator = $this->createMock(Validator::class);
+ $validator->expects($this->exactly(2))
+ ->method('validate')
+ ->withConsecutive(
+ [['foo' => 'bar'], ['foo' => 'required']],
+ [[], ['foo' => 'required']]
+ )
+ ->willReturnOnConsecutiveCalls(
+ true,
+ false
+ );
+ $validator->expects($this->once())
+ ->method('getData')
+ ->willReturn(['foo' => 'bar']);
+
+ $implementation = new ValidatesRequestImplementation();
+ $implementation->setValidator($validator);
+
+ $return = $implementation->validateData(new Request([], ['foo' => 'bar']), ['foo' => 'required']);
+
+ $this->assertEquals(['foo' => 'bar'], $return);
+
+ $this->expectException(ValidationException::class);
+ $implementation->validateData(new Request([], []), ['foo' => 'required']);
+ }
+}
diff --git a/tests/Unit/Http/Validation/ValidationServiceProviderTest.php b/tests/Unit/Http/Validation/ValidationServiceProviderTest.php
new file mode 100644
index 00000000..969f4351
--- /dev/null
+++ b/tests/Unit/Http/Validation/ValidationServiceProviderTest.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Http\Validation;
+
+use Engelsystem\Application;
+use Engelsystem\Http\Validation\ValidationServiceProvider;
+use Engelsystem\Http\Validation\Validator;
+use Engelsystem\Test\Unit\Http\Validation\Stub\ValidatesRequestImplementation;
+use Engelsystem\Test\Unit\ServiceProviderTest;
+use stdClass;
+
+class ValidationServiceProviderTest extends ServiceProviderTest
+{
+ /**
+ * @covers \Engelsystem\Http\Validation\ValidationServiceProvider::register
+ */
+ public function testRegister()
+ {
+ $app = new Application();
+
+ $serviceProvider = new ValidationServiceProvider($app);
+ $serviceProvider->register();
+
+ $this->assertTrue($app->has(Validator::class));
+ $this->assertTrue($app->has('validator'));
+
+ /** @var ValidatesRequestImplementation $validatesRequest */
+ $validatesRequest = $app->make(ValidatesRequestImplementation::class);
+ $this->assertTrue($validatesRequest->hasValidator());
+
+ // Test afterResolving early return
+ $app->make(stdClass::class);
+ }
+}
diff --git a/tests/Unit/Http/Validation/ValidatorTest.php b/tests/Unit/Http/Validation/ValidatorTest.php
new file mode 100644
index 00000000..450e5d4e
--- /dev/null
+++ b/tests/Unit/Http/Validation/ValidatorTest.php
@@ -0,0 +1,142 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Http\Validation;
+
+use Engelsystem\Http\Validation\Validator;
+use InvalidArgumentException;
+use PHPUnit\Framework\TestCase;
+
+class ValidatorTest extends TestCase
+{
+ /**
+ * @covers \Engelsystem\Http\Validation\Validator::validate
+ * @covers \Engelsystem\Http\Validation\Validator::getData
+ * @covers \Engelsystem\Http\Validation\Validator::getErrors
+ */
+ public function testValidate()
+ {
+ $val = new Validator();
+
+ $this->assertTrue($val->validate(
+ ['foo' => 'bar', 'lorem' => 'on', 'dolor' => 'bla'],
+ ['lorem' => 'accepted']
+ ));
+ $this->assertEquals(['lorem' => 'on'], $val->getData());
+
+ $this->assertFalse($val->validate(
+ [],
+ ['lorem' => 'required|min:3']
+ ));
+ $this->assertEquals(
+ ['lorem' => ['validation.lorem.required', 'validation.lorem.min']],
+ $val->getErrors()
+ );
+ }
+
+ /**
+ * @covers \Engelsystem\Http\Validation\Validator::validate
+ */
+ public function testValidateChaining()
+ {
+ $val = new Validator();
+
+ $this->assertTrue($val->validate(
+ ['lorem' => 10],
+ ['lorem' => 'required|min:3|max:10']
+ ));
+ $this->assertTrue($val->validate(
+ ['lorem' => 3],
+ ['lorem' => 'required|min:3|max:10']
+ ));
+
+ $this->assertFalse($val->validate(
+ ['lorem' => 2],
+ ['lorem' => 'required|min:3|max:10']
+ ));
+ $this->assertFalse($val->validate(
+ ['lorem' => 42],
+ ['lorem' => 'required|min:3|max:10']
+ ));
+ }
+
+ /**
+ * @covers \Engelsystem\Http\Validation\Validator::validate
+ */
+ public function testValidateNotImplemented()
+ {
+ $val = new Validator();
+
+ $this->expectException(InvalidArgumentException::class);
+
+ $val->validate(
+ ['lorem' => 'bar'],
+ ['foo' => 'never_implemented']
+ );
+ }
+
+ /**
+ * @covers \Engelsystem\Http\Validation\Validator::map
+ * @covers \Engelsystem\Http\Validation\Validator::mapBack
+ */
+ public function testValidateMapping()
+ {
+ $val = new Validator();
+
+ $this->assertTrue($val->validate(
+ ['foo' => 'bar'],
+ ['foo' => 'required']
+ ));
+ $this->assertTrue($val->validate(
+ ['foo' => '0'],
+ ['foo' => 'int']
+ ));
+ $this->assertTrue($val->validate(
+ ['foo' => 'on'],
+ ['foo' => 'accepted']
+ ));
+
+ $this->assertFalse($val->validate(
+ [],
+ ['lorem' => 'required']
+ ));
+ $this->assertEquals(
+ ['lorem' => ['validation.lorem.required']],
+ $val->getErrors()
+ );
+ }
+
+ /**
+ * @covers \Engelsystem\Http\Validation\Validator::validate
+ */
+ public function testValidateNesting()
+ {
+ $val = new Validator();
+
+ $this->assertTrue($val->validate(
+ [],
+ ['foo' => 'not|required']
+ ));
+
+ $this->assertTrue($val->validate(
+ ['foo' => 'foo'],
+ ['foo' => 'not|int']
+ ));
+ $this->assertFalse($val->validate(
+ ['foo' => 1],
+ ['foo' => 'not|int']
+ ));
+
+ $this->assertTrue($val->validate(
+ [],
+ ['foo' => 'optional|int']
+ ));
+ $this->assertTrue($val->validate(
+ ['foo' => '33'],
+ ['foo' => 'optional|int']
+ ));
+ $this->assertFalse($val->validate(
+ ['foo' => 'T'],
+ ['foo' => 'optional|int']
+ ));
+ }
+}
diff --git a/tests/Unit/Middleware/ErrorHandlerTest.php b/tests/Unit/Middleware/ErrorHandlerTest.php
index 6c37b651..a9fdd71a 100644
--- a/tests/Unit/Middleware/ErrorHandlerTest.php
+++ b/tests/Unit/Middleware/ErrorHandlerTest.php
@@ -2,14 +2,23 @@
namespace Engelsystem\Test\Unit\Middleware;
+use Engelsystem\Application;
use Engelsystem\Http\Exceptions\HttpException;
+use Engelsystem\Http\Exceptions\ValidationException;
+use Engelsystem\Http\Psr7ServiceProvider;
+use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
+use Engelsystem\Http\ResponseServiceProvider;
+use Engelsystem\Http\Validation\Validator;
use Engelsystem\Middleware\ErrorHandler;
use Engelsystem\Test\Unit\Middleware\Stub\ReturnResponseMiddlewareHandler;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use Symfony\Component\HttpFoundation\Session\Session;
+use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Twig_LoaderInterface as TwigLoader;
class ErrorHandlerTest extends TestCase
@@ -104,7 +113,7 @@ class ErrorHandlerTest extends TestCase
/**
* @covers \Engelsystem\Middleware\ErrorHandler::process
*/
- public function testProcessException()
+ public function testProcessHttpException()
{
/** @var ServerRequestInterface|MockObject $request */
$request = $this->createMock(ServerRequestInterface::class);
@@ -146,6 +155,67 @@ class ErrorHandlerTest extends TestCase
/**
* @covers \Engelsystem\Middleware\ErrorHandler::process
+ * @covers \Engelsystem\Middleware\ErrorHandler::getPreviousUrl
+ */
+ public function testProcessValidationException()
+ {
+ /** @var TwigLoader|MockObject $twigLoader */
+ $twigLoader = $this->createMock(TwigLoader::class);
+ $handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
+ $validator = $this->createMock(Validator::class);
+
+ $handler->expects($this->exactly(2))
+ ->method('handle')
+ ->willReturnCallback(function () use ($validator) {
+ throw new ValidationException($validator);
+ });
+
+ $validator->expects($this->exactly(2))
+ ->method('getErrors')
+ ->willReturn(['foo' => ['validation.foo.numeric']]);
+
+ $session = new Session(new MockArraySessionStorage());
+ $session->set('errors', ['validation' => ['foo' => ['validation.foo.required']]]);
+ $request = Request::create(
+ '/foo/bar',
+ 'POST',
+ ['foo' => 'bar', 'password' => 'Test123', 'password_confirmation' => 'Test1234']
+ );
+ $request->setSession($session);
+
+ /** @var Application $app */
+ $app = app();
+ (new ResponseServiceProvider($app))->register();
+ (new Psr7ServiceProvider($app))->register();
+
+ $errorHandler = new ErrorHandler($twigLoader);
+
+ $return = $errorHandler->process($request, $handler);
+
+ $this->assertEquals(302, $return->getStatusCode());
+ $this->assertEquals('/', $return->getHeaderLine('location'));
+ $this->assertEquals([
+ 'errors' => [
+ 'validation' => [
+ 'foo' => [
+ 'validation.foo.required',
+ 'validation.foo.numeric',
+ ],
+ ],
+ ],
+ 'form-data' => [
+ 'foo' => 'bar',
+ ],
+ ], $session->all());
+
+ $request = $request->withAddedHeader('referer', '/foo/batz');
+ $return = $errorHandler->process($request, $handler);
+
+ $this->assertEquals('/foo/batz', $return->getHeaderLine('location'));
+ }
+
+ /**
+ * @covers \Engelsystem\Middleware\ErrorHandler::process
*/
public function testProcessContentTypeSniffer()
{
@@ -153,7 +223,7 @@ class ErrorHandlerTest extends TestCase
$request = $this->createMock(ServerRequestInterface::class);
/** @var TwigLoader|MockObject $twigLoader */
$twigLoader = $this->createMock(TwigLoader::class);
- $response = new Response('<!DOCTYPE html><html><body><h1>Hi!</h1></body></html>', 500);
+ $response = new Response('<!DOCTYPE html><html lang="en"><body><h1>Hi!</h1></body></html>', 500);
$returnResponseHandler = new ReturnResponseMiddlewareHandler($response);
/** @var ErrorHandler|MockObject $errorHandler */
diff --git a/tests/Unit/Middleware/LegacyMiddlewareTest.php b/tests/Unit/Middleware/LegacyMiddlewareTest.php
index f14a38ed..cce7371a 100644
--- a/tests/Unit/Middleware/LegacyMiddlewareTest.php
+++ b/tests/Unit/Middleware/LegacyMiddlewareTest.php
@@ -3,7 +3,7 @@
namespace Engelsystem\Test\Unit\Middleware;
use Engelsystem\Helpers\Authenticator;
-use Engelsystem\Helpers\Translator;
+use Engelsystem\Helpers\Translation\Translator;
use Engelsystem\Http\Request;
use Engelsystem\Middleware\LegacyMiddleware;
use PHPUnit\Framework\MockObject\MockObject;
diff --git a/tests/Unit/Middleware/SetLocaleTest.php b/tests/Unit/Middleware/SetLocaleTest.php
index dc68d83a..a586f6b7 100644
--- a/tests/Unit/Middleware/SetLocaleTest.php
+++ b/tests/Unit/Middleware/SetLocaleTest.php
@@ -2,7 +2,7 @@
namespace Engelsystem\Test\Unit\Middleware;
-use Engelsystem\Helpers\Translator;
+use Engelsystem\Helpers\Translation\Translator;
use Engelsystem\Middleware\SetLocale;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
diff --git a/tests/Unit/Renderer/EngineTest.php b/tests/Unit/Renderer/EngineTest.php
new file mode 100644
index 00000000..659d85c5
--- /dev/null
+++ b/tests/Unit/Renderer/EngineTest.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Renderer;
+
+use Engelsystem\Test\Unit\Renderer\Stub\EngineImplementation;
+use PHPUnit\Framework\TestCase;
+
+class EngineTest extends TestCase
+{
+ /**
+ * @covers \Engelsystem\Renderer\Engine::share
+ */
+ public function testShare()
+ {
+ $engine = new EngineImplementation();
+ $engine->share(['foo' => ['bar' => 'baz', 'lorem' => 'ipsum']]);
+ $engine->share(['foo' => ['lorem' => 'dolor']]);
+ $engine->share('key', 'value');
+
+ $this->assertEquals(
+ ['foo' => ['bar' => 'baz', 'lorem' => 'dolor'], 'key' => 'value'],
+ $engine->getSharedData()
+ );
+ }
+}
diff --git a/tests/Unit/Renderer/HtmlEngineTest.php b/tests/Unit/Renderer/HtmlEngineTest.php
index 4a31e4bc..f76e7528 100644
--- a/tests/Unit/Renderer/HtmlEngineTest.php
+++ b/tests/Unit/Renderer/HtmlEngineTest.php
@@ -16,11 +16,12 @@ class HtmlEngineTest extends TestCase
public function testGet()
{
$engine = new HtmlEngine();
+ $engine->share('shared_data', 'tester');
- $file = $this->createTempFile('<div>%main_content%</div>');
+ $file = $this->createTempFile('<div>%main_content% is a %shared_data%</div>');
$data = $engine->get($file, ['main_content' => 'Lorem ipsum dolor sit']);
- $this->assertEquals('<div>Lorem ipsum dolor sit</div>', $data);
+ $this->assertEquals('<div>Lorem ipsum dolor sit is a tester</div>', $data);
}
/**
diff --git a/tests/Unit/Renderer/Stub/EngineImplementation.php b/tests/Unit/Renderer/Stub/EngineImplementation.php
new file mode 100644
index 00000000..fc436569
--- /dev/null
+++ b/tests/Unit/Renderer/Stub/EngineImplementation.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Engelsystem\Test\Unit\Renderer\Stub;
+
+use Engelsystem\Renderer\Engine;
+
+class EngineImplementation extends Engine
+{
+ /**
+ * @inheritdoc
+ */
+ public function get(string $path, array $data = []): string
+ {
+ return '';
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function canRender(string $path): bool
+ {
+ return true;
+ }
+
+ /**
+ * @return array
+ */
+ public function getSharedData(): array
+ {
+ return $this->sharedData;
+ }
+}
diff --git a/tests/Unit/Renderer/Twig/Extensions/TranslationTest.php b/tests/Unit/Renderer/Twig/Extensions/TranslationTest.php
index 18705683..0b055c44 100644
--- a/tests/Unit/Renderer/Twig/Extensions/TranslationTest.php
+++ b/tests/Unit/Renderer/Twig/Extensions/TranslationTest.php
@@ -2,7 +2,7 @@
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
-use Engelsystem\Helpers\Translator;
+use Engelsystem\Helpers\Translation\Translator;
use Engelsystem\Renderer\Twig\Extensions\Translation;
use PHPUnit\Framework\MockObject\MockObject;
use Twig_Extensions_TokenParser_Trans as TranslationTokenParser;
diff --git a/tests/Unit/Renderer/TwigEngineTest.php b/tests/Unit/Renderer/TwigEngineTest.php
index 9d0618f1..5e5e59d9 100644
--- a/tests/Unit/Renderer/TwigEngineTest.php
+++ b/tests/Unit/Renderer/TwigEngineTest.php
@@ -20,16 +20,16 @@ class TwigEngineTest extends TestCase
$twig = $this->createMock(Twig::class);
$path = 'foo.twig';
- $data = ['lorem' => 'ipsum'];
-
$twig->expects($this->once())
->method('render')
- ->with($path, $data)
- ->willReturn('LoremIpsum!');
+ ->with($path, ['lorem' => 'ipsum', 'shared' => 'data'])
+ ->willReturn('LoremIpsum data!');
$engine = new TwigEngine($twig);
- $return = $engine->get($path, $data);
- $this->assertEquals('LoremIpsum!', $return);
+ $engine->share('shared', 'data');
+
+ $return = $engine->get($path, ['lorem' => 'ipsum']);
+ $this->assertEquals('LoremIpsum data!', $return);
}