PRONOTE_ENT était incorrectement traité comme obligatoire pour pronotepy. Rend ENT optionnel pour les connexions directes, conformément à la spécification. Corrige le mode pronotepy explicite et le mode auto sans iCal. 10 tests de régression ajoutés. Co-authored-by: Antoine Van Elstraete <antoine@van-elstraete.net> Co-committed-by: Antoine Van Elstraete <antoine@van-elstraete.net>
619 lines
20 KiB
Python
619 lines
20 KiB
Python
"""Tests unitaires pour le client Pronote via pronotepy.
|
|
|
|
Ce module vérifie le comportement du client ``PronoteClient`` et de son
|
|
protocole ``PronoteClientProtocol``. Tous les tests sont unitaires et
|
|
utilisent des mocks pour éviter tout accès réseau réel à Pronote.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date, datetime
|
|
|
|
import pronotepy
|
|
import pytest
|
|
import pytest_mock
|
|
from pydantic import SecretStr
|
|
|
|
from pronote_sync.config.settings import PronoteSettings
|
|
from pronote_sync.models.agenda import Lesson, LessonStatus
|
|
from pronote_sync.models.homework import Homework
|
|
from pronote_sync.models.message import Message, MessageType
|
|
from pronote_sync.sources.pronote.client import PronoteClient, PronoteClientProtocol
|
|
|
|
# --- Protocol tests ---
|
|
|
|
|
|
def test_protocol_methods(mocker: pytest_mock.MockerFixture) -> None:
|
|
"""Vérifie que le protocole PronoteClientProtocol expose les méthodes attendues.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:return: None
|
|
"""
|
|
assert hasattr(PronoteClientProtocol, "get_messages")
|
|
assert hasattr(PronoteClientProtocol, "get_informations")
|
|
assert hasattr(PronoteClientProtocol, "get_lessons")
|
|
assert hasattr(PronoteClientProtocol, "get_homeworks")
|
|
|
|
|
|
# --- Client with mocked pronotepy ---
|
|
|
|
|
|
@pytest.fixture
|
|
def pronote_settings() -> PronoteSettings:
|
|
"""Fournit des paramètres Pronote valides pour les tests.
|
|
|
|
:return: Instance de PronoteSettings avec des valeurs par défaut.
|
|
:rtype: PronoteSettings
|
|
"""
|
|
return PronoteSettings(
|
|
pronote_url="https://pronote.example.com",
|
|
username="testuser",
|
|
password=SecretStr("testpass"),
|
|
ent="bordeaux",
|
|
account_type="parent",
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def empty_pronote_settings() -> PronoteSettings:
|
|
"""Fournit des paramètres Pronote vides pour les tests.
|
|
|
|
:return: Instance de PronoteSettings avec tous les champs à None.
|
|
:rtype: PronoteSettings
|
|
"""
|
|
return PronoteSettings(username=None, password=None, ent=None)
|
|
|
|
|
|
def test_get_messages_success(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_messages retourne une liste de Message en cas de succès.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
# Mock du client pronotepy
|
|
mock_client = mocker.MagicMock()
|
|
mock_discussion = mocker.MagicMock()
|
|
mock_discussion.subject = "Test Subject"
|
|
mock_message = mocker.MagicMock()
|
|
mock_message.id = "msg-123"
|
|
mock_message.content = "Test message content"
|
|
mock_message.author = "Teacher Test"
|
|
mock_message.created = datetime(2024, 9, 1, 10, 0, 0)
|
|
mock_message.seen = True
|
|
mock_discussion.messages = [mock_message]
|
|
mock_client.discussions.return_value = [mock_discussion]
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
messages = client.get_messages()
|
|
|
|
assert isinstance(messages, list)
|
|
assert len(messages) == 1
|
|
message = messages[0]
|
|
assert isinstance(message, Message)
|
|
assert message.id == "msg-123"
|
|
assert message.type == MessageType.DISCUSSION
|
|
assert message.title == "Test Subject"
|
|
assert message.content == "Test message content"
|
|
assert message.author == "Teacher Test"
|
|
assert message.date == datetime(2024, 9, 1, 10, 0, 0)
|
|
assert message.read is True
|
|
|
|
|
|
def test_get_messages_empty_on_error(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_messages retourne une liste vide en cas d'erreur API.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
mock_client = mocker.MagicMock()
|
|
mock_client.discussions.side_effect = pronotepy.PronoteAPIError("API error")
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
messages = client.get_messages()
|
|
|
|
assert messages == []
|
|
|
|
|
|
def test_get_informations_success(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_informations retourne une liste de Message en cas de succès.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
mock_client = mocker.MagicMock()
|
|
mock_info = mocker.MagicMock()
|
|
mock_info.id = "info-456"
|
|
mock_info.title = "Important Info"
|
|
mock_info.content.return_value = "Important content"
|
|
mock_info.author = "Admin"
|
|
mock_info.creation_date = datetime(2024, 9, 2, 14, 30, 0)
|
|
mock_info.read = False
|
|
mock_info.survey = True
|
|
mock_client.information_and_surveys.return_value = [mock_info]
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
messages = client.get_informations()
|
|
|
|
assert isinstance(messages, list)
|
|
assert len(messages) == 1
|
|
message = messages[0]
|
|
assert isinstance(message, Message)
|
|
assert message.id == "info-456"
|
|
assert message.type == MessageType.SURVEY
|
|
assert message.title == "Important Info"
|
|
assert message.content == "Important content"
|
|
assert message.author == "Admin"
|
|
assert message.date == datetime(2024, 9, 2, 14, 30, 0)
|
|
assert message.read is False
|
|
|
|
|
|
def test_get_informations_empty_on_error(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_informations retourne une liste vide en cas d'erreur API.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
mock_client = mocker.MagicMock()
|
|
mock_client.information_and_surveys.side_effect = pronotepy.PronoteAPIError("API error")
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
messages = client.get_informations()
|
|
|
|
assert messages == []
|
|
|
|
|
|
def test_get_lessons_success(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_lessons retourne une liste de Lesson en cas de succès.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
mock_client = mocker.MagicMock()
|
|
|
|
# Mock des cours
|
|
mock_lesson = mocker.MagicMock()
|
|
mock_lesson.id = "lesson-789"
|
|
mock_lesson.start = datetime(2024, 9, 1, 8, 0, 0)
|
|
mock_lesson.end = datetime(2024, 9, 1, 9, 30, 0)
|
|
mock_lesson.subject = mocker.MagicMock()
|
|
mock_lesson.subject.name = "Maths"
|
|
mock_lesson.teacher_names = ["Prof A", "Prof B"]
|
|
mock_lesson.classrooms = ["Salle 101", "Salle 102"]
|
|
mock_lesson.group_name = "Classe 1"
|
|
mock_lesson.canceled = False
|
|
mock_content = mocker.MagicMock()
|
|
mock_content.description = "Lesson content"
|
|
mock_lesson.content = mock_content
|
|
|
|
mock_client.lessons.return_value = [mock_lesson]
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
lessons = client.get_lessons(date(2024, 9, 1), date(2024, 9, 30))
|
|
|
|
assert isinstance(lessons, list)
|
|
assert len(lessons) == 1
|
|
lesson = lessons[0]
|
|
assert isinstance(lesson, Lesson)
|
|
assert lesson.id == "lesson-789"
|
|
assert lesson.start == datetime(2024, 9, 1, 8, 0, 0)
|
|
assert lesson.end == datetime(2024, 9, 1, 9, 30, 0)
|
|
assert lesson.subject == "Maths"
|
|
assert lesson.teachers == ("Prof A", "Prof B")
|
|
assert lesson.rooms == ("Salle 101", "Salle 102")
|
|
assert lesson.group == "Classe 1"
|
|
assert lesson.status == LessonStatus.NORMAL
|
|
assert lesson.content == "Lesson content"
|
|
|
|
|
|
def test_get_homeworks_success(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_homeworks retourne une liste de Homework en cas de succès.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
mock_client = mocker.MagicMock()
|
|
|
|
# Mock des devoirs
|
|
mock_hw = mocker.MagicMock()
|
|
mock_hw.id = "hw-101"
|
|
mock_hw.subject = mocker.MagicMock()
|
|
mock_hw.subject.name = "Maths"
|
|
mock_hw.date = date(2024, 9, 15)
|
|
mock_hw.description = "Do your homework"
|
|
|
|
mock_client.homework.return_value = [mock_hw]
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
homeworks = client.get_homeworks(date(2024, 9, 1), date(2024, 9, 30))
|
|
|
|
assert isinstance(homeworks, list)
|
|
assert len(homeworks) == 1
|
|
homework = homeworks[0]
|
|
assert isinstance(homework, Homework)
|
|
assert homework.id == "hw-101"
|
|
assert homework.subject == "Maths"
|
|
assert homework.teachers == ()
|
|
assert homework.assigned_on is None
|
|
assert homework.due_on == date(2024, 9, 15)
|
|
assert homework.text == "Do your homework"
|
|
assert homework.html == "Do your homework"
|
|
|
|
|
|
def test_get_lessons_propagates_error(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_lessons propage les exceptions API.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
mock_client = mocker.MagicMock()
|
|
mock_client.lessons.side_effect = pronotepy.PronoteAPIError("API error")
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
|
|
with pytest.raises(pronotepy.PronoteAPIError):
|
|
client.get_lessons(date(2024, 9, 1), date(2024, 9, 30))
|
|
|
|
|
|
def test_get_homeworks_propagates_error(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_homeworks propage les exceptions API.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
mock_client = mocker.MagicMock()
|
|
mock_client.homework.side_effect = pronotepy.PronoteAPIError("API error")
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
|
|
with pytest.raises(pronotepy.PronoteAPIError):
|
|
client.get_homeworks(date(2024, 9, 1), date(2024, 9, 30))
|
|
|
|
|
|
def test_missing_credentials_raises(empty_pronote_settings: PronoteSettings) -> None:
|
|
"""Vérifie que les appels échouent avec ValueError si les identifiants sont manquants.
|
|
|
|
:param empty_pronote_settings: Paramètres Pronote avec tous les champs à None.
|
|
:return: None
|
|
"""
|
|
client = PronoteClient(empty_pronote_settings)
|
|
|
|
with pytest.raises(
|
|
ValueError, match="pronote_url, username et password sont requis pour pronotepy"
|
|
):
|
|
client._connect()
|
|
|
|
|
|
def test_connect_with_ent_resolution(mocker: pytest_mock.MockerFixture) -> None:
|
|
"""Vérifie que _resolve_ent retourne le callable attendu pour un ENT connu.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:return: None
|
|
"""
|
|
from pronote_sync.sources.pronote.client import _resolve_ent
|
|
|
|
resolver = _resolve_ent("bordeaux")
|
|
assert resolver is not None
|
|
|
|
|
|
def test_connect_with_unknown_ent_raises(mocker: pytest_mock.MockerFixture) -> None:
|
|
"""Vérifie que _resolve_ent lève ValueError pour un ENT inconnu.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:return: None
|
|
"""
|
|
from pronote_sync.sources.pronote.client import _resolve_ent
|
|
|
|
with pytest.raises(ValueError) as exc_info:
|
|
_resolve_ent("inconnu")
|
|
assert "ENT inconnu : 'inconnu'" in str(exc_info.value)
|
|
assert "ENT supportés :" in str(exc_info.value)
|
|
|
|
|
|
def test_connect_parent_account_type(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que account_type='parent' utilise pronotepy.ParentClient.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
from unittest.mock import Mock
|
|
|
|
from pronote_sync.sources.pronote.client import PronoteClient
|
|
|
|
mock_client = mocker.MagicMock()
|
|
mock_client_class = Mock(return_value=mock_client)
|
|
mocker.patch("pronotepy.ParentClient", new=mock_client_class)
|
|
mocker.patch("pronotepy.Client")
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
_ = client._connect()
|
|
|
|
# Verify ParentClient was used
|
|
assert mock_client_class.call_count == 1
|
|
pronotepy.Client.assert_not_called() # type: ignore[attr-defined]
|
|
|
|
|
|
def test_connect_without_ent_but_with_required_credentials(
|
|
mocker: pytest_mock.MockerFixture,
|
|
) -> None:
|
|
"""Vérifie que _connect() fonctionne sans ent mais avec les autres identifiants requis.
|
|
|
|
Ce test valide que PRONOTE_ENT est optionnel pour une connexion directe Pronote.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:return: None
|
|
"""
|
|
from unittest.mock import Mock
|
|
|
|
from pronote_sync.config.settings import PronoteSettings
|
|
from pronote_sync.sources.pronote.client import PronoteClient
|
|
|
|
# Settings sans ent mais avec les autres champs requis
|
|
settings = PronoteSettings(
|
|
pronote_url="https://pronote.example.com",
|
|
username="testuser",
|
|
password=SecretStr("testpass"),
|
|
ent=None, # Explicitement None
|
|
account_type="parent",
|
|
)
|
|
|
|
mock_client = mocker.MagicMock()
|
|
mock_client_class = Mock(return_value=mock_client)
|
|
mocker.patch("pronotepy.ParentClient", new=mock_client_class)
|
|
mocker.patch("pronotepy.Client")
|
|
|
|
client = PronoteClient(settings)
|
|
connected_client = client._connect()
|
|
|
|
# Should not raise ValueError about missing ent
|
|
assert connected_client is mock_client
|
|
|
|
# Verify ParentClient was called with ent=None
|
|
mock_client_class.assert_called_once_with(
|
|
pronote_url="https://pronote.example.com",
|
|
username="testuser",
|
|
password="testpass", # pragma: allowlist secret
|
|
ent=None, # ent should be None, not resolved
|
|
)
|
|
|
|
|
|
def test_connect_missing_required_credentials_still_raises(
|
|
mocker: pytest_mock.MockerFixture,
|
|
) -> None:
|
|
"""Vérifie que _connect() lève ValueError si pronote_url, username ou password manquent.
|
|
|
|
Ce test valide que l'erreur ne mentionne plus ent comme requis.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:return: None
|
|
"""
|
|
from pronote_sync.config.settings import PronoteSettings
|
|
from pronote_sync.sources.pronote.client import PronoteClient
|
|
|
|
# Settings avec ent mais sans pronote_url
|
|
settings = PronoteSettings(
|
|
pronote_url=None,
|
|
username="testuser",
|
|
password=SecretStr("testpass"),
|
|
ent=None,
|
|
account_type="parent",
|
|
)
|
|
|
|
client = PronoteClient(settings)
|
|
|
|
with pytest.raises(ValueError) as exc_info:
|
|
client._connect()
|
|
|
|
# Error should NOT mention ent as required
|
|
assert "pronote_url, username et password sont requis" in str(exc_info.value)
|
|
assert "ent" not in str(exc_info.value)
|
|
|
|
|
|
def test_connect_missing_username_raises(mocker: pytest_mock.MockerFixture) -> None:
|
|
"""Vérifie que _connect() lève ValueError si username manque.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:return: None
|
|
"""
|
|
from pronote_sync.config.settings import PronoteSettings
|
|
from pronote_sync.sources.pronote.client import PronoteClient
|
|
|
|
settings = PronoteSettings(
|
|
pronote_url="https://pronote.example.com",
|
|
username=None,
|
|
password=SecretStr("testpass"),
|
|
ent=None,
|
|
account_type="parent",
|
|
)
|
|
|
|
client = PronoteClient(settings)
|
|
|
|
with pytest.raises(ValueError) as exc_info:
|
|
client._connect()
|
|
|
|
assert "pronote_url, username et password sont requis" in str(exc_info.value)
|
|
|
|
|
|
def test_connect_missing_password_raises(mocker: pytest_mock.MockerFixture) -> None:
|
|
"""Vérifie que _connect() lève ValueError si password manque.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:return: None
|
|
"""
|
|
from pronote_sync.config.settings import PronoteSettings
|
|
from pronote_sync.sources.pronote.client import PronoteClient
|
|
|
|
settings = PronoteSettings(
|
|
pronote_url="https://pronote.example.com",
|
|
username="testuser",
|
|
password=None,
|
|
ent=None,
|
|
account_type="parent",
|
|
)
|
|
|
|
client = PronoteClient(settings)
|
|
|
|
with pytest.raises(ValueError) as exc_info:
|
|
client._connect()
|
|
|
|
assert "pronote_url, username et password sont requis" in str(exc_info.value)
|
|
|
|
|
|
def test_connect_student_account_type(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que account_type='student' utilise pronotepy.Client.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
from unittest.mock import Mock
|
|
|
|
from pronote_sync.sources.pronote.client import PronoteClient
|
|
|
|
pronote_settings_student = PronoteSettings(
|
|
pronote_url="https://pronote.example.com",
|
|
username="testuser",
|
|
password=SecretStr("testpass"),
|
|
ent="bordeaux",
|
|
account_type="student",
|
|
)
|
|
mock_client = mocker.MagicMock()
|
|
mock_client_class = Mock(return_value=mock_client)
|
|
mocker.patch("pronotepy.Client", new=mock_client_class)
|
|
mocker.patch("pronotepy.ParentClient")
|
|
|
|
client = PronoteClient(pronote_settings_student)
|
|
_ = client._connect()
|
|
|
|
# Verify Client was used
|
|
assert mock_client_class.call_count == 1
|
|
pronotepy.ParentClient.assert_not_called() # type: ignore[attr-defined]
|
|
|
|
|
|
def test_connect_with_ent_resolution_still_works(
|
|
mocker: pytest_mock.MockerFixture,
|
|
) -> None:
|
|
"""Vérifie que _resolve_ent est appelé et fonctionne quand ent est fourni.
|
|
|
|
Ce test valide que lorsque ent est fourni, il est toujours résolu via _resolve_ent.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:return: None
|
|
"""
|
|
from unittest.mock import Mock
|
|
|
|
from pronote_sync.config.settings import PronoteSettings
|
|
from pronote_sync.sources.pronote.client import PronoteClient
|
|
|
|
settings = PronoteSettings(
|
|
pronote_url="https://pronote.example.com",
|
|
username="testuser",
|
|
password=SecretStr("testpass"),
|
|
ent="bordeaux", # ent est fourni
|
|
account_type="parent",
|
|
)
|
|
|
|
mock_client = mocker.MagicMock()
|
|
mock_client_class = Mock(return_value=mock_client)
|
|
mocker.patch("pronotepy.ParentClient", new=mock_client_class)
|
|
|
|
# Mock _resolve_ent to return a mock resolver
|
|
mock_resolver = Mock()
|
|
mocker.patch(
|
|
"pronote_sync.sources.pronote.client._resolve_ent",
|
|
return_value=mock_resolver,
|
|
)
|
|
|
|
client = PronoteClient(settings)
|
|
_ = client._connect()
|
|
|
|
# _resolve_ent should have been called
|
|
from pronote_sync.sources.pronote.client import _resolve_ent as resolve_ent_func
|
|
|
|
resolve_ent_func.assert_called_once_with("bordeaux") # type: ignore[attr-defined]
|
|
|
|
# ParentClient should have been called with the resolved ent
|
|
mock_client_class.assert_called_once_with(
|
|
pronote_url="https://pronote.example.com",
|
|
username="testuser",
|
|
password="testpass", # pragma: allowlist secret
|
|
ent=mock_resolver,
|
|
)
|
|
|
|
|
|
def test_get_messages_degraded_on_error(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_messages retourne une liste vide en cas d'erreur réseau.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
mock_client = mocker.MagicMock()
|
|
mock_client.discussions.side_effect = ConnectionError("Network error")
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
messages = client.get_messages()
|
|
|
|
assert messages == []
|
|
|
|
|
|
def test_get_informations_degraded_on_error(
|
|
mocker: pytest_mock.MockerFixture, pronote_settings: PronoteSettings
|
|
) -> None:
|
|
"""Vérifie que get_informations retourne une liste vide en cas d'erreur réseau.
|
|
|
|
:param mocker: Fixture pytest-mock pour le mocking.
|
|
:param pronote_settings: Paramètres Pronote valides.
|
|
:return: None
|
|
"""
|
|
mock_client = mocker.MagicMock()
|
|
mock_client.information_and_surveys.side_effect = TimeoutError("Timeout")
|
|
mocker.patch.object(PronoteClient, "_connect", return_value=mock_client)
|
|
|
|
client = PronoteClient(pronote_settings)
|
|
messages = client.get_informations()
|
|
|
|
assert messages == []
|
|
|
|
|
|
# Ensure trailing newline
|