fix(pronote): préserver les cours déplacés et changements de salle
Revue Codex validée. Statuts canoniques iCal/pronotepy et consolidation prudente des cours remplacés. Co-authored-by: Codex <codex@antoineve.me> Co-committed-by: Codex <codex@antoineve.me>
This commit was merged in pull request #32.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
"""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]
|
||||
Reference in New Issue
Block a user