Files
Classeo/backend/tests/Functional/Administration/Application/HomeworkRulesPersistenceFunctionalTest.php
Mathias STRASSER 5f3c5c2d71
Some checks failed
CI / Backend Tests (push) Has been cancelled
CI / Frontend Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Naming Conventions (push) Has been cancelled
CI / Build Check (push) Has been cancelled
feat: Permettre aux administrateurs de configurer les règles de devoirs
Les établissements ont besoin de protéger les élèves et familles des
devoirs de dernière minute. Cette configuration au niveau tenant permet
de définir des règles de timing (délai minimum, pas de devoir pour
lundi après une heure limite) et un mode d'application (avertissement,
blocage ou désactivé).

Le service de validation est prêt pour être branché dans le flux de
création de devoirs (Stories 5.4/5.5). L'historique des changements
assure la traçabilité des modifications de configuration.
2026-03-17 21:28:10 +01:00

152 lines
5.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Functional\Administration\Application;
use App\Administration\Domain\Model\HomeworkRules\EnforcementMode;
use App\Administration\Domain\Model\HomeworkRules\HomeworkRule;
use App\Administration\Domain\Model\HomeworkRules\HomeworkRules;
use App\Administration\Domain\Model\HomeworkRules\RuleType;
use App\Administration\Domain\Repository\HomeworkRulesRepository;
use App\Shared\Domain\Tenant\TenantId;
use DateTimeImmutable;
use Doctrine\DBAL\Connection;
use PHPUnit\Framework\Attributes\Test;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
/**
* Tests fonctionnels pour la persistence des HomeworkRules.
*
* Vérifie le round-trip DBAL : save → findByTenantId → hydration correcte.
*/
final class HomeworkRulesPersistenceFunctionalTest extends KernelTestCase
{
private const string TENANT_ID = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeee01';
private HomeworkRulesRepository $repository;
protected function setUp(): void
{
self::bootKernel();
$this->repository = static::getContainer()->get(HomeworkRulesRepository::class);
}
protected function tearDown(): void
{
/** @var Connection $connection */
$connection = static::getContainer()->get(Connection::class);
$connection->executeStatement(
'DELETE FROM homework_rules_history WHERE tenant_id = :t',
['t' => self::TENANT_ID],
);
$connection->executeStatement(
'DELETE FROM homework_rules WHERE tenant_id = :t',
['t' => self::TENANT_ID],
);
parent::tearDown();
}
#[Test]
public function saveAndRetrieveEmptyRules(): void
{
$tenantId = TenantId::fromString(self::TENANT_ID);
$rules = HomeworkRules::creer(tenantId: $tenantId, now: new DateTimeImmutable('2026-03-17 10:00:00'));
$this->repository->save($rules);
$loaded = $this->repository->findByTenantId($tenantId);
self::assertNotNull($loaded);
self::assertTrue($loaded->tenantId->equals($tenantId));
self::assertSame([], $loaded->rules);
self::assertSame(EnforcementMode::SOFT, $loaded->enforcementMode);
self::assertTrue($loaded->enabled);
}
#[Test]
public function saveAndRetrieveWithRules(): void
{
$tenantId = TenantId::fromString(self::TENANT_ID);
$rules = HomeworkRules::creer(tenantId: $tenantId, now: new DateTimeImmutable('2026-03-17 10:00:00'));
$rules->mettreAJour(
rules: [
new HomeworkRule(RuleType::MINIMUM_DELAY, ['days' => 3]),
new HomeworkRule(RuleType::NO_MONDAY_AFTER, ['day' => 'friday', 'time' => '12:00']),
],
enforcementMode: EnforcementMode::HARD,
enabled: true,
now: new DateTimeImmutable('2026-03-17 11:00:00'),
);
$this->repository->save($rules);
$loaded = $this->repository->findByTenantId($tenantId);
self::assertNotNull($loaded);
self::assertCount(2, $loaded->rules);
self::assertSame(RuleType::MINIMUM_DELAY, $loaded->rules[0]->type);
self::assertSame(3, $loaded->rules[0]->params['days']);
self::assertSame(RuleType::NO_MONDAY_AFTER, $loaded->rules[1]->type);
self::assertSame('friday', $loaded->rules[1]->params['day']);
self::assertSame('12:00', $loaded->rules[1]->params['time']);
self::assertSame(EnforcementMode::HARD, $loaded->enforcementMode);
}
#[Test]
public function upsertOverwritesExistingConfig(): void
{
$tenantId = TenantId::fromString(self::TENANT_ID);
$rules = HomeworkRules::creer(tenantId: $tenantId, now: new DateTimeImmutable('2026-03-17 10:00:00'));
$this->repository->save($rules);
$rules->mettreAJour(
rules: [new HomeworkRule(RuleType::MINIMUM_DELAY, ['days' => 5])],
enforcementMode: EnforcementMode::HARD,
enabled: true,
now: new DateTimeImmutable('2026-03-17 12:00:00'),
);
$this->repository->save($rules);
$loaded = $this->repository->findByTenantId($tenantId);
self::assertNotNull($loaded);
self::assertCount(1, $loaded->rules);
self::assertSame(5, $loaded->rules[0]->params['days']);
self::assertSame(EnforcementMode::HARD, $loaded->enforcementMode);
}
#[Test]
public function findByTenantIdReturnsNullWhenNotFound(): void
{
$tenantId = TenantId::fromString('99999999-9999-9999-9999-999999999999');
self::assertNull($this->repository->findByTenantId($tenantId));
}
#[Test]
public function getThrowsWhenNotFound(): void
{
$this->expectException(\App\Administration\Domain\Exception\HomeworkRulesNotFoundException::class);
$this->repository->get(TenantId::fromString('99999999-9999-9999-9999-999999999999'));
}
#[Test]
public function disabledStatePersistedCorrectly(): void
{
$tenantId = TenantId::fromString(self::TENANT_ID);
$rules = HomeworkRules::creer(tenantId: $tenantId, now: new DateTimeImmutable('2026-03-17 10:00:00'));
$rules->desactiver(new DateTimeImmutable('2026-03-17 11:00:00'));
$this->repository->save($rules);
$loaded = $this->repository->findByTenantId($tenantId);
self::assertNotNull($loaded);
self::assertFalse($loaded->enabled);
self::assertSame(EnforcementMode::DISABLED, $loaded->enforcementMode);
self::assertFalse($loaded->estActif());
}
}