feat: Gestion des périodes scolaires
L'administration d'un établissement nécessite de découper l'année scolaire en trimestres ou semestres avant de pouvoir saisir les notes et générer les bulletins. Ce module permet de configurer les périodes par année scolaire (current/previous/next résolus en UUID v5 déterministes), de modifier les dates individuelles avec validation anti-chevauchement, et de consulter la période en cours avec le décompte des jours restants. Les dates par défaut de février s'adaptent aux années bissextiles. Le repository utilise UPSERT transactionnel pour garantir l'intégrité lors du changement de mode (trimestres ↔ semestres). Les domain events de Subject sont étendus pour couvrir toutes les mutations (code, couleur, description) en plus du renommage.
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Domain\Model\AcademicYear;
|
||||
|
||||
use App\Administration\Domain\Exception\InvalidPeriodDatesException;
|
||||
use App\Administration\Domain\Model\AcademicYear\AcademicPeriod;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class AcademicPeriodTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function itCreatesValidPeriod(): void
|
||||
{
|
||||
$period = new AcademicPeriod(
|
||||
sequence: 1,
|
||||
label: 'T1',
|
||||
startDate: new DateTimeImmutable('2025-09-01'),
|
||||
endDate: new DateTimeImmutable('2025-11-30'),
|
||||
);
|
||||
|
||||
self::assertSame(1, $period->sequence);
|
||||
self::assertSame('T1', $period->label);
|
||||
self::assertSame('2025-09-01', $period->startDate->format('Y-m-d'));
|
||||
self::assertSame('2025-11-30', $period->endDate->format('Y-m-d'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itRejectsEndDateBeforeStartDate(): void
|
||||
{
|
||||
$this->expectException(InvalidPeriodDatesException::class);
|
||||
|
||||
new AcademicPeriod(
|
||||
sequence: 1,
|
||||
label: 'T1',
|
||||
startDate: new DateTimeImmutable('2025-11-30'),
|
||||
endDate: new DateTimeImmutable('2025-09-01'),
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itRejectsEqualDates(): void
|
||||
{
|
||||
$this->expectException(InvalidPeriodDatesException::class);
|
||||
|
||||
new AcademicPeriod(
|
||||
sequence: 1,
|
||||
label: 'T1',
|
||||
startDate: new DateTimeImmutable('2025-09-01'),
|
||||
endDate: new DateTimeImmutable('2025-09-01'),
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itDetectsDateWithinPeriod(): void
|
||||
{
|
||||
$period = new AcademicPeriod(
|
||||
sequence: 1,
|
||||
label: 'T1',
|
||||
startDate: new DateTimeImmutable('2025-09-01'),
|
||||
endDate: new DateTimeImmutable('2025-11-30'),
|
||||
);
|
||||
|
||||
self::assertTrue($period->containsDate(new DateTimeImmutable('2025-10-15')));
|
||||
self::assertTrue($period->containsDate(new DateTimeImmutable('2025-09-01')));
|
||||
self::assertTrue($period->containsDate(new DateTimeImmutable('2025-11-30')));
|
||||
self::assertFalse($period->containsDate(new DateTimeImmutable('2025-08-31')));
|
||||
self::assertFalse($period->containsDate(new DateTimeImmutable('2025-12-01')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itIncludesLastDayRegardlessOfTime(): void
|
||||
{
|
||||
$period = new AcademicPeriod(
|
||||
sequence: 1,
|
||||
label: 'T1',
|
||||
startDate: new DateTimeImmutable('2025-09-01'),
|
||||
endDate: new DateTimeImmutable('2025-11-30'),
|
||||
);
|
||||
|
||||
// Last day at 15:00 must still be "within" the period
|
||||
self::assertTrue($period->containsDate(new DateTimeImmutable('2025-11-30 15:00:00')));
|
||||
self::assertFalse($period->isPast(new DateTimeImmutable('2025-11-30 23:59:59')));
|
||||
self::assertTrue($period->isPast(new DateTimeImmutable('2025-12-01 00:00:01')));
|
||||
|
||||
// daysRemaining on last day should be 0 (same day)
|
||||
self::assertSame(0, $period->daysRemaining(new DateTimeImmutable('2025-11-30 15:00:00')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itCalculatesDaysRemaining(): void
|
||||
{
|
||||
$period = new AcademicPeriod(
|
||||
sequence: 1,
|
||||
label: 'T1',
|
||||
startDate: new DateTimeImmutable('2025-09-01'),
|
||||
endDate: new DateTimeImmutable('2025-11-30'),
|
||||
);
|
||||
|
||||
// During the period
|
||||
self::assertSame(30, $period->daysRemaining(new DateTimeImmutable('2025-10-31')));
|
||||
|
||||
// After the period
|
||||
self::assertSame(0, $period->daysRemaining(new DateTimeImmutable('2025-12-01')));
|
||||
|
||||
// Before the period: returns total period length
|
||||
self::assertSame(90, $period->daysRemaining(new DateTimeImmutable('2025-08-01')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itDetectsPastPeriod(): void
|
||||
{
|
||||
$period = new AcademicPeriod(
|
||||
sequence: 1,
|
||||
label: 'T1',
|
||||
startDate: new DateTimeImmutable('2025-09-01'),
|
||||
endDate: new DateTimeImmutable('2025-11-30'),
|
||||
);
|
||||
|
||||
self::assertTrue($period->isPast(new DateTimeImmutable('2025-12-01')));
|
||||
self::assertFalse($period->isPast(new DateTimeImmutable('2025-11-30')));
|
||||
self::assertFalse($period->isPast(new DateTimeImmutable('2025-10-15')));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Domain\Model\AcademicYear;
|
||||
|
||||
use App\Administration\Domain\Model\AcademicYear\DefaultPeriods;
|
||||
use App\Administration\Domain\Model\AcademicYear\PeriodType;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class DefaultPeriodsTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function itGeneratesDefaultTremesters(): void
|
||||
{
|
||||
$config = DefaultPeriods::forType(PeriodType::TRIMESTER, 2025);
|
||||
|
||||
self::assertSame(PeriodType::TRIMESTER, $config->type);
|
||||
self::assertCount(3, $config->periods);
|
||||
|
||||
self::assertSame('T1', $config->periods[0]->label);
|
||||
self::assertSame('2025-09-01', $config->periods[0]->startDate->format('Y-m-d'));
|
||||
self::assertSame('2025-11-30', $config->periods[0]->endDate->format('Y-m-d'));
|
||||
|
||||
self::assertSame('T2', $config->periods[1]->label);
|
||||
self::assertSame('2025-12-01', $config->periods[1]->startDate->format('Y-m-d'));
|
||||
self::assertSame('2026-02-28', $config->periods[1]->endDate->format('Y-m-d'));
|
||||
|
||||
self::assertSame('T3', $config->periods[2]->label);
|
||||
self::assertSame('2026-03-01', $config->periods[2]->startDate->format('Y-m-d'));
|
||||
self::assertSame('2026-06-30', $config->periods[2]->endDate->format('Y-m-d'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itHandlesLeapYearForTrimesters(): void
|
||||
{
|
||||
// 2023-2024 : 2024 is a leap year, Feb has 29 days
|
||||
$config = DefaultPeriods::forType(PeriodType::TRIMESTER, 2023);
|
||||
|
||||
self::assertSame('2024-02-29', $config->periods[1]->endDate->format('Y-m-d'));
|
||||
self::assertSame('2024-03-01', $config->periods[2]->startDate->format('Y-m-d'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itHandlesNonLeapYearForTrimesters(): void
|
||||
{
|
||||
// 2024-2025 : 2025 is not a leap year
|
||||
$config = DefaultPeriods::forType(PeriodType::TRIMESTER, 2024);
|
||||
|
||||
self::assertSame('2025-02-28', $config->periods[1]->endDate->format('Y-m-d'));
|
||||
self::assertSame('2025-03-01', $config->periods[2]->startDate->format('Y-m-d'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itGeneratesDefaultSemesters(): void
|
||||
{
|
||||
$config = DefaultPeriods::forType(PeriodType::SEMESTER, 2025);
|
||||
|
||||
self::assertSame(PeriodType::SEMESTER, $config->type);
|
||||
self::assertCount(2, $config->periods);
|
||||
|
||||
self::assertSame('S1', $config->periods[0]->label);
|
||||
self::assertSame('2025-09-01', $config->periods[0]->startDate->format('Y-m-d'));
|
||||
self::assertSame('2026-01-31', $config->periods[0]->endDate->format('Y-m-d'));
|
||||
|
||||
self::assertSame('S2', $config->periods[1]->label);
|
||||
self::assertSame('2026-02-01', $config->periods[1]->startDate->format('Y-m-d'));
|
||||
self::assertSame('2026-06-30', $config->periods[1]->endDate->format('Y-m-d'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Domain\Model\AcademicYear;
|
||||
|
||||
use App\Administration\Domain\Exception\InvalidPeriodCountException;
|
||||
use App\Administration\Domain\Exception\PeriodsCoverageGapException;
|
||||
use App\Administration\Domain\Exception\PeriodsOverlapException;
|
||||
use App\Administration\Domain\Model\AcademicYear\AcademicPeriod;
|
||||
use App\Administration\Domain\Model\AcademicYear\PeriodConfiguration;
|
||||
use App\Administration\Domain\Model\AcademicYear\PeriodType;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class PeriodConfigurationTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function itCreatesValidTrimesterConfiguration(): void
|
||||
{
|
||||
$config = $this->validTrimesterConfig();
|
||||
|
||||
self::assertSame(PeriodType::TRIMESTER, $config->type);
|
||||
self::assertCount(3, $config->periods);
|
||||
self::assertSame('2025-09-01', $config->startDate()->format('Y-m-d'));
|
||||
self::assertSame('2026-06-30', $config->endDate()->format('Y-m-d'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itCreatesValidSemesterConfiguration(): void
|
||||
{
|
||||
$config = new PeriodConfiguration(PeriodType::SEMESTER, [
|
||||
new AcademicPeriod(1, 'S1', new DateTimeImmutable('2025-09-01'), new DateTimeImmutable('2026-01-31')),
|
||||
new AcademicPeriod(2, 'S2', new DateTimeImmutable('2026-02-01'), new DateTimeImmutable('2026-06-30')),
|
||||
]);
|
||||
|
||||
self::assertSame(PeriodType::SEMESTER, $config->type);
|
||||
self::assertCount(2, $config->periods);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itRejectsWrongPeriodCountForTrimester(): void
|
||||
{
|
||||
$this->expectException(InvalidPeriodCountException::class);
|
||||
|
||||
new PeriodConfiguration(PeriodType::TRIMESTER, [
|
||||
new AcademicPeriod(1, 'S1', new DateTimeImmutable('2025-09-01'), new DateTimeImmutable('2026-01-31')),
|
||||
new AcademicPeriod(2, 'S2', new DateTimeImmutable('2026-02-01'), new DateTimeImmutable('2026-06-30')),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itRejectsWrongPeriodCountForSemester(): void
|
||||
{
|
||||
$this->expectException(InvalidPeriodCountException::class);
|
||||
|
||||
new PeriodConfiguration(PeriodType::SEMESTER, [
|
||||
new AcademicPeriod(1, 'T1', new DateTimeImmutable('2025-09-01'), new DateTimeImmutable('2025-11-30')),
|
||||
new AcademicPeriod(2, 'T2', new DateTimeImmutable('2025-12-01'), new DateTimeImmutable('2026-02-28')),
|
||||
new AcademicPeriod(3, 'T3', new DateTimeImmutable('2026-03-01'), new DateTimeImmutable('2026-06-30')),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itRejectsOverlappingPeriods(): void
|
||||
{
|
||||
$this->expectException(PeriodsOverlapException::class);
|
||||
|
||||
new PeriodConfiguration(PeriodType::TRIMESTER, [
|
||||
new AcademicPeriod(1, 'T1', new DateTimeImmutable('2025-09-01'), new DateTimeImmutable('2025-12-01')),
|
||||
new AcademicPeriod(2, 'T2', new DateTimeImmutable('2025-11-30'), new DateTimeImmutable('2026-02-28')),
|
||||
new AcademicPeriod(3, 'T3', new DateTimeImmutable('2026-03-01'), new DateTimeImmutable('2026-06-30')),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itRejectsCoverageGap(): void
|
||||
{
|
||||
$this->expectException(PeriodsCoverageGapException::class);
|
||||
|
||||
new PeriodConfiguration(PeriodType::TRIMESTER, [
|
||||
new AcademicPeriod(1, 'T1', new DateTimeImmutable('2025-09-01'), new DateTimeImmutable('2025-11-28')),
|
||||
new AcademicPeriod(2, 'T2', new DateTimeImmutable('2025-12-01'), new DateTimeImmutable('2026-02-28')),
|
||||
new AcademicPeriod(3, 'T3', new DateTimeImmutable('2026-03-01'), new DateTimeImmutable('2026-06-30')),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itSortsPeriodsByStartDate(): void
|
||||
{
|
||||
$config = new PeriodConfiguration(PeriodType::TRIMESTER, [
|
||||
new AcademicPeriod(3, 'T3', new DateTimeImmutable('2026-03-01'), new DateTimeImmutable('2026-06-30')),
|
||||
new AcademicPeriod(1, 'T1', new DateTimeImmutable('2025-09-01'), new DateTimeImmutable('2025-11-30')),
|
||||
new AcademicPeriod(2, 'T2', new DateTimeImmutable('2025-12-01'), new DateTimeImmutable('2026-02-28')),
|
||||
]);
|
||||
|
||||
self::assertSame('T1', $config->periods[0]->label);
|
||||
self::assertSame('T2', $config->periods[1]->label);
|
||||
self::assertSame('T3', $config->periods[2]->label);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itFindsCurrentPeriod(): void
|
||||
{
|
||||
$config = $this->validTrimesterConfig();
|
||||
|
||||
$current = $config->currentPeriod(new DateTimeImmutable('2025-10-15'));
|
||||
self::assertNotNull($current);
|
||||
self::assertSame('T1', $current->label);
|
||||
|
||||
$current = $config->currentPeriod(new DateTimeImmutable('2026-01-15'));
|
||||
self::assertNotNull($current);
|
||||
self::assertSame('T2', $current->label);
|
||||
|
||||
$current = $config->currentPeriod(new DateTimeImmutable('2026-05-01'));
|
||||
self::assertNotNull($current);
|
||||
self::assertSame('T3', $current->label);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itReturnsNullWhenNoCurrentPeriod(): void
|
||||
{
|
||||
$config = $this->validTrimesterConfig();
|
||||
|
||||
self::assertNull($config->currentPeriod(new DateTimeImmutable('2025-08-01')));
|
||||
self::assertNull($config->currentPeriod(new DateTimeImmutable('2026-07-01')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itFindsPeriodBySequence(): void
|
||||
{
|
||||
$config = $this->validTrimesterConfig();
|
||||
|
||||
$period = $config->periodBySequence(2);
|
||||
self::assertNotNull($period);
|
||||
self::assertSame('T2', $period->label);
|
||||
|
||||
self::assertNull($config->periodBySequence(4));
|
||||
}
|
||||
|
||||
private function validTrimesterConfig(): PeriodConfiguration
|
||||
{
|
||||
return new PeriodConfiguration(PeriodType::TRIMESTER, [
|
||||
new AcademicPeriod(1, 'T1', new DateTimeImmutable('2025-09-01'), new DateTimeImmutable('2025-11-30')),
|
||||
new AcademicPeriod(2, 'T2', new DateTimeImmutable('2025-12-01'), new DateTimeImmutable('2026-02-28')),
|
||||
new AcademicPeriod(3, 'T3', new DateTimeImmutable('2026-03-01'), new DateTimeImmutable('2026-06-30')),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Domain\Model\AcademicYear;
|
||||
|
||||
use App\Administration\Domain\Model\AcademicYear\PeriodType;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class PeriodTypeTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function trimesterExpectsThreePeriods(): void
|
||||
{
|
||||
self::assertSame(3, PeriodType::TRIMESTER->expectedCount());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function semesterExpectsTwoPeriods(): void
|
||||
{
|
||||
self::assertSame(2, PeriodType::SEMESTER->expectedCount());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function itHasCorrectValues(): void
|
||||
{
|
||||
self::assertSame('trimester', PeriodType::TRIMESTER->value);
|
||||
self::assertSame('semester', PeriodType::SEMESTER->value);
|
||||
}
|
||||
}
|
||||
@@ -112,8 +112,9 @@ final class SubjectTest extends TestCase
|
||||
$events = $subject->pullDomainEvents();
|
||||
self::assertCount(1, $events);
|
||||
self::assertInstanceOf(MatiereModifiee::class, $events[0]);
|
||||
self::assertTrue($events[0]->ancienNom->equals($ancienNom));
|
||||
self::assertTrue($events[0]->nouveauNom->equals($nouveauNom));
|
||||
self::assertSame('nom', $events[0]->champ);
|
||||
self::assertSame((string) $ancienNom, $events[0]->ancienneValeur);
|
||||
self::assertSame((string) $nouveauNom, $events[0]->nouvelleValeur);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@@ -130,9 +131,10 @@ final class SubjectTest extends TestCase
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function changerCodeUpdatesCode(): void
|
||||
public function changerCodeUpdatesCodeAndRecordsEvent(): void
|
||||
{
|
||||
$subject = $this->createSubject();
|
||||
$subject->pullDomainEvents();
|
||||
$at = new DateTimeImmutable('2026-02-01 10:00:00');
|
||||
$nouveauCode = new SubjectCode('MATHS');
|
||||
|
||||
@@ -140,23 +142,33 @@ final class SubjectTest extends TestCase
|
||||
|
||||
self::assertTrue($subject->code->equals($nouveauCode));
|
||||
self::assertEquals($at, $subject->updatedAt);
|
||||
|
||||
$events = $subject->pullDomainEvents();
|
||||
self::assertCount(1, $events);
|
||||
self::assertInstanceOf(MatiereModifiee::class, $events[0]);
|
||||
self::assertSame('code', $events[0]->champ);
|
||||
self::assertSame('MATH', $events[0]->ancienneValeur);
|
||||
self::assertSame('MATHS', $events[0]->nouvelleValeur);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function changerCodeWithSameCodeDoesNothing(): void
|
||||
{
|
||||
$subject = $this->createSubject();
|
||||
$subject->pullDomainEvents();
|
||||
$originalUpdatedAt = $subject->updatedAt;
|
||||
|
||||
$subject->changerCode(new SubjectCode('MATH'), new DateTimeImmutable('2026-02-01 10:00:00'));
|
||||
|
||||
self::assertEquals($originalUpdatedAt, $subject->updatedAt);
|
||||
self::assertEmpty($subject->pullDomainEvents());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function changerCouleurUpdatesColor(): void
|
||||
public function changerCouleurUpdatesColorAndRecordsEvent(): void
|
||||
{
|
||||
$subject = $this->createSubject();
|
||||
$subject->pullDomainEvents();
|
||||
$at = new DateTimeImmutable('2026-02-01 10:00:00');
|
||||
$nouvelleCouleur = new SubjectColor('#EF4444');
|
||||
|
||||
@@ -165,41 +177,66 @@ final class SubjectTest extends TestCase
|
||||
self::assertNotNull($subject->color);
|
||||
self::assertTrue($subject->color->equals($nouvelleCouleur));
|
||||
self::assertEquals($at, $subject->updatedAt);
|
||||
|
||||
$events = $subject->pullDomainEvents();
|
||||
self::assertCount(1, $events);
|
||||
self::assertInstanceOf(MatiereModifiee::class, $events[0]);
|
||||
self::assertSame('couleur', $events[0]->champ);
|
||||
self::assertSame('#3B82F6', $events[0]->ancienneValeur);
|
||||
self::assertSame('#EF4444', $events[0]->nouvelleValeur);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function changerCouleurToNullRemovesColor(): void
|
||||
public function changerCouleurToNullRemovesColorAndRecordsEvent(): void
|
||||
{
|
||||
$subject = $this->createSubject();
|
||||
$subject->pullDomainEvents();
|
||||
$at = new DateTimeImmutable('2026-02-01 10:00:00');
|
||||
|
||||
$subject->changerCouleur(null, $at);
|
||||
|
||||
self::assertNull($subject->color);
|
||||
self::assertEquals($at, $subject->updatedAt);
|
||||
|
||||
$events = $subject->pullDomainEvents();
|
||||
self::assertCount(1, $events);
|
||||
self::assertInstanceOf(MatiereModifiee::class, $events[0]);
|
||||
self::assertSame('couleur', $events[0]->champ);
|
||||
self::assertSame('#3B82F6', $events[0]->ancienneValeur);
|
||||
self::assertNull($events[0]->nouvelleValeur);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function changerCouleurWithSameColorDoesNothing(): void
|
||||
{
|
||||
$subject = $this->createSubject();
|
||||
$subject->pullDomainEvents();
|
||||
$originalUpdatedAt = $subject->updatedAt;
|
||||
|
||||
$subject->changerCouleur(new SubjectColor('#3B82F6'), new DateTimeImmutable('2026-02-01 10:00:00'));
|
||||
|
||||
self::assertEquals($originalUpdatedAt, $subject->updatedAt);
|
||||
self::assertEmpty($subject->pullDomainEvents());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function decrireUpdatesDescription(): void
|
||||
public function decrireUpdatesDescriptionAndRecordsEvent(): void
|
||||
{
|
||||
$subject = $this->createSubject();
|
||||
$subject->pullDomainEvents();
|
||||
$at = new DateTimeImmutable('2026-02-01 10:00:00');
|
||||
|
||||
$subject->decrire('Cours de mathématiques généralistes', $at);
|
||||
|
||||
self::assertSame('Cours de mathématiques généralistes', $subject->description);
|
||||
self::assertEquals($at, $subject->updatedAt);
|
||||
|
||||
$events = $subject->pullDomainEvents();
|
||||
self::assertCount(1, $events);
|
||||
self::assertInstanceOf(MatiereModifiee::class, $events[0]);
|
||||
self::assertSame('description', $events[0]->champ);
|
||||
self::assertNull($events[0]->ancienneValeur);
|
||||
self::assertSame('Cours de mathématiques généralistes', $events[0]->nouvelleValeur);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
|
||||
Reference in New Issue
Block a user