fix(config): refuser file:// et userinfo dans le contrat d'endpoint

Retire le schéma file du contrat ExternalEndpoint (CalDAV, Pronote iCal, Blog RSS) : seuls https et le loopback http CalDAV explicite restent acceptés. Rejette les URLs contenant userinfo. Ajoute hide_input_in_errors aux Settings. Réécrit les fixtures file:// en https mocké et ajoute une matrice de tests paramétrée du contrat.

Refs #63
This commit is contained in:
2026-09-13 15:30:00 +02:00
parent d1371cabbb
commit 177286b528
5 changed files with 329 additions and 61 deletions
+22 -23
View File
@@ -1,7 +1,7 @@
"""Tests unitaires pour le module iCal : téléchargement et parsing.
Ce module teste :
- La récupération du flux iCal (file://, HTTP)
- La récupération du flux iCal (HTTP)
- Le parsing des événements en modèles Lesson, SchoolEvent
- L'extraction et normalisation des devoirs
- La collecte et déduplication des devoirs par date cible
@@ -11,8 +11,6 @@ Les tests utilisent des mocks pour éviter tout appel réseau réel.
from __future__ import annotations
import tempfile
import urllib.parse
from datetime import date, datetime
from pathlib import Path
@@ -57,38 +55,39 @@ def invalid_ical_content() -> str:
return "INVALID:CONTENT\nThis is not a valid iCal file."
def test_fetch_ical_file_protocol() -> None:
"""fetch_ical("file://tests/fixtures/pronote-4e.ics") retourne un contenu commençant par BEGIN:VCALENDAR.
@responses.activate
def test_fetch_ical_fixture_content() -> None:
"""fetch_ical("https://…") sur un mock réseau retourne un contenu commençant par BEGIN:VCALENDAR.
:return: None
"""
fixture_path = Path(__file__).parent.parent / "fixtures" / "pronote-4e.ics"
url = f"file://{fixture_path}"
responses.add(
responses.GET,
"https://pronote.example.test/ical.ics",
body=fixture_path.read_text(encoding="utf-8"),
status=200,
)
content = fetch_ical(url)
content = fetch_ical("https://pronote.example.test/ical.ics")
assert content.lstrip().startswith("BEGIN:VCALENDAR")
def test_fetch_ical_file_uri_decoding() -> None:
"""fetch_ical("file://path%20with%20spaces") décode correctement le chemin.
@responses.activate
def test_fetch_ical_url_with_encoded_characters() -> None:
"""fetch_ical préserve les caractères encodés (%20) de l'URL interrogée.
:return: None
"""
# Créer un fichier temporaire avec un espace dans le nom
with tempfile.TemporaryDirectory() as tmpdir:
temp_path = Path(tmpdir) / "fichier avec espaces.ics"
temp_path.write_text(
"BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//Test//Test//FR\nEND:VCALENDAR",
encoding="utf-8",
)
responses.add(
responses.GET,
"https://pronote.example.test/fichier%20avec%20espaces.ics",
body="BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//Test//Test//FR\nEND:VCALENDAR",
status=200,
)
# URL encodée avec espace
encoded_name = urllib.parse.quote("fichier avec espaces.ics")
url = f"file://{tmpdir}/{encoded_name}"
# Cela devrait fonctionner car Path.read_text décode l'URL
content = fetch_ical(url)
assert content.lstrip().startswith("BEGIN:VCALENDAR")
content = fetch_ical("https://pronote.example.test/fichier%20avec%20espaces.ics")
assert content.lstrip().startswith("BEGIN:VCALENDAR")
@responses.activate