Fusion #69 : Alertes unifiees (tests/test_draco_alertes.py)
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
"""Fusion #69 — Alertes unifiées (chantier 2, Flowdeck).
|
||||||
|
|
||||||
|
Source réelle de Flowdeck : GET /api/notifications (non lues =
|
||||||
|
actives, `url` relative pour le lien profond), déjà exposée et
|
||||||
|
inchangée ici. Couverts : placeholder Alertes disparu, module servi,
|
||||||
|
CSP connect-src avec les origines soeurs, CORS (origines soeurs
|
||||||
|
ajoutées à allow_origins ; tiers sans en-tête).
|
||||||
|
"""
|
||||||
|
|
||||||
|
SOEURS = ("https://og.dracodev.net", "https://flowdeck.dracodev.net",
|
||||||
|
"https://tiktak.dracodev.net", "https://kanbante.dracodev.net")
|
||||||
|
|
||||||
|
|
||||||
|
def test_barre_alertes_sans_placeholder_et_module_servi(client):
|
||||||
|
# Les pages applicatives authentifiées ne sont pas atteignables
|
||||||
|
# telles quelles dans la sandbox (l'écran de connexion est servi
|
||||||
|
# pour "/" comme pour "/dashboard") : on vérifie donc le gabarit
|
||||||
|
# livré lui-même, plus les fichiers statiques servis.
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
gabarit = Path("app/templates/_draco_bar.html").read_text()
|
||||||
|
assert "Alertes unifiées : arrive avec la fédération" not in gabarit
|
||||||
|
assert "draco-alertes.js" in gabarit
|
||||||
|
assert "draco-alertes.css" in gabarit
|
||||||
|
assert "DRACO_ALERTES.open()" in gabarit
|
||||||
|
js = client.get("/static/js/draco-alertes.js")
|
||||||
|
assert js.status_code == 200
|
||||||
|
assert "DRACO_ALERTES" in js.text
|
||||||
|
assert "api/notifications" in js.text
|
||||||
|
css = client.get("/static/css/draco-alertes.css")
|
||||||
|
assert css.status_code == 200
|
||||||
|
assert "draco-alertes-overlay" in css.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_csp_connect_src_contient_les_soeurs(client):
|
||||||
|
# La CSP est posée sur toute réponse HTML, y compris l'écran de
|
||||||
|
# connexion servi ici : elle prouve les origines soeurs en
|
||||||
|
# connect-src pour les pages de l'hôte.
|
||||||
|
r = client.get("/")
|
||||||
|
csp = r.headers.get("content-security-policy", "")
|
||||||
|
assert "connect-src" in csp
|
||||||
|
for origine in SOEURS:
|
||||||
|
assert origine in csp, csp
|
||||||
|
|
||||||
|
|
||||||
|
def test_notifications_api_et_cors_soeur(client):
|
||||||
|
r = client.get("/api/notifications")
|
||||||
|
assert r.status_code == 200
|
||||||
|
body = r.json()
|
||||||
|
assert isinstance(body["notifications"], list)
|
||||||
|
assert "unread" in body
|
||||||
|
r2 = client.options("/api/notifications",
|
||||||
|
headers={"Origin": "https://tiktak.dracodev.net",
|
||||||
|
"Access-Control-Request-Method": "GET"})
|
||||||
|
assert r2.headers.get("access-control-allow-origin") == "https://tiktak.dracodev.net"
|
||||||
|
assert r2.headers.get("access-control-allow-credentials") == "true"
|
||||||
|
r3 = client.get("/api/notifications",
|
||||||
|
headers={"Origin": "https://tiktak.dracodev.net"})
|
||||||
|
assert r3.headers.get("access-control-allow-origin") == "https://tiktak.dracodev.net"
|
||||||
|
r4 = client.options("/api/notifications",
|
||||||
|
headers={"Origin": "https://evil.example",
|
||||||
|
"Access-Control-Request-Method": "GET"})
|
||||||
|
assert "access-control-allow-origin" not in r4.headers
|
||||||
Reference in New Issue
Block a user