feat: Gestion des classes scolaires

Permet aux administrateurs de créer, modifier et supprimer des classes
pour organiser les élèves par niveau. L'archivage soft-delete préserve
l'historique tout en masquant les classes obsolètes.

Inclut la validation des noms (2-50 caractères), les niveaux scolaires
du CP à la Terminale, et les contrôles d'accès par rôle.
This commit is contained in:
2026-02-05 15:24:29 +01:00
parent b45ef735db
commit 8e09e0abf1
54 changed files with 5099 additions and 5 deletions

View File

@@ -0,0 +1,104 @@
<?php
declare(strict_types=1);
namespace App\Tests\Unit\Administration\Domain\Model\SchoolClass;
use App\Administration\Domain\Exception\ClassNameInvalideException;
use App\Administration\Domain\Model\SchoolClass\ClassName;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
final class ClassNameTest extends TestCase
{
#[Test]
public function constructWithValidName(): void
{
$name = new ClassName('6ème A');
self::assertSame('6ème A', $name->value);
self::assertSame('6ème A', (string) $name);
}
#[Test]
public function constructTrimsWhitespace(): void
{
$name = new ClassName(' 6ème A ');
self::assertSame('6ème A', $name->value);
}
#[Test]
#[DataProvider('validNamesProvider')]
public function constructAcceptsValidNames(string $value): void
{
$name = new ClassName($value);
self::assertNotEmpty($name->value);
}
/**
* @return array<string, array{string}>
*/
public static function validNamesProvider(): array
{
return [
'minimum length' => ['AB'],
'typical class name' => ['6ème A'],
'longer name' => ['Classe préparatoire aux grandes écoles'],
'with numbers' => ['CM1-2'],
'maximum length' => [str_repeat('A', 50)],
];
}
#[Test]
#[DataProvider('invalidNamesProvider')]
public function constructRejectsInvalidNames(string $value): void
{
$this->expectException(ClassNameInvalideException::class);
new ClassName($value);
}
/**
* @return array<string, array{string}>
*/
public static function invalidNamesProvider(): array
{
return [
'empty string' => [''],
'single character' => ['A'],
'only whitespace' => [' '],
'one char after trim' => [' A '],
'too long' => [str_repeat('A', 51)],
];
}
#[Test]
public function equalsReturnsTrueForSameValue(): void
{
$name1 = new ClassName('6ème A');
$name2 = new ClassName('6ème A');
self::assertTrue($name1->equals($name2));
}
#[Test]
public function equalsReturnsFalseForDifferentValue(): void
{
$name1 = new ClassName('6ème A');
$name2 = new ClassName('6ème B');
self::assertFalse($name1->equals($name2));
}
#[Test]
public function equalsIsCaseSensitive(): void
{
$name1 = new ClassName('Classe A');
$name2 = new ClassName('classe A');
self::assertFalse($name1->equals($name2));
}
}