feat: Permettre à l'élève de consulter ses notes et moyennes
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).
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Scolarite\Infrastructure\Persistence\InMemory;
|
||||
|
||||
use App\Administration\Domain\Model\User\UserId;
|
||||
use App\Scolarite\Domain\Model\Evaluation\EvaluationId;
|
||||
use App\Scolarite\Domain\Model\Evaluation\GradeScale;
|
||||
use App\Scolarite\Domain\Model\Grade\Grade;
|
||||
use App\Scolarite\Domain\Model\Grade\GradeStatus;
|
||||
use App\Scolarite\Domain\Model\Grade\GradeValue;
|
||||
use App\Scolarite\Infrastructure\Persistence\InMemory\InMemoryGradeRepository;
|
||||
use App\Shared\Domain\Tenant\TenantId;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class InMemoryGradeRepositoryTest extends TestCase
|
||||
{
|
||||
private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
|
||||
private const string OTHER_TENANT_ID = '550e8400-e29b-41d4-a716-446655440002';
|
||||
private const string EVALUATION_A_ID = '550e8400-e29b-41d4-a716-446655440010';
|
||||
private const string EVALUATION_B_ID = '550e8400-e29b-41d4-a716-446655440011';
|
||||
private const string EVALUATION_C_ID = '550e8400-e29b-41d4-a716-446655440012';
|
||||
private const string STUDENT_ID = '550e8400-e29b-41d4-a716-446655440020';
|
||||
private const string TEACHER_ID = '550e8400-e29b-41d4-a716-446655440030';
|
||||
|
||||
private InMemoryGradeRepository $repository;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->repository = new InMemoryGradeRepository();
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function findByEvaluationsReturnsGroupedResults(): void
|
||||
{
|
||||
$gradeA1 = $this->createGrade(self::EVALUATION_A_ID, self::TENANT_ID, 14.0);
|
||||
$gradeA2 = $this->createGrade(self::EVALUATION_A_ID, self::TENANT_ID, 16.0);
|
||||
$gradeB1 = $this->createGrade(self::EVALUATION_B_ID, self::TENANT_ID, 12.0);
|
||||
|
||||
$this->repository->save($gradeA1);
|
||||
$this->repository->save($gradeA2);
|
||||
$this->repository->save($gradeB1);
|
||||
|
||||
$result = $this->repository->findByEvaluations(
|
||||
[
|
||||
EvaluationId::fromString(self::EVALUATION_A_ID),
|
||||
EvaluationId::fromString(self::EVALUATION_B_ID),
|
||||
],
|
||||
TenantId::fromString(self::TENANT_ID),
|
||||
);
|
||||
|
||||
self::assertCount(2, $result);
|
||||
self::assertArrayHasKey(self::EVALUATION_A_ID, $result);
|
||||
self::assertArrayHasKey(self::EVALUATION_B_ID, $result);
|
||||
self::assertCount(2, $result[self::EVALUATION_A_ID]);
|
||||
self::assertCount(1, $result[self::EVALUATION_B_ID]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function findByEvaluationsReturnsEmptyArrayWhenNoEvaluationIds(): void
|
||||
{
|
||||
$grade = $this->createGrade(self::EVALUATION_A_ID, self::TENANT_ID, 14.0);
|
||||
$this->repository->save($grade);
|
||||
|
||||
$result = $this->repository->findByEvaluations(
|
||||
[],
|
||||
TenantId::fromString(self::TENANT_ID),
|
||||
);
|
||||
|
||||
self::assertSame([], $result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function findByEvaluationsExcludesGradesFromDifferentTenant(): void
|
||||
{
|
||||
$gradeOwnTenant = $this->createGrade(self::EVALUATION_A_ID, self::TENANT_ID, 14.0);
|
||||
$gradeOtherTenant = $this->createGrade(self::EVALUATION_A_ID, self::OTHER_TENANT_ID, 18.0);
|
||||
|
||||
$this->repository->save($gradeOwnTenant);
|
||||
$this->repository->save($gradeOtherTenant);
|
||||
|
||||
$result = $this->repository->findByEvaluations(
|
||||
[EvaluationId::fromString(self::EVALUATION_A_ID)],
|
||||
TenantId::fromString(self::TENANT_ID),
|
||||
);
|
||||
|
||||
self::assertCount(1, $result);
|
||||
self::assertArrayHasKey(self::EVALUATION_A_ID, $result);
|
||||
self::assertCount(1, $result[self::EVALUATION_A_ID]);
|
||||
self::assertSame($gradeOwnTenant, $result[self::EVALUATION_A_ID][0]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function findByEvaluationsExcludesGradesForUnrequestedEvaluations(): void
|
||||
{
|
||||
$gradeA = $this->createGrade(self::EVALUATION_A_ID, self::TENANT_ID, 14.0);
|
||||
$gradeC = $this->createGrade(self::EVALUATION_C_ID, self::TENANT_ID, 10.0);
|
||||
|
||||
$this->repository->save($gradeA);
|
||||
$this->repository->save($gradeC);
|
||||
|
||||
$result = $this->repository->findByEvaluations(
|
||||
[EvaluationId::fromString(self::EVALUATION_A_ID)],
|
||||
TenantId::fromString(self::TENANT_ID),
|
||||
);
|
||||
|
||||
self::assertCount(1, $result);
|
||||
self::assertArrayHasKey(self::EVALUATION_A_ID, $result);
|
||||
self::assertArrayNotHasKey(self::EVALUATION_C_ID, $result);
|
||||
}
|
||||
|
||||
private function createGrade(
|
||||
string $evaluationId,
|
||||
string $tenantId,
|
||||
float $value,
|
||||
): Grade {
|
||||
return Grade::saisir(
|
||||
tenantId: TenantId::fromString($tenantId),
|
||||
evaluationId: EvaluationId::fromString($evaluationId),
|
||||
studentId: UserId::fromString(self::STUDENT_ID),
|
||||
value: new GradeValue($value),
|
||||
status: GradeStatus::GRADED,
|
||||
gradeScale: new GradeScale(20),
|
||||
createdBy: UserId::fromString(self::TEACHER_ID),
|
||||
now: new DateTimeImmutable('2026-03-26 10:00:00'),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user