"""Niezmiennik: KAŻDE wyjście HTTP w dół niesie token międzywarstwowy (LOG-32). Powód istnienia tego testu: token dodano do klienta na gałęzi, która odbiła się od mastera zanim powstały metody `prompt()` i `horoscope()`. Git zmergował obie zmiany czysto (różne linie), ale nowe metody wyszły BEZ tokenu — i dostawały 401 dopiero na produkcji. Zwykły test jednej metody by tego nie złapał, więc sprawdzamy regułę strukturalnie: nie ma wywołania bez `headers=`. """ import ast import pathlib CLIENT = pathlib.Path(__file__).resolve().parents[1] / "app" / "clients" / "logic_client.py" def _http_calls(path: pathlib.Path) -> list[tuple[str, int, bool]]: """(nazwa_metody_http, linia, czy_ma_headers) dla każdego client.post/get.""" tree = ast.parse(path.read_text(encoding="utf-8")) out = [] for node in ast.walk(tree): if not isinstance(node, ast.Call) or not isinstance(node.func, ast.Attribute): continue if node.func.attr not in ("post", "get", "put", "patch", "delete"): continue if not (isinstance(node.func.value, ast.Name) and node.func.value.id == "client"): continue has_headers = any(kw.arg == "headers" for kw in node.keywords) out.append((node.func.attr, node.lineno, has_headers)) return out def test_client_module_exists(): assert CLIENT.is_file() def test_every_outbound_call_sends_auth_header(): calls = _http_calls(CLIENT) assert calls, "nie znaleziono żadnego wywołania HTTP — test przestał cokolwiek pilnować" missing = [f"{CLIENT.name}:{line} client.{verb}()" for verb, line, ok in calls if not ok] assert not missing, ( "Wywołania w dół bez tokenu międzywarstwowego (dostaną 401 przy włączonej " "ochronie): " + ", ".join(missing) ) def test_auth_headers_helper_is_lazy(): """Token czytany przy wywołaniu, nie przy imporcie — inaczej pod wystartowałby z pustym tokenem, gdyby zmienna pojawiła się później.""" import os from app.clients.logic_client import _auth_headers old = os.environ.get("INTERNAL_TOKEN") try: os.environ["INTERNAL_TOKEN"] = "abc" assert _auth_headers() == {"X-Astrololo-Token": "abc"} os.environ.pop("INTERNAL_TOKEN") assert _auth_headers() == {} # ochrona wyłączona = brak nagłówka finally: if old is not None: os.environ["INTERNAL_TOKEN"] = old else: os.environ.pop("INTERNAL_TOKEN", None)