SPB Git

spb/forma-ka Public

Python 65.1% TypeScript 17.9% CSS 16.4% HTML 0.5%
3.5 KB · 96 lines python
Raw Blame History
1# -----------------------------------------------------------------------------2# Forma-Ka — Agrégateur de formations (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# tests/test_normalize.py : couche de normalisation commune5# -----------------------------------------------------------------------------6from formaka.normalize import (7    extract_details,8    normalize_language,9    normalize_mode,10    normalize_type,11    parse_date_fr,12    parse_duration_hours,13    parse_price,14)15from formaka.schema import Formation161718def test_parse_price():19    assert parse_price("1 295,00 $ + tx") == 1295.020    assert parse_price("795 $") == 795.021    assert parse_price("$1,250.00") == 1250.022    assert parse_price("Gratuit") == 0.023    assert parse_price("Sans frais") == 0.024    assert parse_price("") is None25    assert parse_price("Sur demande") is None262728def test_parse_duration_hours():29    assert parse_duration_hours("2 jours") == 14.030    assert parse_duration_hours("45 heures") == 45.031    assert parse_duration_hours("3,5 h") == 3.532    assert parse_duration_hours("90 minutes") == 1.533    assert parse_duration_hours("demi-journée") == 3.534    assert parse_duration_hours("") is None353637def test_normalize_mode():38    assert normalize_mode("Classe virtuelle") == "en ligne"39    assert normalize_mode("À distance") == "en ligne"40    assert normalize_mode("En salle") == "présentiel"41    assert normalize_mode("Comodal") == "hybride"42    assert normalize_mode("À votre rythme") == "asynchrone"434445def test_normalize_type():46    assert normalize_type("Séminaire de 2 jours") == "Séminaire"47    assert normalize_type("Cours de 1er cycle") == "Cours universitaire"48    assert normalize_type("AEC en bureautique") == "Cours collégial"49    assert normalize_type("Webinaire gratuit") == "Webinaire"50    assert normalize_type("Formation continue") == "Formation continue"515253def test_normalize_language():54    assert normalize_language("Français") == "fr"55    assert normalize_language("English") == "en"56    assert normalize_language("FR et EN") == "fr/en"575859def test_parse_date_fr():60    assert parse_date_fr("Débute le 14 octobre 2026") == "2026-10-14"61    assert parse_date_fr("1er décembre 2026") == "2026-12-01"62    assert parse_date_fr("2026-09-08") == "2026-09-08"63    assert parse_date_fr("14/10/2026") == "2026-10-14"64    assert parse_date_fr("aucune date") is None656667def test_extract_details():68    d = extract_details("Ce cours de 3 crédits (1,4 UEC), niveau débutant, 45 heures")69    assert d["credits"] == 3.070    assert d["uec"] == 1.471    assert d["level"] == "débutant"72    assert d["duration_hours"] == 45.0737475def test_finalize_prix_optionnel():76    """Un cours universitaire sans prix est parfaitement valide."""77    f = Formation(source="t", external_id="1", url="u", title=" Cours X ",78                  description="Cours de 3 crédits offert à distance.").finalize()79    assert f.price is None80    assert f.is_free is None81    assert f.credits == "3 crédits"82    assert f.title == "Cours X"838485def test_finalize_complet():86    f = Formation(source="t", external_id="2", url="u", title="Atelier",87                  training_type="atelier", duration="2 jours",88                  price_label="À partir de 795 $",89                  schedule_label="Prochaine séance : 14 octobre 2026").finalize()90    assert f.training_type == "Atelier"91    assert f.price == 795.092    assert f.is_free is False93    assert f.duration_hours == 14.094    assert f.start_date == "2026-10-14"95    assert f.details.get("price_from") is True96