createPolicy(new DateTimeImmutable('2026-03-28 10:00:00')); $evaluation = $this->createPublishedEvaluation(new DateTimeImmutable('2026-03-27 14:00:00')); self::assertTrue($policy->visiblePourEleve($evaluation)); } #[Test] public function eleveNeVoitPasNotesBrouillon(): void { $policy = $this->createPolicy(new DateTimeImmutable('2026-03-27 15:00:00')); $evaluation = $this->createUnpublishedEvaluation(); self::assertFalse($policy->visiblePourEleve($evaluation)); } #[Test] public function parentNeVoitPasAvant24h(): void { $publishedAt = new DateTimeImmutable('2026-03-27 14:00:00'); $now = new DateTimeImmutable('2026-03-28 13:59:59'); // 23h59 après $policy = $this->createPolicy($now); $evaluation = $this->createPublishedEvaluation($publishedAt); self::assertFalse($policy->visiblePourParent($evaluation)); } #[Test] public function parentVoitApres24h(): void { $publishedAt = new DateTimeImmutable('2026-03-27 14:00:00'); $now = new DateTimeImmutable('2026-03-28 14:00:00'); // exactement 24h après $policy = $this->createPolicy($now); $evaluation = $this->createPublishedEvaluation($publishedAt); self::assertTrue($policy->visiblePourParent($evaluation)); } #[Test] public function parentNeVoitPasNotesBrouillon(): void { $policy = $this->createPolicy(new DateTimeImmutable('2026-04-01 10:00:00')); $evaluation = $this->createUnpublishedEvaluation(); self::assertFalse($policy->visiblePourParent($evaluation)); } private function createPolicy(DateTimeImmutable $now): VisibiliteNotesPolicy { $clock = new class($now) implements Clock { public function __construct(private readonly DateTimeImmutable $now) { } public function now(): DateTimeImmutable { return $this->now; } }; return new VisibiliteNotesPolicy($clock); } private function createPublishedEvaluation(DateTimeImmutable $publishedAt): Evaluation { return Evaluation::reconstitute( id: EvaluationId::generate(), tenantId: TenantId::fromString('550e8400-e29b-41d4-a716-446655440001'), classId: ClassId::fromString('550e8400-e29b-41d4-a716-446655440020'), subjectId: SubjectId::fromString('550e8400-e29b-41d4-a716-446655440030'), teacherId: UserId::fromString('550e8400-e29b-41d4-a716-446655440010'), title: 'Test', description: null, evaluationDate: new DateTimeImmutable('2026-04-15'), gradeScale: new GradeScale(20), coefficient: new Coefficient(1.0), status: EvaluationStatus::PUBLISHED, createdAt: new DateTimeImmutable('2026-03-12 10:00:00'), updatedAt: $publishedAt, gradesPublishedAt: $publishedAt, ); } private function createUnpublishedEvaluation(): Evaluation { return Evaluation::reconstitute( id: EvaluationId::generate(), tenantId: TenantId::fromString('550e8400-e29b-41d4-a716-446655440001'), classId: ClassId::fromString('550e8400-e29b-41d4-a716-446655440020'), subjectId: SubjectId::fromString('550e8400-e29b-41d4-a716-446655440030'), teacherId: UserId::fromString('550e8400-e29b-41d4-a716-446655440010'), title: 'Test', description: null, evaluationDate: new DateTimeImmutable('2026-04-15'), gradeScale: new GradeScale(20), coefficient: new Coefficient(1.0), status: EvaluationStatus::PUBLISHED, createdAt: new DateTimeImmutable('2026-03-12 10:00:00'), updatedAt: new DateTimeImmutable('2026-03-12 10:00:00'), ); } }