feat: Permettre aux enseignants de créer et gérer les devoirs
Les enseignants avaient besoin d'un outil pour créer des devoirs assignés à leurs classes, avec filtrage automatique par matière selon la classe sélectionnée. Le système valide que la date d'échéance tombe un jour ouvrable (lundi-vendredi) et empêche les dates dans le passé. Le domaine modélise le devoir comme un agrégat avec pièces jointes, statut brouillon/publié, et événements métier (création, modification, suppression). Les handlers de notification écoutent ces événements pour les futurs envois aux parents et élèves.
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Scolarite\Domain\Service;
|
||||
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntry;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntryId;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntryType;
|
||||
use App\Administration\Domain\Model\SchoolCalendar\SchoolCalendar;
|
||||
use App\Administration\Domain\Model\SchoolClass\AcademicYearId;
|
||||
use App\Scolarite\Domain\Exception\DateEcheanceInvalideException;
|
||||
use App\Scolarite\Domain\Service\DueDateValidator;
|
||||
use App\Shared\Domain\Tenant\TenantId;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class DueDateValidatorTest extends TestCase
|
||||
{
|
||||
private DueDateValidator $validator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->validator = new DueDateValidator();
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function acceptsValidFutureSchoolDay(): void
|
||||
{
|
||||
$now = new DateTimeImmutable('2026-03-12 10:00:00'); // Jeudi
|
||||
$dueDate = new DateTimeImmutable('2026-03-16'); // Lundi
|
||||
$calendar = $this->createEmptyCalendar();
|
||||
|
||||
$this->validator->valider($dueDate, $now, $calendar);
|
||||
|
||||
$this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function rejectsPastDate(): void
|
||||
{
|
||||
$now = new DateTimeImmutable('2026-03-12 10:00:00');
|
||||
$dueDate = new DateTimeImmutable('2026-03-11');
|
||||
$calendar = $this->createEmptyCalendar();
|
||||
|
||||
$this->expectException(DateEcheanceInvalideException::class);
|
||||
$this->expectExceptionMessageMatches('/futur/');
|
||||
|
||||
$this->validator->valider($dueDate, $now, $calendar);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function rejectsTodayDate(): void
|
||||
{
|
||||
$now = new DateTimeImmutable('2026-03-12 10:00:00');
|
||||
$dueDate = new DateTimeImmutable('2026-03-12');
|
||||
$calendar = $this->createEmptyCalendar();
|
||||
|
||||
$this->expectException(DateEcheanceInvalideException::class);
|
||||
$this->expectExceptionMessageMatches('/futur/');
|
||||
|
||||
$this->validator->valider($dueDate, $now, $calendar);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function acceptsTomorrowDate(): void
|
||||
{
|
||||
$now = new DateTimeImmutable('2026-03-12 10:00:00'); // Jeudi
|
||||
$dueDate = new DateTimeImmutable('2026-03-13'); // Vendredi
|
||||
$calendar = $this->createEmptyCalendar();
|
||||
|
||||
$this->validator->valider($dueDate, $now, $calendar);
|
||||
|
||||
$this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function rejectsWeekendDate(): void
|
||||
{
|
||||
$now = new DateTimeImmutable('2026-03-12 10:00:00');
|
||||
$dueDate = new DateTimeImmutable('2026-03-14'); // Samedi
|
||||
$calendar = $this->createEmptyCalendar();
|
||||
|
||||
$this->expectException(DateEcheanceInvalideException::class);
|
||||
$this->expectExceptionMessageMatches('/weekend/');
|
||||
|
||||
$this->validator->valider($dueDate, $now, $calendar);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function rejectsHolidayDate(): void
|
||||
{
|
||||
$now = new DateTimeImmutable('2026-03-12 10:00:00');
|
||||
$dueDate = new DateTimeImmutable('2026-04-06'); // Lundi
|
||||
$calendar = $this->createCalendarWithVacation(
|
||||
new DateTimeImmutable('2026-04-04'),
|
||||
new DateTimeImmutable('2026-04-19'),
|
||||
'Vacances de printemps',
|
||||
);
|
||||
|
||||
$this->expectException(DateEcheanceInvalideException::class);
|
||||
$this->expectExceptionMessageMatches('/Vacances de printemps/');
|
||||
|
||||
$this->validator->valider($dueDate, $now, $calendar);
|
||||
}
|
||||
|
||||
private function createEmptyCalendar(): SchoolCalendar
|
||||
{
|
||||
return SchoolCalendar::reconstitute(
|
||||
tenantId: TenantId::fromString('550e8400-e29b-41d4-a716-446655440001'),
|
||||
academicYearId: AcademicYearId::fromString('550e8400-e29b-41d4-a716-446655440002'),
|
||||
zone: null,
|
||||
entries: [],
|
||||
);
|
||||
}
|
||||
|
||||
private function createCalendarWithVacation(
|
||||
DateTimeImmutable $start,
|
||||
DateTimeImmutable $end,
|
||||
string $label,
|
||||
): SchoolCalendar {
|
||||
return SchoolCalendar::reconstitute(
|
||||
tenantId: TenantId::fromString('550e8400-e29b-41d4-a716-446655440001'),
|
||||
academicYearId: AcademicYearId::fromString('550e8400-e29b-41d4-a716-446655440002'),
|
||||
zone: null,
|
||||
entries: [
|
||||
new CalendarEntry(
|
||||
id: CalendarEntryId::generate(),
|
||||
type: CalendarEntryType::VACATION,
|
||||
startDate: $start,
|
||||
endDate: $end,
|
||||
label: $label,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user