Add ShirtSize validation

This commit is contained in:
Michael Weimann 2023-05-03 17:51:43 +02:00 committed by Igor Scheller
parent 8bb8837e38
commit c5317e2536
9 changed files with 104 additions and 13 deletions

View File

@ -20,6 +20,9 @@
<div class="col-md-6">
{{ f.select('shirt_size', __('user.shirt_size'), config('tshirt_sizes'), {
'selected': userdata.personalData.shirt_size,
'required': true,
'required_icon': true,
'default_option': __('Please select...'),
}) }}
</div>
{% endif %}

View File

@ -143,6 +143,7 @@
'selected': user.personalData.shirt_size,
'required': true,
'required_icon': true,
'default_option': __('Please select...'),
}) }}
</div>
{% endif %}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Http\Validation\Rules;
use Respect\Validation\Rules\In;
/**
* Validates whether the value is contained in the keys of the config item "tshirt_sizes".
*/
class ShirtSize extends In
{
public function __construct()
{
parent::__construct(array_keys(config('tshirt_sizes')));
}
}

View File

@ -7,6 +7,7 @@ namespace Engelsystem\Test\Unit\Controllers\Admin;
use Engelsystem\Config\GoodieType;
use Engelsystem\Controllers\Admin\UserShirtController;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Http\Exceptions\ValidationException;
use Engelsystem\Http\Redirector;
use Engelsystem\Http\Validation\Validator;
use Engelsystem\Models\User\PersonalData;
@ -60,6 +61,7 @@ class UserShirtControllerTest extends ControllerTest
}
/**
* @todo Factor out separate tests. Isolated User, Config and permissions per test.
* @covers \Engelsystem\Controllers\Admin\UserShirtController::saveShirt
*/
public function testSaveShirt(): void
@ -81,11 +83,11 @@ class UserShirtControllerTest extends ControllerTest
->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);

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Test\Unit\Http\Validation\Rules;
use Engelsystem\Http\Validation\Rules\ShirtSize;
use Engelsystem\Test\Unit\ServiceProviderTest;
class ShirtSizeTest extends ServiceProviderTest
{
private ShirtSize $subject;
public function setUp(): void
{
$app = $this->createAndSetUpAppWithConfig([]);
$app->get('config')->set('tshirt_sizes', [
'S' => 'Small Straight-Cut',
'M' => 'Medium Straight-Cut',
]);
$this->subject = new ShirtSize();
}
/**
* @return array<string, array{string, bool}>
*/
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));
}
}

View File

@ -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';

View File

@ -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;
}
}