"""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'"