125 lines
4.6 KiB
Python
125 lines
4.6 KiB
Python
"""Tests de la recherche fédérée Kanbante (fusion #68).
|
|
|
|
Fonctions pures de app/recherche.py uniquement : aucune base, aucun
|
|
serveur, aucune forge.
|
|
"""
|
|
|
|
from app.recherche import (
|
|
cors_headers_for,
|
|
groupes_vers_json,
|
|
is_dev_host,
|
|
origin_of,
|
|
preflight_headers,
|
|
sister_origins,
|
|
)
|
|
|
|
RESOLVED_DEV = {
|
|
"obsigate": "https://og-dev.dracodev.net/",
|
|
"flowdeck": "https://flowdeck-dev.dracodev.net",
|
|
"tiktak": "https://tiktak-dev.dracodev.net/",
|
|
"kanbante": "https://kanbante-dev.dracodev.net/",
|
|
}
|
|
|
|
|
|
def test_is_dev_host():
|
|
assert is_dev_host("kanbante-dev.dracodev.net") is True
|
|
assert is_dev_host("kanbante.dracodev.net") is False
|
|
assert is_dev_host("x-dev.dracodev.net.evil") is False
|
|
assert is_dev_host(None) is False
|
|
|
|
|
|
def test_origin_of():
|
|
assert origin_of("https://og-dev.dracodev.net/") == "https://og-dev.dracodev.net"
|
|
assert origin_of("{{URL_OBSIGATE}}") is None
|
|
|
|
|
|
def test_sister_origins_dev():
|
|
# Correctif 2026-10-28 : 10 origines officielles (8 sœurs + 2 agent), prod ET dev,
|
|
# quelle que soit la résolution.
|
|
assert sister_origins(RESOLVED_DEV) == {
|
|
"https://og.dracodev.net",
|
|
"https://flowdeck.dracodev.net",
|
|
"https://tiktak.dracodev.net",
|
|
"https://kanbante.dracodev.net",
|
|
"https://og-dev.dracodev.net",
|
|
"https://flowdeck-dev.dracodev.net",
|
|
"https://tiktak-dev.dracodev.net",
|
|
"https://kanbante-dev.dracodev.net",
|
|
"https://agent.dracodev.net",
|
|
"https://agent-dev.dracodev.net",
|
|
}
|
|
|
|
|
|
|
|
def test_cors_headers_agent_console_autorise():
|
|
# Fédération depuis la console (2026-10-28) : les origines agent
|
|
# prod ET dev passent, avec credentials ; un tiers reste refusé.
|
|
for origine in ("https://agent.dracodev.net",
|
|
"https://agent-dev.dracodev.net"):
|
|
headers = cors_headers_for(origine, RESOLVED_DEV)
|
|
assert headers is not None
|
|
assert headers["Access-Control-Allow-Origin"] == origine
|
|
assert headers["Access-Control-Allow-Credentials"] == "true"
|
|
assert cors_headers_for("https://agent.dracodev.net.evil.example",
|
|
RESOLVED_DEV) is None
|
|
|
|
def test_cors_headers():
|
|
headers = cors_headers_for("https://tiktak-dev.dracodev.net", RESOLVED_DEV)
|
|
assert headers["Access-Control-Allow-Origin"] == "https://tiktak-dev.dracodev.net"
|
|
assert headers["Access-Control-Allow-Credentials"] == "true"
|
|
assert cors_headers_for("https://evil.example", RESOLVED_DEV) is None
|
|
assert cors_headers_for("https://og-dev.dracodev.net.evil.example",
|
|
RESOLVED_DEV) is None
|
|
# Autre environnement autorisé (correctif 2026-10-28).
|
|
assert cors_headers_for("https://og.dracodev.net",
|
|
RESOLVED_DEV) is not None
|
|
|
|
|
|
def test_preflight_headers():
|
|
headers = preflight_headers("https://og-dev.dracodev.net", RESOLVED_DEV)
|
|
assert headers["Access-Control-Allow-Methods"] == "GET, OPTIONS"
|
|
assert preflight_headers("https://evil.example", RESOLVED_DEV) is None
|
|
|
|
|
|
def test_groupes_vers_json_tronque_et_filtre():
|
|
groups = [{
|
|
"full_name": "Projets/site",
|
|
"rows": [
|
|
{"issue": {"number": 12, "title": "Bug", "state": "open",
|
|
"body": "x" * 500, "labels": [{"name": "bug", "color": "ff0000"}],
|
|
"token_secret": "ne-doit-pas-sortir"},
|
|
"column": "in_progress"},
|
|
{"issue": {"number": 13, "title": "Autre", "state": "closed",
|
|
"body": "", "labels": []},
|
|
"column": "done"},
|
|
],
|
|
}]
|
|
data, total = groupes_vers_json(groups, limit=1)
|
|
assert total == 1
|
|
assert len(data[0]["rows"]) == 1
|
|
row = data[0]["rows"][0]
|
|
assert row["issue"]["number"] == 12
|
|
assert len(row["issue"]["body"]) == 160
|
|
assert "token_secret" not in row["issue"]
|
|
assert row["issue"]["labels"] == [{"name": "bug", "color": "ff0000"}]
|
|
assert row["column"] == "in_progress"
|
|
|
|
|
|
def test_groupes_vers_json_vide():
|
|
assert groupes_vers_json([], limit=20) == ([], 0)
|
|
assert groupes_vers_json(None, limit=20) == ([], 0)
|
|
|
|
|
|
def test_sister_origins_hote_requete():
|
|
# Correctif 2026-10-28 : configuration muette, quel que soit
|
|
# l'hôte de la requête, prod ET dev passent.
|
|
assert "https://og-dev.dracodev.net" in sister_origins(
|
|
{}, request_host="kanbante-dev.dracodev.net"
|
|
)
|
|
assert "https://og.dracodev.net" in sister_origins(
|
|
{}, request_host="kanbante-dev.dracodev.net"
|
|
)
|
|
assert "https://og-dev.dracodev.net" in sister_origins(
|
|
{}, request_host="kanbante.dracodev.net"
|
|
)
|