"""Teste US-011 (PRD 5.20): indicator mediu RAR in statusbar + toggle conditionat. Rute testate: GET /_fragments/status -- indicator mediu (eticheta statica sau toggle) POST /_fragments/status/toggle-env -- comuta rar_env_default intre mediile disponibile Teste: test_afiseaza_env_default -- un mediu disponibil -> eticheta statica, fara toggle test_toggle_doar_la_doua_medii -- doua medii -> toggle prezent; un mediu -> toggle absent test_toggle_schimba_default -- POST toggle -> rar_env_default schimbat in DB, 200 """ from __future__ import annotations import os import re import tempfile import pytest from cryptography.fernet import Fernet # --------------------------------------------------------------------------- # Fixture # --------------------------------------------------------------------------- @pytest.fixture() def client(monkeypatch): """Client izolat cu DB temporara + cheie Fernet pentru criptare creds.""" tmp = tempfile.mkdtemp() monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t_statusbar.db")) monkeypatch.setenv("AUTOPASS_CREDS_KEY", Fernet.generate_key().decode()) from app.config import get_settings from app import crypto get_settings.cache_clear() crypto.reset_cache() from app.main import app with __import__("starlette.testclient", fromlist=["TestClient"]).TestClient( app, follow_redirects=False ) as c: yield c get_settings.cache_clear() crypto.reset_cache() # --------------------------------------------------------------------------- # Helpere # --------------------------------------------------------------------------- def _create_account_user( name: str = "Service Env SRL", email: str = "env@test.com", password: str = "parolasecreta10", ): """Creeaza cont + user. Returneaza (acct_id, user_id).""" from app.accounts import create_account from app.users import create_user from app.db import get_connection conn = get_connection() try: acct_id = create_account(conn, name, active=True) user_id = create_user(conn, acct_id, email, password) return acct_id, user_id finally: conn.close() def _login(client, email: str, password: str) -> None: """Face login real prin HTTP si seteaza cookie-ul de sesiune pe client.""" resp = client.get("/login") assert resp.status_code == 200 m = re.search(r'name="csrf_token"\s+value="([^"]+)"', resp.text) if not m: m = re.search(r'value="([^"]+)"\s+name="csrf_token"', resp.text) assert m, "csrf_token negasit pe /login" csrf = m.group(1) resp = client.post("/login", data={ "email": email, "parola": password, "csrf_token": csrf, }) assert resp.status_code == 303, f"Login esuat: {resp.status_code} {resp.text[:200]}" def _seteaza_mediu_disponibil(acct_id: int, env: str) -> None: """Scrie direct in DB: activeaza mediul `env` cu creds criptate mock. Alternativa rapida la POST /cont/rar-medii cu monkeypatch (nu necesita HTTP). Reutilizeaza cheia Fernet curenta (setata in fixture). """ from app.db import get_connection from app.crypto import encrypt_creds enc = encrypt_creds({"email": f"rar_{env}@firma.ro", "password": f"parola_{env}"}) conn = get_connection() try: if env == "test": conn.execute( "UPDATE accounts SET rar_test_enabled=1, rar_creds_test_enc=? WHERE id=?", (enc, acct_id), ) elif env == "prod": conn.execute( "UPDATE accounts SET rar_prod_enabled=1, rar_creds_prod_enc=? WHERE id=?", (enc, acct_id), ) conn.commit() finally: conn.close() def _get_csrf_din_status(client) -> str: """Obtine CSRF token din fragmentul /_fragments/status.""" resp = client.get("/_fragments/status") assert resp.status_code == 200, f"/_fragments/status a returnat {resp.status_code}" m = re.search(r'name="csrf_token"\s+value="([^"]+)"', resp.text) if not m: m = re.search(r'value="([^"]+)"\s+name="csrf_token"', resp.text) assert m, f"csrf_token negasit in statusbar: {resp.text[:600]}" return m.group(1) # --------------------------------------------------------------------------- # Teste # --------------------------------------------------------------------------- def test_afiseaza_env_default(client): """Cont cu UN singur mediu disponibil (prod) -> statusbar contine eticheta 'Productie', fara niciun control de toggle/comutare. """ acct_id, _ = _create_account_user("Firma Env1", "env1@test.com") _seteaza_mediu_disponibil(acct_id, "prod") _login(client, "env1@test.com", "parolasecreta10") resp = client.get("/_fragments/status") assert resp.status_code == 200, f"Status HTTP neasteptat: {resp.status_code}" html = resp.text # Eticheta mediului trebuie prezenta assert "Productie" in html, f"Eticheta 'Productie' absenta in statusbar: {html[:600]}" # Nu trebuie sa existe un control de comutare (toggle) la un singur mediu assert "toggle-env" not in html, \ "Control toggle gresit prezent la un singur mediu disponibil" def test_toggle_doar_la_doua_medii(client): """Cont cu DOUA medii disponibile -> statusbar contine controlul de toggle. Cont cu UN singur mediu -> NU contine toggle. """ # Cont cu doua medii acct2_id, _ = _create_account_user("Firma Env2", "env2@test.com") _seteaza_mediu_disponibil(acct2_id, "test") _seteaza_mediu_disponibil(acct2_id, "prod") _login(client, "env2@test.com", "parolasecreta10") resp2 = client.get("/_fragments/status") assert resp2.status_code == 200 html2 = resp2.text assert "toggle-env" in html2, \ f"Control toggle absent cand sunt doua medii disponibile: {html2[:600]}" # Cont cu un singur mediu (test) acct1_id, _ = _create_account_user("Firma Env1B", "env1b@test.com") _seteaza_mediu_disponibil(acct1_id, "test") # Relogin pe alt cont (simulam logout/login rapid prin schimbare sesiune) _login(client, "env1b@test.com", "parolasecreta10") resp1 = client.get("/_fragments/status") assert resp1.status_code == 200 html1 = resp1.text assert "toggle-env" not in html1, \ f"Control toggle gresit prezent la un singur mediu: {html1[:600]}" assert "Testare" in html1, \ f"Eticheta 'Testare' absenta cand mediul unic e 'test': {html1[:600]}" def test_toggle_schimba_default(client): """POST la /_fragments/status/toggle-env comuta rar_env_default in DB si intoarce statusbar-ul actualizat (200). """ acct_id, _ = _create_account_user("Firma Toggle", "toggle@test.com") _seteaza_mediu_disponibil(acct_id, "test") _seteaza_mediu_disponibil(acct_id, "prod") _login(client, "toggle@test.com", "parolasecreta10") # Verifica valoarea initiala in DB (default=prod) from app.db import get_connection conn = get_connection() try: row_inainte = conn.execute( "SELECT rar_env_default FROM accounts WHERE id=?", (acct_id,) ).fetchone() finally: conn.close() env_inainte = row_inainte["rar_env_default"] or "prod" # Obtine CSRF si face toggle csrf = _get_csrf_din_status(client) resp = client.post("/_fragments/status/toggle-env", data={"csrf_token": csrf}) assert resp.status_code == 200, \ f"Toggle a returnat {resp.status_code}: {resp.text[:300]}" # Verifica ca statusbar-ul actualizat e in raspuns html = resp.text assert "status-bar" in html, \ f"Raspunsul toggle nu contine statusbar: {html[:400]}" # Verifica schimbarea in DB conn = get_connection() try: row_dupa = conn.execute( "SELECT rar_env_default FROM accounts WHERE id=?", (acct_id,) ).fetchone() finally: conn.close() env_dupa = row_dupa["rar_env_default"] assert env_dupa != env_inainte, \ f"rar_env_default NU s-a schimbat: inainte={env_inainte!r}, dupa={env_dupa!r}" assert env_dupa in ("test", "prod"), \ f"rar_env_default are valoare invalida: {env_dupa!r}"