"""Fusion #69 — Alertes unifiées (chantier 2 + chantier 5, Kanbante). Kanbante n'a pas de table de notifications : sa source réelle est le journal d'événements, déjà exposé par GET /api/events (aucun nouvel endpoint). Kanbante ne porte aucun état lu/non lu : ses événements sont donc tous de l'historique et ne sont jamais comptés comme actifs par le panneau. Couverts ici : placeholder disparu, module servi, CORS limité à /api/events pour les seules origines soeurs. """ SOEUR = "https://flowdeck.dracodev.net" def test_barre_alertes_sans_placeholder_et_module_servi(client): r = client.get("/") assert r.status_code == 200 assert "Alertes unifiées : arrive avec la fédération" not in r.text assert "draco-alertes.js" in r.text assert "draco-alertes.css" in r.text js = client.get("/static/js/draco-alertes.js").text assert "DRACO_ALERTES" in js assert "api/events" in js def test_events_forme(client): r = client.get("/api/events") assert r.status_code == 200 body = r.json() assert body["ok"] is True assert isinstance(body["events"], list) def test_cors_events_soeur_preflight_get_et_tiers(client): r = client.options("/api/events", headers={"Origin": SOEUR, "Access-Control-Request-Method": "GET"}) assert r.status_code == 200 assert r.headers.get("access-control-allow-origin") == SOEUR assert r.headers.get("access-control-allow-credentials") == "true" r2 = client.get("/api/events", headers={"Origin": SOEUR}) assert r2.status_code == 200 assert r2.headers.get("access-control-allow-origin") == SOEUR r3 = client.options("/api/events", headers={"Origin": "https://evil.example", "Access-Control-Request-Method": "GET"}) assert "access-control-allow-origin" not in r3.headers # Correctif 2026-10-28 : une origine sœur dev passe aussi. r4 = client.options("/api/events", headers={"Origin": "https://tiktak-dev.dracodev.net", "Access-Control-Request-Method": "GET"}) assert r4.status_code == 200 assert r4.headers.get("access-control-allow-origin") == "https://tiktak-dev.dracodev.net" assert r4.headers.get("access-control-allow-credentials") == "true" def test_chantier5_onglet_console_spark_et_alertes_onglets(client): """Chantier 5 : onglet Console Spark en dernier dans la barre, et vue Alertes en onglets (module + styles vendangés depuis commons).""" r = client.get("/") assert r.status_code == 200 nav = r.text.split('