L'élève avait accès à ses compétences mais pas à ses notes numériques. Cette fonctionnalité lui donne une vue complète de sa progression scolaire avec moyennes par matière, détail par évaluation, statistiques de classe, et un mode "découverte" pour révéler ses notes à son rythme (FR14, FR15). Les notes ne sont visibles qu'après publication par l'enseignant, ce qui garantit que l'élève les découvre avant ses parents (délai 24h story 6.7).
172 lines
6.4 KiB
PHP
172 lines
6.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Unit\Scolarite\Domain\Policy;
|
|
|
|
use App\Administration\Domain\Model\SchoolClass\ClassId;
|
|
use App\Administration\Domain\Model\Subject\SubjectId;
|
|
use App\Administration\Domain\Model\User\UserId;
|
|
use App\Scolarite\Domain\Model\Evaluation\Coefficient;
|
|
use App\Scolarite\Domain\Model\Evaluation\Evaluation;
|
|
use App\Scolarite\Domain\Model\Evaluation\EvaluationId;
|
|
use App\Scolarite\Domain\Model\Evaluation\EvaluationStatus;
|
|
use App\Scolarite\Domain\Model\Evaluation\GradeScale;
|
|
use App\Scolarite\Domain\Policy\VisibiliteNotesPolicy;
|
|
use App\Shared\Domain\Clock;
|
|
use App\Shared\Domain\Tenant\TenantId;
|
|
use DateTimeImmutable;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class VisibiliteNotesPolicyTest extends TestCase
|
|
{
|
|
#[Test]
|
|
public function eleveVoitNotesPubliees(): void
|
|
{
|
|
$policy = $this->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));
|
|
}
|
|
|
|
#[Test]
|
|
public function parentVoitImmediatementAvecDelaiZero(): void
|
|
{
|
|
$publishedAt = new DateTimeImmutable('2026-03-27 14:00:00');
|
|
$now = new DateTimeImmutable('2026-03-27 14:00:01'); // 1 seconde après
|
|
$policy = $this->createPolicy($now);
|
|
$evaluation = $this->createPublishedEvaluation($publishedAt);
|
|
|
|
self::assertTrue($policy->visiblePourParent($evaluation, delaiHeures: 0));
|
|
}
|
|
|
|
#[Test]
|
|
public function parentNeVoitPasAvec48hDeDelai(): void
|
|
{
|
|
$publishedAt = new DateTimeImmutable('2026-03-27 14:00:00');
|
|
$now = new DateTimeImmutable('2026-03-29 13:59:59'); // 47h59 après
|
|
$policy = $this->createPolicy($now);
|
|
$evaluation = $this->createPublishedEvaluation($publishedAt);
|
|
|
|
self::assertFalse($policy->visiblePourParent($evaluation, delaiHeures: 48));
|
|
}
|
|
|
|
#[Test]
|
|
public function parentVoitApres48hDeDelai(): void
|
|
{
|
|
$publishedAt = new DateTimeImmutable('2026-03-27 14:00:00');
|
|
$now = new DateTimeImmutable('2026-03-29 14:00:00'); // exactement 48h après
|
|
$policy = $this->createPolicy($now);
|
|
$evaluation = $this->createPublishedEvaluation($publishedAt);
|
|
|
|
self::assertTrue($policy->visiblePourParent($evaluation, delaiHeures: 48));
|
|
}
|
|
|
|
#[Test]
|
|
public function parentVoitImmediatementAvecDelaiNegatifTraiteCommeZero(): void
|
|
{
|
|
$publishedAt = new DateTimeImmutable('2026-03-27 14:00:00');
|
|
$now = new DateTimeImmutable('2026-03-27 14:00:01');
|
|
$policy = $this->createPolicy($now);
|
|
$evaluation = $this->createPublishedEvaluation($publishedAt);
|
|
|
|
self::assertTrue($policy->visiblePourParent($evaluation, delaiHeures: -5));
|
|
}
|
|
|
|
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'),
|
|
);
|
|
}
|
|
}
|