validator = new HomeworkRulesValidator(); } // -- Règles désactivées -- #[Test] public function disabledRulesAlwaysValid(): void { $rules = $this->creerRulesAvecDelai(3, EnforcementMode::DISABLED, false); $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-20'), // vendredi new DateTimeImmutable('2026-03-19 15:00'), // jeudi (1 jour, < 3) ); self::assertTrue($result->estValide()); } // -- Délai minimum (AC3) -- #[Test] public function delaiMinimumOkQuandRespected(): void { $rules = $this->creerRulesAvecDelai(3); // Devoir vendredi 20 mars, créé mardi 17 mars = 3 jours = OK $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-20'), new DateTimeImmutable('2026-03-17 10:00'), ); self::assertTrue($result->estValide()); } #[Test] public function delaiMinimumViolationQuandTropTard(): void { $rules = $this->creerRulesAvecDelai(3); // Devoir vendredi 20 mars, créé mercredi 18 mars = 2 jours < 3 $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-20'), new DateTimeImmutable('2026-03-18 10:00'), ); self::assertFalse($result->estValide()); self::assertCount(1, $result->violations); self::assertSame(RuleType::MINIMUM_DELAY, $result->violations[0]->ruleType); } #[Test] public function delaiMinimumSoftModeRetourneAvertissement(): void { $rules = $this->creerRulesAvecDelai(3, EnforcementMode::SOFT); $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-20'), new DateTimeImmutable('2026-03-18 10:00'), ); self::assertTrue($result->estAvertissement()); self::assertFalse($result->estBloquant()); } #[Test] public function delaiMinimumHardModeRetourneErreur(): void { $rules = $this->creerRulesAvecDelai(3, EnforcementMode::HARD); $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-20'), new DateTimeImmutable('2026-03-18 10:00'), ); self::assertTrue($result->estBloquant()); self::assertFalse($result->estAvertissement()); } // -- Règle pas de devoir pour lundi (AC4) -- #[Test] public function pasLundiApresOkQuandCreationAvantCutoff(): void { $rules = $this->creerRulesAvecLundi(); // Devoir pour lundi 23 mars, créé vendredi 20 mars à 11h (avant 12h) $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-23'), // lundi new DateTimeImmutable('2026-03-20 11:00'), // vendredi 11h ); self::assertTrue($result->estValide()); } #[Test] public function pasLundiApresViolationQuandCreationApresCutoff(): void { $rules = $this->creerRulesAvecLundi(); // Devoir pour lundi 23 mars, créé vendredi 20 mars à 14h (après 12h) $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-23'), // lundi new DateTimeImmutable('2026-03-20 14:00'), // vendredi 14h ); self::assertFalse($result->estValide()); self::assertSame(RuleType::NO_MONDAY_AFTER, $result->violations[0]->ruleType); } #[Test] public function pasLundiApresIgnorePourJoursNonLundi(): void { $rules = $this->creerRulesAvecLundi(); // Devoir pour mardi 24 mars, créé n'importe quand $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-24'), // mardi new DateTimeImmutable('2026-03-23 20:00'), // lundi soir ); self::assertTrue($result->estValide()); } #[Test] public function pasLundiApresViolationSamediCreation(): void { $rules = $this->creerRulesAvecLundi(); // Devoir pour lundi 23 mars, créé samedi 21 mars (après vendredi 12h) $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-23'), // lundi new DateTimeImmutable('2026-03-21 10:00'), // samedi ); self::assertFalse($result->estValide()); } // -- Règles combinées -- #[Test] public function multipleViolationsQuandPlusieursReglesEnfreintes(): void { $rules = $this->creerRulesComplet(); // Devoir pour lundi 23 mars, créé samedi 21 mars 10h // Violation délai minimum (3 jours: 23-3 = 20, samedi 21 > 20) // Violation lundi (après vendredi 12h) $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-23'), // lundi new DateTimeImmutable('2026-03-21 10:00'), // samedi ); self::assertFalse($result->estValide()); self::assertCount(2, $result->violations); } #[Test] public function messagesRetourneListeMessages(): void { $rules = $this->creerRulesAvecDelai(3); $result = $this->validator->valider( $rules, new DateTimeImmutable('2026-03-20'), new DateTimeImmutable('2026-03-19 10:00'), ); self::assertCount(1, $result->messages()); self::assertStringContainsString('3 jours', $result->messages()[0]); } // -- Helpers -- private function creerRulesAvecDelai( int $days, EnforcementMode $mode = EnforcementMode::SOFT, bool $enabled = true, ): HomeworkRules { $rules = HomeworkRules::creer( tenantId: TenantId::fromString('550e8400-e29b-41d4-a716-446655440001'), now: new DateTimeImmutable('2026-03-01'), ); $rules->mettreAJour( rules: [new HomeworkRule(RuleType::MINIMUM_DELAY, ['days' => $days])], enforcementMode: $mode, enabled: $enabled, now: new DateTimeImmutable('2026-03-01'), ); return $rules; } private function creerRulesAvecLundi( EnforcementMode $mode = EnforcementMode::SOFT, ): HomeworkRules { $rules = HomeworkRules::creer( tenantId: TenantId::fromString('550e8400-e29b-41d4-a716-446655440001'), now: new DateTimeImmutable('2026-03-01'), ); $rules->mettreAJour( rules: [new HomeworkRule(RuleType::NO_MONDAY_AFTER, ['day' => 'friday', 'time' => '12:00'])], enforcementMode: $mode, enabled: true, now: new DateTimeImmutable('2026-03-01'), ); return $rules; } private function creerRulesComplet( EnforcementMode $mode = EnforcementMode::SOFT, ): HomeworkRules { $rules = HomeworkRules::creer( tenantId: TenantId::fromString('550e8400-e29b-41d4-a716-446655440001'), now: new DateTimeImmutable('2026-03-01'), ); $rules->mettreAJour( rules: [ new HomeworkRule(RuleType::MINIMUM_DELAY, ['days' => 3]), new HomeworkRule(RuleType::NO_MONDAY_AFTER, ['day' => 'friday', 'time' => '12:00']), ], enforcementMode: $mode, enabled: true, now: new DateTimeImmutable('2026-03-01'), ); return $rules; } }