"""Teste US-001 (PRD 5.12): companie/email/CUI obligatorii la signup. TDD strict: testele se scriu INAINTE de implementare (RED), dupa implementare trec (GREEN). """ from __future__ import annotations import os import re import tempfile import pytest from starlette.testclient import TestClient @pytest.fixture() def client(monkeypatch): tmp = tempfile.mkdtemp() monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "test_signup_us001.db")) monkeypatch.setenv("AUTOPASS_SIGNUP_RATE_MAX", "100") from app.config import get_settings get_settings.cache_clear() from app.web import ratelimit ratelimit._hits.clear() from app.main import app with TestClient(app) as c: yield c get_settings.cache_clear() def _csrf(html: str) -> str: m = re.search(r'name="csrf_token"\s+value="([^"]+)"', html) if not m: m = re.search(r'value="([^"]+)"\s+name="csrf_token"', html) assert m, "csrf_token negasit in HTML" return m.group(1) def test_signup_html_cui_obligatoriu_ui(client): """GET /signup: campul CUI NU contine '(optional)' si are atribut required (US-001 UI).""" resp = client.get("/signup") assert resp.status_code == 200 # (a) NU trebuie sa apara textul "(optional)" langa CUI assert "(optional)" not in resp.text, "Campul CUI afiseaza '(optional)' — trebuie sa fie obligatoriu" # (b) input[name=cui] trebuie sa aiba atribut required assert 'name="cui"' in resp.text # cautam required pe aceeasi linie cu name="cui" sau intr-un bloc care contine name="cui" required import re # fie pe aceeasi linie: # fie in orice forma cu required si name="cui" in acelasi tag cui_input_match = re.search(r']*name="cui"[^>]*>', resp.text) assert cui_input_match, "input name='cui' negasit in HTML" assert "required" in cui_input_match.group(0), ( f"input[name='cui'] NU are atribut required: {cui_input_match.group(0)}" ) def test_signup_fara_cui_422(client): """POST /signup fara CUI -> 422, formular re-randat cu eroare, fara cont creat.""" resp = client.get("/signup") token = _csrf(resp.text) resp = client.post("/signup", data={ "name": "Service Fara CUI", "cui": "", "email": "fara_cui@test.com", "parola": "parolasecreta123", "consent": "1", "csrf_token": token, }) # trebuie sa returneze 422 (sau sa randeze formularul cu eroare) assert resp.status_code == 422 # cheia API nu trebuie sa apara assert "rfak_" not in resp.text # campul name trebuie sa fie pastrat (form re-render cu valorile existente) assert "Service Fara CUI" in resp.text # verifica ca nu s-a creat niciun cont from app.db import get_connection conn = get_connection() try: n = conn.execute( "SELECT COUNT(*) AS n FROM accounts WHERE name='Service Fara CUI'" ).fetchone()["n"] assert n == 0, "Cont creat desi CUI lipsea" finally: conn.close() def test_signup_scrie_email_pe_account(client): """POST /signup valid -> accounts.email = emailul utilizatorului.""" resp = client.get("/signup") token = _csrf(resp.text) resp = client.post("/signup", data={ "name": "Service Cu Email", "cui": "RO9999001", "email": "cu_email@test.com", "parola": "parolasecreta123", "consent": "1", "csrf_token": token, }) assert resp.status_code == 200 assert "rfak_" in resp.text from app.db import get_connection conn = get_connection() try: acct = conn.execute( "SELECT * FROM accounts WHERE name='Service Cu Email'" ).fetchone() assert acct is not None # emailul trebuie scris pe cont (normalizat: lower + trim) assert acct["email"] == "cu_email@test.com" finally: conn.close() def test_signup_email_duplicat_mesaj_email(client): """POST /signup cu email existent dar CUI nou -> mesaj despre EMAIL, NU despre CUI/firma. Bug: 'email deja folosit' contine 'deja folosit' -> era prins de conditia CUI duplicat si afisa gresit 'Aceasta firma (CUI X) e deja inregistrata' (CUI nou, NU cauza reala). Fix: verifica intai email-ul, apoi CUI-ul. """ from tests.conftest import make_test_cui # primul signup cu email E + CUI C1 resp = client.get("/signup") token = _csrf(resp.text) resp1 = client.post("/signup", data={ "name": "Firma Prima SRL", "cui": make_test_cui("email-dup-c1"), "email": "emaildup@test.com", "parola": "parolasecreta123", "consent": "1", "csrf_token": token, }) assert resp1.status_code == 200 assert "rfak_" in resp1.text, "Primul signup trebuia sa reuseasca" # al doilea signup cu ACELASI email dar CUI NOU resp = client.get("/signup") token2 = _csrf(resp.text) cui_nou = make_test_cui("email-dup-c2") resp2 = client.post("/signup", data={ "name": "Firma A Doua SRL", "cui": cui_nou, "email": "emaildup@test.com", "parola": "parolasecreta456", "consent": "1", "csrf_token": token2, }) assert resp2.status_code in (200, 422) assert "rfak_" not in resp2.text, "Nu trebuia creata cheie API la email duplicat" body_lower = resp2.text.lower() # mesajul trebuie sa se refere la EMAIL assert "email" in body_lower, ( f"Mesajul de eroare nu mentioneaza 'email': {resp2.text[:500]}" ) # mesajul NU trebuie sa afiseze pattern-ul gresit cu firma si CUI-ul nou # (CUI-ul apare legitim si in campul pre-completat al formularului, dar nu in mesajul de eroare) wrong_pattern = f"(cui {cui_nou.lower()}) e deja inregistrata" assert wrong_pattern not in body_lower, ( f"Mesajul arata gresit pattern-ul CUI-duplicat desi problema e emailul: {resp2.text[:500]}" ) # nu trebuie sa apara mesajul specific CUI-duplicat assert "e deja inregistrata" not in body_lower, ( f"Mesajul arata 'e deja inregistrata' (mesaj CUI) la eroare de email: {resp2.text[:500]}" ) def test_signup_cui_existent_mesaj_prietenos(client): """POST /signup cu CUI existent -> mesaj prietenos, NU mesaj tehnic cu 'activate --account'.""" resp = client.get("/signup") token = _csrf(resp.text) # primul signup client.post("/signup", data={ "name": "Firma Existenta SRL", "cui": "RO8888001", "email": "firma1@test.com", "parola": "parolasecreta123", "consent": "1", "csrf_token": token, }) # al doilea signup cu acelasi CUI resp = client.get("/signup") token2 = _csrf(resp.text) resp2 = client.post("/signup", data={ "name": "Alt Utilizator SRL", "cui": "RO8888001", "email": "firma2@test.com", "parola": "parolasecreta456", "consent": "1", "csrf_token": token2, }) assert resp2.status_code in (200, 422) # NU trebuie sa apara mesajul tehnic cu referinta la CLI assert "activate --account" not in resp2.text # trebuie sa apara un mesaj prietenos cu CUI-ul assert "RO8888001" in resp2.text # trebuie sa contina cuvant cheie de tip "firma" sau "inregistrata" body_lower = resp2.text.lower() assert any(kw in body_lower for kw in ["firma", "inregistrat", "cont", "acces"])