SPB Git forge

spb/sorti-ka

Public

Toutes les sorties et tous les événements du Québec, un seul endroit — 7 connecteurs, fiches SSR, design Groupe KA.

58commits 1branches 0releases
13.7 MBsize
maindefault branch
17 days agolast push
HTML 82.9% Python 15.2% TypeScript 0.9% JavaScript 0.7%
5.7 KB · 133 lines python
Raw Blame History
1# ==============================================================================2# Author: Simon-Pierre Boucher <contact@spboucher.ai>3# File:   tests/test_normalize.py4# Desc:   Tests de la couche de normalisation (dates, prix, catégories, régions)5# ==============================================================================6from __future__ import annotations78from sortika.normalize import (artists_from_title, clean_city, clean_text,9                               map_categories, parse_date_iso, parse_latlng,10                               parse_price, parse_time, utc_to_local)11from sortika.regions import region_from_city, region_from_tourist12from sortika.schema import Event131415def test_parse_date_iso():16    assert parse_date_iso("2026-09-11T00:00:00") == "2026-09-11"17    assert parse_date_iso("2026-09-11") == "2026-09-11"18    assert parse_date_iso("") is None19    assert parse_date_iso("demain") is None20    assert parse_date_iso("0001-99-99") is None212223def test_parse_time():24    assert parse_time("17 août 2026, 20h00") == "20:00"25    assert parse_time("19h30") == "19:30"26    assert parse_time("15 h 00") == "15:00"27    assert parse_time("19:30:00") == "19:30"28    assert parse_time("2026-09-11T19:30:00") == "19:30"29    assert parse_time("17 août 2026") is None30    assert parse_time("") is None31    assert parse_time(None) is None323334def test_utc_to_local():35    # hiver (UTC-5) et été (UTC-4), vérifiés sur les flux Laval/Sherbrooke36    assert utc_to_local("2025-02-13T23:30:00") == ("2025-02-13", "18:30")37    assert utc_to_local("2026-08-01T22:30:00Z") == ("2026-08-01", "18:30")38    # minuit local = placeholder « toute la journée » → pas d'heure39    assert utc_to_local("2026-07-10T04:00:00Z") == ("2026-07-10", None)40    assert utc_to_local(None) == (None, None)414243def test_artists_from_title():44    # patron sûr : suffixe = salle connue de l'événement45    assert artists_from_title("Les Cowboys Fringants - Club Soda",46                              "Club Soda") == ["Les Cowboys Fringants"]47    # patron sûr : « X en concert / en spectacle »48    assert artists_from_title("Marc Dupré en spectacle", "") == ["Marc Dupré"]49    # ambigu ou événement → jamais d'artiste inventé50    assert artists_from_title("Festival d'été de Québec", "") == []51    assert artists_from_title("Soirée humour - Club Soda", "Club Soda") == []52    assert artists_from_title("Un artiste - Une autre salle", "Club Soda") == []53    assert artists_from_title("", "") == []545556def test_parse_price():57    assert parse_price("Gratuit") == (True, None, "Gratuit")58    assert parse_price("Entrée libre") == (True, None, "Entrée libre")59    free, amt, _ = parse_price("Adulte 25 $, enfant 12,50 $")60    assert free is False and amt == 12.5061    assert parse_price("Payant")[0] is False62    assert parse_price("")[0] is None636465def test_map_categories():66    assert map_categories(["Festival"]) == ["festival"]67    assert map_categories(["Manifestation sportive"]) == ["sport"]68    assert map_categories(["Chanson", "Sports et plein air"]) == ["musique", "sport"]69    assert map_categories(["Conseil et comité"]) == ["communautaire"]70    assert map_categories(["Zzz-inconnu"]) == ["autre"]71    assert map_categories([]) == ["autre"]727374def test_regions():75    assert region_from_tourist("Cantons-de-l'Est") == "Estrie"76    assert region_from_tourist("Charlevoix") == "Capitale-Nationale"77    assert region_from_tourist("Québec") == "Capitale-Nationale"78    assert region_from_city("Lévis") == "Chaudière-Appalaches"79    assert region_from_city("Gatineau") == "Outaouais"80    assert region_from_city("Ville-Inconnue") == ""818283def test_clean():84    assert clean_city("Montréal (Québec)") == "Montréal"85    assert clean_text("a  <b>b</b>&nbsp;c") == "a b c"868788def test_parse_latlng():89    assert parse_latlng("45.5", "-73.5") == (45.5, -73.5)90    assert parse_latlng("0", "0") == (None, None)91    assert parse_latlng(None, None) == (None, None)929394def test_event_finalize_and_dedup():95    a = Event(source="sitq", external_id="X1", url="https://a",96              title="  Festival d'été  ", city="Québec (Québec)",97              tourist_region="Québec", raw_categories=["Festival"],98              start_date="2026-07-01T00:00:00", price_label="Gratuit").finalize()99    b = Event(source="montreal", external_id="Y2", url="https://b",100              title="Festival d'été", city="Québec",101              start_date="2026-07-01").finalize()102    assert a.title == "Festival d'été"103    assert a.region == "Capitale-Nationale"104    assert a.categories == ["festival"]105    assert a.is_free is True106    assert a.end_date == "2026-07-01"107    assert a.dedup_key() == b.dedup_key()108109110def test_canonical_city_mamh():111    """Phase 2 : les graphies sans accents des sources sont ramenées au nom112    officiel du Répertoire MAMH (facettes ville unifiées)."""113    from sortika.normalize import canonical_city114    assert canonical_city("Montreal") == "Montréal"115    assert canonical_city("Quebec") == "Québec"116    assert canonical_city("Levis") == "Lévis"117    assert canonical_city("Trois-Rivieres") == "Trois-Rivières"118    assert canonical_city("MONTRÉAL") == "Montréal"119    assert canonical_city("Toronto") == "Toronto"    # hors répertoire : intact120    assert clean_city("Montreal, Québec") == "Montréal"121122123def test_normalize_status():124    from sortika.schema import normalize_status125    assert normalize_status("cancelled") == "cancelled"126    assert normalize_status("ANNULÉ") == "cancelled"127    assert normalize_status("sold_out") == "soldout"128    assert normalize_status("postponed") == "postponed"129    assert normalize_status("rescheduled") == "postponed"130    assert normalize_status("buy_now") == ""131    assert normalize_status("") == ""132    assert normalize_status(None) == ""133