"""Teste US-005 (PRD 5.12): formular de editare partajat DRY + input date. _form_editare.html — partial NOU cu campurile vehicul/data/odo. _macros.html — macro `camp` extins cu tip='date'. _trimitere_detaliu.html — consuma partial-ul in ramura editabil. TDD: scriem testele RED inainte de implementare. """ from __future__ import annotations import json import os import re import tempfile from pathlib import Path import pytest from starlette.testclient import TestClient TEMPLATES_DIR = Path(__file__).resolve().parent.parent / "app" / "web" / "templates" # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def _create_account_user(email: str, name: str = "Service", password: str = "parolasecreta10"): 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) create_user(conn, acct_id, email, password) return acct_id finally: conn.close() def _login(client, email: str, password: str = "parolasecreta10") -> None: resp = client.get("/login") m = re.search(r'name="csrf_token"\s+value="([^"]+)"', resp.text) or \ re.search(r'value="([^"]+)"\s+name="csrf_token"', resp.text) assert m resp = client.post("/login", data={"email": email, "parola": password, "csrf_token": m.group(1)}) assert resp.status_code == 303 def _insert(acct: int, *, status: str, payload: dict) -> int: from app.db import get_connection conn = get_connection() try: cur = conn.execute( "INSERT INTO submissions (idempotency_key, account_id, status, payload_json) VALUES (?, ?, ?, ?)", (f"k-{os.urandom(6).hex()}", acct, status, json.dumps(payload)), ) conn.commit() return int(cur.lastrowid) finally: conn.close() def _payload_needs_data(vin: str = "WVWZZZ1JZXW0FE001") -> dict: return { "vin": vin, "nr_inmatriculare": "B200FE", "data_prestatie": "2026-06-15", "odometru_final": "", # gol -> needs_data "prestatii": [{"cod_prestatie": "R-FRANE"}], } @pytest.fixture() def client(monkeypatch): tmp = tempfile.mkdtemp() monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "form_editare.db")) monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "true") 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, follow_redirects=False) as c: yield c ratelimit._hits.clear() get_settings.cache_clear() # --------------------------------------------------------------------------- # Test 1: fragmentul de trimitere randeaza pentru data_prestatie # --------------------------------------------------------------------------- def test_form_editare_are_input_date_pe_data_prestatie(client): """Fragmentul de detaliu pentru un rand needs_data trebuie sa randereze pentru campul data_prestatie (calendar nativ, D#10/R3). Inainte de US-005, campul e type="text" -> test RED. """ acct = _create_account_user("fe1@test.com") sid = _insert(acct, status="needs_data", payload=_payload_needs_data()) _login(client, "fe1@test.com") resp = client.get(f"/_fragments/trimitere/{sid}") assert resp.status_code == 200 html = resp.text # Campul data_prestatie trebuie sa fie type="date" (nu type="text"). assert 'name="data_prestatie"' in html, "campul data_prestatie lipseste din fragment" # Cautam input cu name=data_prestatie si type=date. assert re.search(r']+name="data_prestatie"[^>]+type="date"', html) or \ re.search(r']+type="date"[^>]+name="data_prestatie"', html), \ "data_prestatie trebuie sa fie , nu type='text'" # Asiguram ca NU este type="text" pentru data_prestatie. # type="text" pe data_prestatie inseamna ca partial-ul nu e activ. match_text = re.search(r']+name="data_prestatie"[^>]+type="text"', html) or \ re.search(r']+type="text"[^>]+name="data_prestatie"', html) assert not match_text, \ "data_prestatie NU trebuie sa fie type='text' dupa US-005 (trebuie type='date')" # --------------------------------------------------------------------------- # Test 2: _trimitere_detaliu.html foloseste partial-ul _form_editare.html # --------------------------------------------------------------------------- def test_trimitere_detaliu_foloseste_form_partajat(): """Sursa _trimitere_detaliu.html trebuie sa includa _form_editare.html. Inainte de US-005, include lipseste -> test RED. """ sursa = (TEMPLATES_DIR / "_trimitere_detaliu.html").read_text(encoding="utf-8") # Trebuie sa contina include sau import din _form_editare.html. assert "_form_editare.html" in sursa, ( "_trimitere_detaliu.html nu referencieaza _form_editare.html. " "US-005 cere ca partial-ul sa fie consumat in ramura editabil." ) # --------------------------------------------------------------------------- # Test 3: macro `camp` din _macros.html suporta tip='date' # --------------------------------------------------------------------------- def test_camp_macro_randeaza_type_date(): """Macro `camp` din _macros.html trebuie sa suporte tip='date' si sa randeze fara a strica tip='text' (default). Inainte de US-005, macros.html nu are macro `camp` -> test RED. """ from jinja2 import Environment, FileSystemLoader env = Environment(loader=FileSystemLoader(str(TEMPLATES_DIR))) # Randare directa a macro-ului camp din _macros.html. tmpl = env.from_string( "{% from '_macros.html' import camp %}" "{{ camp('data_prestatie', 'Data prestatie', '2026-06-15', tip='date') }}" ) html = tmpl.render() # Trebuie sa contina type="date". assert 'type="date"' in html, \ "macro camp cu tip='date' trebuie sa randeze " assert 'name="data_prestatie"' in html, \ "macro camp trebuie sa randeze input cu name corect" # Verifica ca tip='text' (default) inca functioneaza. tmpl_text = env.from_string( "{% from '_macros.html' import camp %}" "{{ camp('nr_inmatriculare', 'Nr inmatriculare', 'B100AA') }}" ) html_text = tmpl_text.render() assert 'type="text"' in html_text, \ "macro camp fara tip explicit trebuie sa randeze type='text' (default neschimbat)" assert 'type="date"' not in html_text, \ "macro camp fara tip='date' NU trebuie sa randeze type='date'"