mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Refactor PersonControllerUpdateTest: separate validation test on dedicated test
This commit is contained in:
parent
80684f65fe
commit
52d791f6d0
@ -64,7 +64,6 @@ class PersonType extends AbstractType
|
|||||||
array $personFieldsConfiguration,
|
array $personFieldsConfiguration,
|
||||||
ConfigPersonAltNamesHelper $configAltNamesHelper,
|
ConfigPersonAltNamesHelper $configAltNamesHelper,
|
||||||
protected TranslatableStringHelperInterface $translatableStringHelper,
|
protected TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
private readonly ParameterBagInterface $parameterBag
|
|
||||||
) {
|
) {
|
||||||
$this->config = $personFieldsConfiguration;
|
$this->config = $personFieldsConfiguration;
|
||||||
$this->configAltNamesHelper = $configAltNamesHelper;
|
$this->configAltNamesHelper = $configAltNamesHelper;
|
||||||
|
@ -82,45 +82,6 @@ final class PersonControllerUpdateTest extends WebTestCase
|
|||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function providesInvalidFieldsValues()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
['firstName', $this->getVeryLongText()],
|
|
||||||
['lastName', $this->getVeryLongText()],
|
|
||||||
['firstName', ''],
|
|
||||||
['lastName', ''],
|
|
||||||
['birthdate', 'false date'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testEditLanguages()
|
|
||||||
{
|
|
||||||
$crawler = $this->client->request('GET', $this->editUrl);
|
|
||||||
$selectedLanguages = ['en', 'an', 'bbj'];
|
|
||||||
|
|
||||||
$form = $crawler->selectButton('Enregistrer')
|
|
||||||
->form();
|
|
||||||
$form->get('chill_personbundle_person[spokenLanguages]')
|
|
||||||
->setValue($selectedLanguages);
|
|
||||||
|
|
||||||
$this->client->submit($form);
|
|
||||||
$this->refreshPerson();
|
|
||||||
|
|
||||||
$this->assertTrue(
|
|
||||||
$this->client->getResponse()->isRedirect($this->viewUrl),
|
|
||||||
'the page is redirected to /general view'
|
|
||||||
);
|
|
||||||
//retrieve languages codes present in person
|
|
||||||
foreach ($this->person->getSpokenLanguages() as $lang) {
|
|
||||||
$languagesCodesPresents[] = $lang->getId();
|
|
||||||
}
|
|
||||||
$this->assertEquals(
|
|
||||||
asort($selectedLanguages),
|
|
||||||
asort($languagesCodesPresents),
|
|
||||||
'the person speaks the expected languages'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the edit page of a given person are not accessible for an
|
* Test the edit page of a given person are not accessible for an
|
||||||
* administrative user.
|
* administrative user.
|
||||||
@ -160,158 +121,44 @@ final class PersonControllerUpdateTest extends WebTestCase
|
|||||||
*/
|
*/
|
||||||
public function testEditPageIsSuccessful()
|
public function testEditPageIsSuccessful()
|
||||||
{
|
{
|
||||||
$this->client->request('GET', $this->editUrl);
|
$client = $this->getClientAuthenticated();
|
||||||
$this->assertTrue(
|
|
||||||
$this->client->getResponse()->isSuccessful(),
|
|
||||||
'The person edit form is accessible'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$crawler = $client->request('GET', $this->editUrl);
|
||||||
* Test the edition of a field.
|
|
||||||
*
|
|
||||||
* Given I fill the field with $value
|
|
||||||
* And I submit the form
|
|
||||||
* Then I am redirected to the 'general' page
|
|
||||||
* And the person is updated in the db
|
|
||||||
*
|
|
||||||
* @dataProvider validTextFieldsProvider
|
|
||||||
*
|
|
||||||
* @param string $field
|
|
||||||
* @param string $value
|
|
||||||
*/
|
|
||||||
public function testEditTextField($field, $value, Closure $callback)
|
|
||||||
{
|
|
||||||
$crawler = $this->client->request('GET', $this->editUrl);
|
|
||||||
|
|
||||||
$form = $crawler->selectButton('Enregistrer')
|
self::assertResponseIsSuccessful('The person edit form is accessible');
|
||||||
->form();
|
|
||||||
//transform countries into value if needed
|
|
||||||
switch ($field) {
|
|
||||||
case 'nationality':
|
|
||||||
case 'countryOfBirth':
|
|
||||||
if (false === empty($value)) {
|
|
||||||
$country = $this->em->getRepository(\Chill\MainBundle\Entity\Country::class)
|
|
||||||
->findOneByCountryCode($value);
|
|
||||||
$transformedValue = $country->getId();
|
|
||||||
} else {
|
|
||||||
$transformedValue = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
$form = $crawler->selectButton('Enregistrer')->form();
|
||||||
|
|
||||||
default:
|
$form['chill_personbundle_person[firstName]'] = 'tagada';
|
||||||
$transformedValue = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
$form->get('chill_personbundle_person[' . $field . ']')
|
$client->submit($form);
|
||||||
->setValue($transformedValue);
|
|
||||||
|
self::assertResponseRedirects($this->viewUrl);
|
||||||
|
|
||||||
$this->client->submit($form);
|
|
||||||
$this->refreshPerson();
|
$this->refreshPerson();
|
||||||
|
|
||||||
$this->assertTrue(
|
self::assertEquals('tagada', $this->person->getFirstName());
|
||||||
$this->client->getResponse()->isRedirect($this->viewUrl),
|
|
||||||
'the page is redirected to general view'
|
|
||||||
);
|
|
||||||
$this->assertEquals(
|
|
||||||
$value,
|
|
||||||
$callback($this->person),
|
|
||||||
'the value ' . $field . ' is updated in db'
|
|
||||||
);
|
|
||||||
|
|
||||||
$crawler = $this->client->followRedirect();
|
|
||||||
|
|
||||||
self::assertTrue($this->client->getResponse()->isSuccessful());
|
|
||||||
|
|
||||||
$this->assertGreaterThan(
|
|
||||||
0,
|
|
||||||
$crawler->filter('.alert-success')->count(),
|
|
||||||
'an element .alert-success is shown'
|
|
||||||
);
|
|
||||||
|
|
||||||
if ('birthdate' === $field || 'memo' === $field || 'countryOfBirth' === $field || 'nationality' === $field
|
|
||||||
|| 'gender' === $field) {
|
|
||||||
// we do not perform test on the web page contents.
|
|
||||||
} else {
|
|
||||||
$this->assertGreaterThan(0, $crawler->filter('html:contains("' . $value . '")')->count());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testEditPageWithErrorIsNotProcessable()
|
||||||
* Test the configurable fields are present.
|
|
||||||
*
|
|
||||||
* @group configurable_fields
|
|
||||||
*/
|
|
||||||
public function testHiddenFielsArePresent()
|
|
||||||
{
|
{
|
||||||
$crawler = $this->client->request('GET', $this->editUrl);
|
$client = $this->getClientAuthenticated();
|
||||||
$configurables = ['placeOfBirth', 'phonenumber', 'email',
|
|
||||||
'countryOfBirth', 'nationality', 'spokenLanguages', 'maritalStatus', ];
|
|
||||||
$form = $crawler->selectButton('Enregistrer')->form(); //;
|
|
||||||
|
|
||||||
foreach ($configurables as $key) {
|
$crawler = $client->request('GET', $this->editUrl);
|
||||||
$this->assertTrue($form->has('chill_personbundle_person[' . $key . ']'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
self::assertResponseIsSuccessful('The person edit form is accessible');
|
||||||
* Test tbe detection of invalid data during the update procedure.
|
|
||||||
*
|
|
||||||
* @dataProvider providesInvalidFieldsValues
|
|
||||||
*
|
|
||||||
* @param string $field
|
|
||||||
* @param string $value
|
|
||||||
*/
|
|
||||||
public function testInvalidFields($field, $value)
|
|
||||||
{
|
|
||||||
$crawler = $this->client->request('GET', $this->editUrl);
|
|
||||||
|
|
||||||
$form = $crawler->selectButton('Enregistrer')
|
$form = $crawler->selectButton('Enregistrer')->form();
|
||||||
->form();
|
|
||||||
$form->get('chill_personbundle_person[' . $field . ']')
|
|
||||||
->setValue($value);
|
|
||||||
|
|
||||||
$crawler = $this->client->submit($form);
|
$form['chill_personbundle_person[firstName]'] = '';
|
||||||
|
|
||||||
$this->assertFalse(
|
$crawler = $client->submit($form);
|
||||||
$this->client->getResponse()->isRedirect(),
|
|
||||||
'the page is not redirected to /general'
|
|
||||||
);
|
|
||||||
$this->assertGreaterThan(
|
|
||||||
0,
|
|
||||||
$crawler->filter('.alert-danger')->count(),
|
|
||||||
'a element .error is shown'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
self::assertResponseIsSuccessful('the page is successful but not redirected');
|
||||||
* provide valid values to test, with field name and
|
|
||||||
* a function to find the value back from person entity.
|
$alerts = $crawler->filter('.alert-danger');
|
||||||
*
|
|
||||||
* @return mixed[]
|
self::assertEquals(1, $alerts->count(), "there is an alert message displayed on the page");
|
||||||
*/
|
|
||||||
public function validTextFieldsProvider()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
['firstName', 'random Value', static fn (Person $person) => $person->getFirstName()],
|
|
||||||
['lastName', 'random Value', static fn (Person $person) => $person->getLastName()],
|
|
||||||
// reminder: this value is capitalized
|
|
||||||
['placeOfBirth', 'A PLACE', static fn (Person $person) => $person->getPlaceOfBirth()],
|
|
||||||
['birthdate', '1980-12-15', static fn (Person $person) => $person->getBirthdate()->format('Y-m-d')],
|
|
||||||
// TODO test on phonenumber update
|
|
||||||
// ['phonenumber', '+32123456789', static function (Person $person) { return $person->getPhonenumber(); }],
|
|
||||||
['memo', 'jfkdlmq jkfldmsq jkmfdsq', static fn (Person $person) => $person->getMemo()],
|
|
||||||
['countryOfBirth', 'BE', static fn (Person $person) => $person->getCountryOfBirth()->getCountryCode()],
|
|
||||||
['nationality', 'FR', static fn (Person $person) => $person->getNationality()->getCountryCode()],
|
|
||||||
['placeOfBirth', '', static fn (Person $person) => $person->getPlaceOfBirth()],
|
|
||||||
['birthdate', '', static fn (Person $person) => $person->getBirthdate()],
|
|
||||||
//['phonenumber', '', static function (Person $person) { return $person->getPhonenumber(); }],
|
|
||||||
['memo', '', static fn (Person $person) => $person->getMemo()],
|
|
||||||
['countryOfBirth', null, static fn (Person $person) => $person->getCountryOfBirth()],
|
|
||||||
['nationality', null, static fn (Person $person) => $person->getNationality()],
|
|
||||||
['gender', Person::FEMALE_GENDER, static fn (Person $person) => $person->getGender()],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -322,11 +169,4 @@ final class PersonControllerUpdateTest extends WebTestCase
|
|||||||
$this->person = $this->em->getRepository(\Chill\PersonBundle\Entity\Person::class)
|
$this->person = $this->em->getRepository(\Chill\PersonBundle\Entity\Person::class)
|
||||||
->find($this->person->getId());
|
->find($this->person->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getVeryLongText()
|
|
||||||
{
|
|
||||||
return <<<'EOT'
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse molestie at enim id auctor. Vivamus malesuada elit ipsum, ac mollis ex facilisis sit amet. Phasellus accumsan, quam ut aliquet accumsan, augue ligula consequat erat, condimentum iaculis orci magna egestas eros. In vel blandit sapien. Duis ut dui vitae tortor iaculis malesuada vitae vitae lorem. Morbi efficitur dolor orci, a rhoncus urna blandit quis. Aenean at placerat dui, ut tincidunt nulla. In ultricies tempus ligula ac rutrum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce urna nibh, placerat vel auctor sed, maximus quis magna. Vivamus quam ante, consectetur vel feugiat quis, aliquet id ante. Integer gravida erat dignissim ante commodo mollis. Donec imperdiet mauris elit, nec blandit dolor feugiat ut. Proin iaculis enim ut tortor pretium commodo. Etiam aliquet hendrerit dolor sed fringilla. Vestibulum facilisis nibh tincidunt dui egestas, vitae congue mi imperdiet. Duis vulputate ultricies lectus id cursus. Fusce bibendum sem dignissim, bibendum purus quis, mollis ex. Cras ac est justo. Duis congue mattis ipsum, vitae sagittis justo dictum sit amet. Duis aliquam pharetra sem, non laoreet ante laoreet ac. Mauris ornare mi tempus rutrum consequat.
|
|
||||||
EOT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Tests\Validation;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
|
use Symfony\Component\Validator\ConstraintViolation;
|
||||||
|
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||||
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class PersonValidationTest extends KernelTestCase
|
||||||
|
{
|
||||||
|
private static ValidatorInterface $validator;
|
||||||
|
|
||||||
|
public static function setUpBeforeClass(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
self::$validator = self::$container->get(ValidatorInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideDataValidation
|
||||||
|
*/
|
||||||
|
public function testFirstName(Person $person, string $path, string $code, int $expectedCountErrors): void
|
||||||
|
{
|
||||||
|
$errors = self::$validator->validate($person);
|
||||||
|
|
||||||
|
$errorsFiltered = array_filter(iterator_to_array($errors), fn (ConstraintViolationInterface $e) => $path === $e->getPropertyPath() /*&& $code === $e->getCode()*/);
|
||||||
|
|
||||||
|
self::assertCount($expectedCountErrors, $errorsFiltered);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function provideDataValidation(): iterable
|
||||||
|
{
|
||||||
|
$person = new Person();
|
||||||
|
|
||||||
|
yield [$person, 'firstName', 'c1051bb4-d103-4f74-8988-acbcafc7fdc3', 1];
|
||||||
|
yield [$person, 'lastName', 'c1051bb4-d103-4f74-8988-acbcafc7fdc3', 1];
|
||||||
|
|
||||||
|
$person = (new Person())->setFirstName('')->setLastName('');
|
||||||
|
|
||||||
|
yield [$person, 'firstName', 'c1051bb4-d103-4f74-8988-acbcafc7fdc3', 1];
|
||||||
|
yield [$person, 'lastName', 'c1051bb4-d103-4f74-8988-acbcafc7fdc3', 1];
|
||||||
|
|
||||||
|
$person = (new Person())->setFirstName('Valid')->setLastName('valid');
|
||||||
|
|
||||||
|
yield [$person, 'firstName', 'c1051bb4-d103-4f74-8988-acbcafc7fdc3', 0];
|
||||||
|
yield [$person, 'lastName', 'c1051bb4-d103-4f74-8988-acbcafc7fdc3', 0];
|
||||||
|
|
||||||
|
$person = (new Person())->setBirthdate(new \DateTime('next year'));
|
||||||
|
|
||||||
|
yield [$person, 'birthdate', '3f42fd96-0b2d-11ec-8cf3-0f3b1b1ca1c4', 1];
|
||||||
|
|
||||||
|
$person = (new Person())->setBirthdate(new \DateTime('1700-01-01T00:00:00'));
|
||||||
|
|
||||||
|
yield [$person, 'birthdate', '3f42fd96-0b2d-11ec-8cf3-0f3b1b1ca1c4', 1];
|
||||||
|
|
||||||
|
$person = (new Person())->setBirthdate(new \DateTime('yesterday'));
|
||||||
|
|
||||||
|
yield [$person, 'birthdate', '3f42fd96-0b2d-11ec-8cf3-0f3b1b1ca1c4', 0];
|
||||||
|
|
||||||
|
$person = (new Person())->setEmail('blabla');
|
||||||
|
|
||||||
|
yield [$person, 'email', 'bd79c0ab-ddba-46cc-a703-a7a4b08de310', 1];
|
||||||
|
|
||||||
|
$person = (new Person())->setEmail('chillfake@gmail.com');
|
||||||
|
|
||||||
|
yield [$person, 'email', 'bd79c0ab-ddba-46cc-a703-a7a4b08de310', 0];
|
||||||
|
}
|
||||||
|
}
|
@ -28,4 +28,6 @@ class Birthdate extends Constraint
|
|||||||
final public const BIRTHDATE_INVALID_CODE = '3f42fd96-0b2d-11ec-8cf3-0f3b1b1ca1c4';
|
final public const BIRTHDATE_INVALID_CODE = '3f42fd96-0b2d-11ec-8cf3-0f3b1b1ca1c4';
|
||||||
|
|
||||||
public $message = 'The birthdate must be before %date%';
|
public $message = 'The birthdate must be before %date%';
|
||||||
|
|
||||||
|
public $belowMessage = 'The birthdate must be after %date%';
|
||||||
}
|
}
|
||||||
|
@ -14,17 +14,27 @@ namespace Chill\PersonBundle\Validator\Constraints\Person;
|
|||||||
use DateInterval;
|
use DateInterval;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
|
use Symfony\Component\Clock\ClockInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
use Symfony\Component\Validator\ConstraintValidator;
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||||
use function get_class;
|
use function get_class;
|
||||||
use function gettype;
|
use function gettype;
|
||||||
use function is_object;
|
use function is_object;
|
||||||
|
|
||||||
class BirthdateValidator extends ConstraintValidator
|
class BirthdateValidator extends ConstraintValidator
|
||||||
{
|
{
|
||||||
public function __construct(private $interval_spec = null)
|
private string $interval_spec;
|
||||||
{
|
|
||||||
|
private string $below_interval = 'P150Y';
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private ParameterBagInterface $parameterBag,
|
||||||
|
private ClockInterface $clock
|
||||||
|
) {
|
||||||
|
$this->interval_spec = $this->parameterBag->get('chill_person')['validation']['birthdate_not_after'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function validate($value, Constraint $constraint)
|
public function validate($value, Constraint $constraint)
|
||||||
@ -38,27 +48,40 @@ class BirthdateValidator extends ConstraintValidator
|
|||||||
. (get_debug_type($value)));
|
. (get_debug_type($value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$constraint instanceof Birthdate) {
|
||||||
|
throw new UnexpectedTypeException($constraint, Birthdate::class);
|
||||||
|
}
|
||||||
|
|
||||||
$limitDate = $this->getLimitDate();
|
$limitDate = $this->getLimitDate();
|
||||||
|
|
||||||
if ($limitDate < $value) {
|
if ($value > $limitDate) {
|
||||||
$this->context->buildViolation($constraint->message)
|
$this->context->buildViolation($constraint->message)
|
||||||
->setParameter('%date%', $limitDate->format('d-m-Y'))
|
->setParameter('%date%', $limitDate->format('d-m-Y'))
|
||||||
->setCode(Birthdate::BIRTHDATE_INVALID_CODE)
|
->setCode(Birthdate::BIRTHDATE_INVALID_CODE)
|
||||||
->addViolation();
|
->addViolation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($value < $this->getBelowLimitDate()) {
|
||||||
|
$this->context->buildViolation($constraint->belowMessage)
|
||||||
|
->setParameter('%date%', $this->getBelowLimitDate()->format('d-m-Y'))
|
||||||
|
->setCode(Birthdate::BIRTHDATE_INVALID_CODE)
|
||||||
|
->addViolation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function getLimitDate(): DateTime
|
||||||
* @return DateTime
|
|
||||||
*/
|
|
||||||
private function getLimitDate()
|
|
||||||
{
|
{
|
||||||
if (null !== $this->interval_spec) {
|
if (null !== $this->interval_spec) {
|
||||||
$interval = new DateInterval($this->interval_spec);
|
$interval = new DateInterval($this->interval_spec);
|
||||||
|
|
||||||
return (new DateTime('now'))->sub($interval);
|
return DateTime::createFromImmutable($this->clock->now()->sub($interval));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DateTime('now');
|
return DateTime::createFromImmutable($this->clock->now());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBelowLimitDate(): DateTime
|
||||||
|
{
|
||||||
|
return DateTime::createFromImmutable($this->clock->now()->sub(new DateInterval($this->below_interval)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user