feat(sites) : brique fondatrice du module Sites (ticket 1/4)
Module Sites optionnel et desactivable via config/modules.php. Entite Site (nom unique, ville, CP FR, couleur hex, adresse), repository + impl Doctrine, migration racine (namespace DoctrineMigrations conforme exception CLAUDE.md), fixtures idempotentes (Chatellerault, Saint-Jean, Pommevic), permissions RBAC sites.view/sites.manage. Tests unitaires + validation via KernelTestCase (UniqueEntity, regex hex et CP, NotBlank, Length). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
86
tests/Module/Sites/Domain/Entity/SiteTest.php
Normal file
86
tests/Module/Sites/Domain/Entity/SiteTest.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Module\Sites\Domain\Entity;
|
||||
|
||||
use App\Module\Sites\Domain\Entity\Site;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Tests unitaires de comportement de l'entite Site : etat initial, setters
|
||||
* et gestion des timestamps. Les contraintes de validation (regex, unicite)
|
||||
* sont couvertes par SiteValidationTest.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class SiteTest extends TestCase
|
||||
{
|
||||
public function testConstructorInitialState(): void
|
||||
{
|
||||
$site = new Site(
|
||||
'Chatellerault',
|
||||
'Chatellerault',
|
||||
'86100',
|
||||
'#056CF2',
|
||||
"1 avenue de l'Europe\n86100 Chatellerault",
|
||||
);
|
||||
|
||||
self::assertNull($site->getId());
|
||||
self::assertSame('Chatellerault', $site->getName());
|
||||
self::assertSame('Chatellerault', $site->getCity());
|
||||
self::assertSame('86100', $site->getPostalCode());
|
||||
self::assertSame('#056CF2', $site->getColor());
|
||||
self::assertStringContainsString('Chatellerault', $site->getFullAddress());
|
||||
self::assertInstanceOf(DateTimeImmutable::class, $site->getCreatedAt());
|
||||
self::assertInstanceOf(DateTimeImmutable::class, $site->getUpdatedAt());
|
||||
}
|
||||
|
||||
public function testCreatedAtAndUpdatedAtAreInitiallyEqual(): void
|
||||
{
|
||||
$site = new Site('A', 'B', '12345', '#000000', 'Rue X');
|
||||
|
||||
// A la creation, les deux timestamps sont seedes avec la meme valeur
|
||||
// pour garantir updated_at >= created_at au niveau base.
|
||||
self::assertEquals($site->getCreatedAt(), $site->getUpdatedAt());
|
||||
}
|
||||
|
||||
public function testOnPreUpdateAdvancesUpdatedAtOnly(): void
|
||||
{
|
||||
$site = new Site('A', 'B', '12345', '#000000', 'Rue X');
|
||||
$originalCreatedAt = $site->getCreatedAt();
|
||||
|
||||
// On force updatedAt a une valeur strictement anterieure via reflection
|
||||
// pour ne pas dependre d'un `sleep()` (flaky en CI, lent) : l'entite
|
||||
// n'expose volontairement pas de setter sur updatedAt, c'est le
|
||||
// callback Doctrine PreUpdate qui s'en charge.
|
||||
$pastUpdatedAt = new DateTimeImmutable('-1 hour');
|
||||
$reflection = new ReflectionClass(Site::class);
|
||||
$updatedAtProperty = $reflection->getProperty('updatedAt');
|
||||
$updatedAtProperty->setValue($site, $pastUpdatedAt);
|
||||
|
||||
$site->onPreUpdate();
|
||||
|
||||
self::assertSame($originalCreatedAt, $site->getCreatedAt(), 'created_at doit rester immuable apres un update.');
|
||||
self::assertGreaterThan($pastUpdatedAt, $site->getUpdatedAt(), 'updated_at doit avancer apres onPreUpdate().');
|
||||
}
|
||||
|
||||
public function testSettersMutateFields(): void
|
||||
{
|
||||
$site = new Site('Old', 'OldCity', '12345', '#000000', 'Old Addr');
|
||||
|
||||
$site->setName('New');
|
||||
$site->setCity('NewCity');
|
||||
$site->setPostalCode('67890');
|
||||
$site->setColor('#ABCDEF');
|
||||
$site->setFullAddress('New Addr');
|
||||
|
||||
self::assertSame('New', $site->getName());
|
||||
self::assertSame('NewCity', $site->getCity());
|
||||
self::assertSame('67890', $site->getPostalCode());
|
||||
self::assertSame('#ABCDEF', $site->getColor());
|
||||
self::assertSame('New Addr', $site->getFullAddress());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user