92 lines
2.7 KiB
Python
92 lines
2.7 KiB
Python
"""Tests des règles communes de statut et de consolidation des cours."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
import pytest
|
|
|
|
from pronote_sync.models.agenda import Lesson, LessonStatus
|
|
from pronote_sync.sources.pronote.lessons import collapse_replaced_lessons, lesson_status
|
|
|
|
|
|
def _lesson(status: LessonStatus, room: str) -> Lesson:
|
|
"""Construit un cours minimal pour les tests de consolidation.
|
|
|
|
:param status: Statut métier du cours.
|
|
:param room: Salle du cours.
|
|
:return: Cours de test.
|
|
:rtype: Lesson
|
|
"""
|
|
return Lesson(
|
|
id=f"lesson-{room}",
|
|
start=datetime(2026, 9, 11, 8, 0),
|
|
end=datetime(2026, 9, 11, 9, 0),
|
|
subject="Mathématiques",
|
|
teachers=("Enseignant A",),
|
|
rooms=(room,),
|
|
group="Classe entière",
|
|
status=status,
|
|
content=None,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("raw_status", "canceled", "expected"),
|
|
[
|
|
("Changement de salle", False, LessonStatus.MOVED),
|
|
("Cours déplacé", False, LessonStatus.MOVED),
|
|
("Cours annulé", False, LessonStatus.CANCELLED),
|
|
(None, True, LessonStatus.CANCELLED),
|
|
("Statut inconnu", False, LessonStatus.NORMAL),
|
|
],
|
|
)
|
|
def test_lesson_status_maps_pronotepy_variants(
|
|
raw_status: object, canceled: bool, expected: LessonStatus
|
|
) -> None:
|
|
"""Convertit les statuts Pronote connus sans interpréter les inconnus.
|
|
|
|
:param raw_status: Statut brut simulé.
|
|
:param canceled: Indicateur d'annulation simulé.
|
|
:param expected: Statut métier attendu.
|
|
:return: None
|
|
"""
|
|
assert lesson_status(raw_status, canceled) == expected
|
|
|
|
|
|
def test_collapse_replaced_lessons_keeps_effective_lesson() -> None:
|
|
"""Retire l'ancien exemplaire annulé d'un changement de salle.
|
|
|
|
:return: None
|
|
"""
|
|
cancelled = _lesson(LessonStatus.CANCELLED, "101")
|
|
moved = _lesson(LessonStatus.MOVED, "204")
|
|
|
|
result = collapse_replaced_lessons([cancelled, moved])
|
|
|
|
assert result == [moved]
|
|
|
|
|
|
def test_collapse_replaced_lessons_keeps_real_cancellation() -> None:
|
|
"""Conserve une annulation lorsqu'aucun cours déplacé ne la remplace.
|
|
|
|
:return: None
|
|
"""
|
|
cancelled = _lesson(LessonStatus.CANCELLED, "101")
|
|
|
|
assert collapse_replaced_lessons([cancelled]) == [cancelled]
|
|
|
|
|
|
def test_collapse_replaced_lessons_keeps_ambiguous_cancellations() -> None:
|
|
"""Conserve les annulations lorsqu'une paire de remplacement est ambiguë.
|
|
|
|
:return: None
|
|
"""
|
|
cancelled_old = _lesson(LessonStatus.CANCELLED, "101")
|
|
cancelled_real = _lesson(LessonStatus.CANCELLED, "305")
|
|
moved = _lesson(LessonStatus.MOVED, "204")
|
|
|
|
result = collapse_replaced_lessons([cancelled_old, cancelled_real, moved])
|
|
|
|
assert result == [cancelled_old, cancelled_real, moved]
|