gmao/app_new/lib_ext/pronotepy/test_grade_parsing.py
2026-08-14 16:02:25 +00:00

164 lines
6 KiB
Python

"""Tests for Grade parsing with missing optional fields.
Some Pronote instances (e.g. 0941093c.index-education.net) do not include
fields like noteMax, noteMin, coefficient, etc. in their grade JSON data.
These tests verify that Grade objects can be constructed without crashing
when those fields are absent.
"""
import unittest
from unittest.mock import MagicMock
from pronotepy.dataClasses import Grade, Period
def _make_grade_json(
include_noteMax: bool = True,
include_noteMin: bool = True,
include_coefficient: bool = True,
include_commentaire: bool = True,
include_estBonus: bool = True,
include_estFacultatif: bool = True,
include_estRamenerSur20: bool = True,
include_moyenne: bool = True,
) -> dict:
"""Build a grade JSON dict with optional fields toggled on/off."""
# Minimal required fields
json_dict: dict = {
"N": "001",
"note": {"V": "15"},
"bareme": {"V": "20"},
"baremeParDefaut": {"V": "20"},
"date": {"V": "15/01/2026"},
"service": {"V": {"N": "101", "L": "MATHEMATIQUES", "estServiceGroupe": False}},
"periode": {"V": {"N": "test_period_id"}},
}
if include_noteMax:
json_dict["noteMax"] = {"V": "19"}
if include_noteMin:
json_dict["noteMin"] = {"V": "5"}
if include_coefficient:
json_dict["coefficient"] = "1"
if include_commentaire:
json_dict["commentaire"] = "Good work"
if include_estBonus:
json_dict["estBonus"] = False
if include_estFacultatif:
json_dict["estFacultatif"] = False
if include_estRamenerSur20:
json_dict["estRamenerSur20"] = False
if include_moyenne:
json_dict["moyenne"] = {"V": "12"}
return json_dict
class TestGradeMissingFields(unittest.TestCase):
"""Test that Grade parsing handles missing optional fields gracefully."""
@classmethod
def setUpClass(cls) -> None:
# Create a mock Period instance so the period resolver can find it
mock_period = MagicMock(spec=Period)
mock_period.id = "test_period_id"
Period.instances.add(mock_period)
@classmethod
def tearDownClass(cls) -> None:
# Clean up mock period instances
Period.instances = {p for p in Period.instances if not isinstance(p, MagicMock)}
def test_all_fields_present(self) -> None:
"""Parsing works when all fields are present."""
json_dict = _make_grade_json()
grade = Grade(json_dict)
self.assertEqual(grade.grade, "15")
self.assertEqual(grade.max, "19")
self.assertEqual(grade.min, "5")
self.assertEqual(grade.coefficient, "1")
self.assertEqual(grade.comment, "Good work")
self.assertFalse(grade.is_bonus)
self.assertFalse(grade.is_optionnal)
self.assertFalse(grade.is_out_of_20)
def test_missing_noteMax(self) -> None:
"""Parsing does not crash when noteMax is missing."""
json_dict = _make_grade_json(include_noteMax=False)
grade = Grade(json_dict)
self.assertIsNone(grade.max)
# Other fields should still be parsed correctly
self.assertEqual(grade.grade, "15")
self.assertEqual(grade.min, "5")
def test_missing_noteMin(self) -> None:
"""Parsing does not crash when noteMin is missing."""
json_dict = _make_grade_json(include_noteMin=False)
grade = Grade(json_dict)
self.assertIsNone(grade.min)
def test_missing_coefficient(self) -> None:
"""Parsing does not crash when coefficient is missing."""
json_dict = _make_grade_json(include_coefficient=False)
grade = Grade(json_dict)
self.assertIsNone(grade.coefficient)
def test_missing_commentaire(self) -> None:
"""Parsing does not crash when commentaire is missing."""
json_dict = _make_grade_json(include_commentaire=False)
grade = Grade(json_dict)
self.assertIsNone(grade.comment)
def test_missing_estBonus(self) -> None:
"""Parsing does not crash when estBonus is missing."""
json_dict = _make_grade_json(include_estBonus=False)
grade = Grade(json_dict)
self.assertFalse(grade.is_bonus)
def test_missing_estFacultatif(self) -> None:
"""Parsing does not crash when estFacultatif is missing."""
json_dict = _make_grade_json(include_estFacultatif=False)
grade = Grade(json_dict)
self.assertFalse(grade.is_optionnal)
def test_missing_estRamenerSur20(self) -> None:
"""Parsing does not crash when estRamenerSur20 is missing."""
json_dict = _make_grade_json(include_estRamenerSur20=False)
grade = Grade(json_dict)
self.assertFalse(grade.is_out_of_20)
def test_missing_moyenne(self) -> None:
"""Parsing does not crash when moyenne is missing."""
json_dict = _make_grade_json(include_moyenne=False)
grade = Grade(json_dict)
self.assertIsNone(grade.average)
def test_all_optional_fields_missing(self) -> None:
"""Parsing does not crash when ALL optional fields are missing.
This simulates the worst case scenario where a Pronote instance
returns only the bare minimum grade data.
"""
json_dict = _make_grade_json(
include_noteMax=False,
include_noteMin=False,
include_coefficient=False,
include_commentaire=False,
include_estBonus=False,
include_estFacultatif=False,
include_estRamenerSur20=False,
include_moyenne=False,
)
grade = Grade(json_dict)
self.assertEqual(grade.grade, "15")
self.assertEqual(grade.out_of, "20")
self.assertIsNone(grade.max)
self.assertIsNone(grade.min)
self.assertIsNone(grade.coefficient)
self.assertIsNone(grade.comment)
self.assertFalse(grade.is_bonus)
self.assertFalse(grade.is_optionnal)
self.assertFalse(grade.is_out_of_20)
self.assertIsNone(grade.average)
if __name__ == "__main__":
unittest.main()