Steph680/ormuz
0
1# -*- coding: utf-8 -*-2"""Tests de l'enrichissement OSINT des incidents (sans réseau)."""3 4import asyncio5 6from app import db, osint_incidents as osint7 8 9def test_parse_date():10 assert osint.parse_date("1 March 2026") == "2026-03-01T00:00:00"11 assert osint.parse_date("29 May 2026").startswith("2026-05-29")12 assert osint.parse_date("bientôt") == ""13 14 15def test_geocode_local_annuaire():16 assert osint.geocode_local("Strait of Hormuz") == (26.57, 56.50)17 assert osint.geocode_local("60 nautical miles off Muscat, Oman")[0] == 23.5918 assert osint.geocode_local("Gulf of Oman") == (24.80, 58.20)19 assert osint.geocode_local("Sri Lanka") is None # hors annuaire régional20 21 22def test_parse_tables_gere_rowspan():23 # Tableau minimal avec un rowspan sur la date (2 navires, même jour).24 html = """25 <table class="wikitable">26 <tr><th>Name</th><th>Flag state</th><th>Ship type</th><th>Date</th>27 <th>Location attacked</th><th>Casualties</th><th>Details</th><th>Ref.</th></tr>28 <tr><td>Alpha</td><td>Panama</td><td>Tanker</td><td rowspan="2">1 March 2026</td>29 <td>Strait of Hormuz</td><td>None</td><td>Struck by drone</td><td>[1]</td></tr>30 <tr><td>Bravo</td><td>Liberia</td><td>Tanker</td>31 <td>Gulf of Oman</td><td>2 dead</td><td>Mine blast</td><td>[2]</td></tr>32 </table>"""33 lignes = osint.parse_tables(html)34 assert len(lignes) == 235 # pandas propage la date sur les deux lignes malgré le rowspan.36 assert lignes[0]["date"].startswith("1 March") and lignes[1]["date"].startswith("1 March")37 assert lignes[1]["navire"] == "Bravo" and lignes[1]["lieu"] == "Gulf of Oman"38 39 40def test_versement_dans_evenements(tmp_path, monkeypatch):41 monkeypatch.setenv("DB_PATH", str(tmp_path / "t.db"))42 incidents = [{43 "url": "https://en.wikipedia.org/wiki/x#alpha-2026-03-01",44 "lat": 26.57, "lon": 56.5, "source": "OSINT", "type": "Attack",45 "place": "Strait of Hormuz", "published_at": "2026-03-01T00:00:00",46 "title": "Alpha — struck by drone"}]47 48 async def scenario():49 await db.init_db()50 assert await osint.store_events(incidents) == 151 assert await osint.store_events(incidents) == 0 # idempotent (url PK)52 async with db.connect() as conn:53 cur = await conn.execute(54 "SELECT source, category, relevance, title, title_en, lang"55 " FROM news_events WHERE url = ?", (incidents[0]["url"],))56 row = await cur.fetchone()57 assert row[0] == "OSINT" and row[1] == "incident_securite"58 assert row[2] == osint.OSINT_RELEVANCE and row[3].startswith("Alpha")59 assert row[4] == row[3] and row[5] == "en" # titre EN d'origine60 61 asyncio.run(scenario())62 63 64def test_build_incidents_filtre_et_geocode():65 lignes = [66 {"navire": "Alpha", "pavillon": "Panama", "type": "Tanker",67 "date": "1 March 2026", "lieu": "Strait of Hormuz", "pertes": "None",68 "details": "Struck by drone"},69 {"navire": "Ghost", "pavillon": "", "type": "", "date": "2 March 2026",70 "lieu": "nan", "pertes": "", "details": ""}, # lieu vide : écarté71 {"navire": "Far", "pavillon": "", "type": "", "date": "3 March 2026",72 "lieu": "Sri Lanka", "pertes": "", "details": ""}, # hors zone : pas géocodé local73 ]74 75 async def scenario():76 # Nominatim ne doit pas être appelé pour « nan » ; on le neutralise.77 async def pas_de_nominatim(client, loc):78 return None79 import app.osint_incidents as m80 m.geocode_nominatim = pas_de_nominatim81 inc = await m.build_incidents(None, lignes)82 assert len(inc) == 183 a = inc[0]84 assert a["source"] == "OSINT" and a["type"] == "Attack"85 assert a["lat"] == 26.57 and a["place"] == "Strait of Hormuz"86 assert a["title"].startswith("Alpha —")87 assert a["url"].endswith("#alpha-2026-03-01")88 89 asyncio.run(scenario())90 