diff --git a/resources/views/admin/user/edit-shirt.twig b/resources/views/admin/user/edit-shirt.twig
index 37705b01..ab3da7a0 100644
--- a/resources/views/admin/user/edit-shirt.twig
+++ b/resources/views/admin/user/edit-shirt.twig
@@ -20,6 +20,9 @@
{{ f.select('shirt_size', __('user.shirt_size'), config('tshirt_sizes'), {
'selected': userdata.personalData.shirt_size,
+ 'required': true,
+ 'required_icon': true,
+ 'default_option': __('Please select...'),
}) }}
{% endif %}
diff --git a/resources/views/pages/settings/profile.twig b/resources/views/pages/settings/profile.twig
index 83f7b470..b6db1a70 100644
--- a/resources/views/pages/settings/profile.twig
+++ b/resources/views/pages/settings/profile.twig
@@ -143,6 +143,7 @@
'selected': user.personalData.shirt_size,
'required': true,
'required_icon': true,
+ 'default_option': __('Please select...'),
}) }}
{% endif %}
diff --git a/src/Controllers/Admin/UserShirtController.php b/src/Controllers/Admin/UserShirtController.php
index 807a607f..d213b0bc 100644
--- a/src/Controllers/Admin/UserShirtController.php
+++ b/src/Controllers/Admin/UserShirtController.php
@@ -58,13 +58,13 @@ class UserShirtController extends BaseController
$user = $this->user->findOrFail($userId);
$data = $this->validate($request, [
- 'shirt_size' => $shirtEnabled ? 'required' : 'optional',
+ 'shirt_size' => ($shirtEnabled ? 'required' : 'optional') . '|shirt_size',
'arrived' => 'optional|checked',
'active' => 'optional|checked',
'got_shirt' => 'optional|checked',
]);
- if ($shirtEnabled && isset($this->config->get('tshirt_sizes')[$data['shirt_size']])) {
+ if ($shirtEnabled) {
$user->personalData->shirt_size = $data['shirt_size'];
$user->personalData->save();
}
diff --git a/src/Controllers/SettingsController.php b/src/Controllers/SettingsController.php
index 6e1ec4e7..3c9dd5bb 100644
--- a/src/Controllers/SettingsController.php
+++ b/src/Controllers/SettingsController.php
@@ -296,7 +296,7 @@ class SettingsController extends BaseController
$rules['planned_departure_date'] = 'optional|date:Y-m-d';
}
if ($goodie_tshirt) {
- $rules['shirt_size'] = 'required';
+ $rules['shirt_size'] = 'required|shirt_size';
}
return $rules;
}
diff --git a/src/Http/Validation/Rules/ShirtSize.php b/src/Http/Validation/Rules/ShirtSize.php
new file mode 100644
index 00000000..325045b5
--- /dev/null
+++ b/src/Http/Validation/Rules/ShirtSize.php
@@ -0,0 +1,18 @@
+create();
$auth
- ->expects($this->exactly(6))
+ ->expects($this->exactly(5))
->method('can')
->with('admin_arrive')
- ->willReturnOnConsecutiveCalls(true, true, true, false, false, true);
- $this->setExpects($redirector, 'back', null, $this->response, $this->exactly(6));
+ ->willReturnOnConsecutiveCalls(true, true, false, false, true);
+ $this->setExpects($redirector, 'back', null, $this->response, $this->exactly(5));
$controller = new UserShirtController(
$auth,
@@ -131,7 +133,12 @@ class UserShirtControllerTest extends ControllerTest
'shirt_size' => 'L',
]);
- $controller->saveShirt($request);
+ try {
+ $controller->saveShirt($request);
+ self::fail('Expected exception was not raised');
+ } catch (ValidationException $e) {
+ // ignore
+ }
$user = User::find(1);
$this->assertEquals('S', $user->personalData->shirt_size);
@@ -142,6 +149,8 @@ class UserShirtControllerTest extends ControllerTest
'arrived' => '1',
]);
+ $user->state->arrived = false;
+ $user->state->save();
$this->assertFalse($user->state->arrived);
$controller->saveShirt($request);
$user = User::find(1);
diff --git a/tests/Unit/Http/Validation/Rules/ShirtSizeTest.php b/tests/Unit/Http/Validation/Rules/ShirtSizeTest.php
new file mode 100644
index 00000000..9186d31d
--- /dev/null
+++ b/tests/Unit/Http/Validation/Rules/ShirtSizeTest.php
@@ -0,0 +1,49 @@
+createAndSetUpAppWithConfig([]);
+ $app->get('config')->set('tshirt_sizes', [
+ 'S' => 'Small Straight-Cut',
+ 'M' => 'Medium Straight-Cut',
+ ]);
+ $this->subject = new ShirtSize();
+ }
+
+ /**
+ * @return array
+ */
+ public function provideTestValidateData(): array
+ {
+ $data = [
+ 'empty string' => ['', false],
+ 'null' => [null, false],
+ '0' => [0, false],
+ '"S" (known value)' => ['S', true],
+ '"M" (known value)' => ['M', true],
+ '"L" (unknown value)' => ['L', false],
+ ];
+
+ return $data;
+ }
+
+ /**
+ * @covers \Engelsystem\Http\Validation\Rules\ShirtSize::__construct
+ * @dataProvider provideTestValidateData
+ */
+ public function testValidate(mixed $value, bool $expectedValid): void
+ {
+ self::assertSame($expectedValid, $this->subject->validate($value));
+ }
+}
diff --git a/tests/Unit/Http/Validation/Rules/UsernameTest.php b/tests/Unit/Http/Validation/Rules/UsernameTest.php
index 47b9f84b..705d9745 100644
--- a/tests/Unit/Http/Validation/Rules/UsernameTest.php
+++ b/tests/Unit/Http/Validation/Rules/UsernameTest.php
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Engelsystem\Test\Unit\Http\Validation\Rules;
-use Engelsystem\Application;
use Engelsystem\Config\Config;
use Engelsystem\Http\Validation\Rules\Username;
use Engelsystem\Test\Unit\ServiceProviderTest;
@@ -20,11 +19,8 @@ class UsernameTest extends ServiceProviderTest
{
$this->subject = new Username();
- $app = $this->getApp([]);
- $this->config = new Config([]);
- $app->instance('config', $this->config);
- $app->get('config');
- Application::setInstance($app);
+ $app = $this->createAndSetUpAppWithConfig([]);
+ $this->config = $app->get('config');
// load "username_regex" from the default config
$defaultConfig = include __DIR__ . '/../../../../../config/config.default.php';
diff --git a/tests/Unit/ServiceProviderTest.php b/tests/Unit/ServiceProviderTest.php
index cd9c5afe..8af9ab79 100644
--- a/tests/Unit/ServiceProviderTest.php
+++ b/tests/Unit/ServiceProviderTest.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Engelsystem\Test\Unit;
use Engelsystem\Application;
+use Engelsystem\Config\Config;
use PHPUnit\Framework\MockObject\MockObject;
abstract class ServiceProviderTest extends TestCase
@@ -15,4 +16,18 @@ abstract class ServiceProviderTest extends TestCase
->onlyMethods($methods)
->getMock();
}
+
+ /**
+ * Creates an Application instance with a Config set as 'config'.
+ * Also sets up the instance as global Application instance.
+ *
+ * @param string[] $methods Names of the methods to mock
+ */
+ protected function createAndSetUpAppWithConfig(array $methods = ['make', 'instance']): Application|MockObject
+ {
+ $app = $this->getApp($methods);
+ $app->instance('config', new Config([]));
+ Application::setInstance($app);
+ return $app;
+ }
}