feat(5.16): aliniere lista/preview la mockup + fix lock seed la boot
Implementeaza planul aprobat din docs/raport-comparatie-mockup-5.16.md (T-1..T-9): - T-1/T-8: rand lista 4->2 linii (placuta primar + cod RAR · operatie · data + pill), fallback placuta, eticheta-problema 10px->--fs-xs (_submissions.html, base.html) - T-2: pill slim restilat fill-tint + dot 7px + text colorat per stare (base.html) - T-3: bug 4a coliziune pill/vehicul in preview — col-stare 104->140px (base.html) - T-4: preview 8->5 coloane (scos #, KM, Note; motivul -> title pe pill) - T-5: titlu sectiune "Trimiterile tale" -> sr-only (a11y) + badge/export discret - T-6: linia plan N/60 in corp doar pe avertizare; consum normal in badge+burger - T-7: guard chenar gol chips extra (_chips_prestatii.html) - T-9: "Anuleaza"->"Renunta"; nume operatie emfatic bold Fix boot: init_db reincarca seedul de ~17k operatii (5.18) pe FIECARE pornire, pe API + worker concurent -> "database is locked" la al doilea proces. Guard "_if_empty" pe mapping_suggestions (ca seed_nomenclator_if_empty) -> boot rapid, fara cursa. Teste actualizate (slim 2-linii, fallback placuta, plan in burger). TODOS.md: defer trackuit (eroare HTMX lista, retokenizare px, diacritice). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -495,7 +495,9 @@ def _insert_submissions_sent(account_id: int, n: int) -> None:
|
||||
|
||||
|
||||
def test_afisaj_plan_si_zile_trial(client):
|
||||
"""US-006: cont in trial Pro -> fragment status arata 'trial N zile ramase'.
|
||||
"""US-006 + T-6 (5.16): cont in trial Pro -> linia de plan din meniul burger (pagina
|
||||
completa) arata 'Plan: Pro · trial N zile ramase'. In starea normala (non-warn) plan_linie
|
||||
NU mai e rand in corpul fragmentului status — traieste in badge antet + burger.
|
||||
Contul nou primeste trial_until=now+30z automat la creare.
|
||||
"""
|
||||
acct_id, _ = _create_account_user("trialzile@test.com")
|
||||
@@ -505,7 +507,7 @@ def test_afisaj_plan_si_zile_trial(client):
|
||||
future = (datetime.now(timezone.utc) + timedelta(days=18, hours=12)).strftime("%Y-%m-%d %H:%M:%S")
|
||||
_set_trial_until(acct_id, future)
|
||||
|
||||
resp = client.get("/_fragments/status")
|
||||
resp = client.get("/", follow_redirects=True)
|
||||
assert resp.status_code == 200
|
||||
html = resp.text
|
||||
|
||||
@@ -516,7 +518,8 @@ def test_afisaj_plan_si_zile_trial(client):
|
||||
|
||||
|
||||
def test_afisaj_consum_lunar(client):
|
||||
"""US-006: cont free (fara trial) -> fragment status arata 'Gratuit · N/60 luna asta'."""
|
||||
"""US-006 + T-6 (5.16): cont free (fara trial) -> linia de plan din burger (pagina
|
||||
completa) arata 'Gratuit · N/60 luna asta'. Consumul normal nu mai e rand in corp."""
|
||||
acct_id, _ = _create_account_user("consumlun@test.com")
|
||||
_login(client, "consumlun@test.com", "parolasecreta10")
|
||||
|
||||
@@ -525,7 +528,7 @@ def test_afisaj_consum_lunar(client):
|
||||
# Insereaza 5 submissions sent luna asta
|
||||
_insert_submissions_sent(acct_id, 5)
|
||||
|
||||
resp = client.get("/_fragments/status")
|
||||
resp = client.get("/", follow_redirects=True)
|
||||
assert resp.status_code == 200
|
||||
html = resp.text
|
||||
|
||||
@@ -584,7 +587,8 @@ def test_copy_pluralizare_zi_zile(client):
|
||||
future_18 = (datetime.now(timezone.utc) + timedelta(days=18, hours=12)).strftime("%Y-%m-%d %H:%M:%S")
|
||||
_set_trial_until(acct_id, future_18)
|
||||
|
||||
resp = client.get("/_fragments/status")
|
||||
# T-6 (5.16): linia de plan (cu pluralizarea zilelor) traieste in burger pe pagina completa.
|
||||
resp = client.get("/", follow_redirects=True)
|
||||
assert resp.status_code == 200
|
||||
html = resp.text
|
||||
assert "18 zile" in html, f"'18 zile' lipseste. HTML: {html[:800]}"
|
||||
@@ -596,7 +600,7 @@ def test_copy_pluralizare_zi_zile(client):
|
||||
future_1 = (datetime.now(timezone.utc) + timedelta(days=1, hours=12)).strftime("%Y-%m-%d %H:%M:%S")
|
||||
_set_trial_until(acct_id, future_1)
|
||||
|
||||
resp = client.get("/_fragments/status")
|
||||
resp = client.get("/", follow_redirects=True)
|
||||
assert resp.status_code == 200
|
||||
html = resp.text
|
||||
assert "1 zi" in html, f"'1 zi' (singular) lipseste la o zi ramasa. HTML: {html[:800]}"
|
||||
|
||||
@@ -107,8 +107,9 @@ def test_submissions_coloane_umane(client):
|
||||
assert "B777ZZZ" in html, "Nr inmatriculare din payload lipseste"
|
||||
assert "Reparatie frane" in html, "Operatia din payload lipseste"
|
||||
|
||||
# Nr. prezentare RAR accesibil pe linia meta discreta
|
||||
assert "68516" in html, "Nr. prezentare RAR lipseste din linia meta"
|
||||
# 5.16: #id_prezentare nu mai e pe rand (randul are MAX 2 linii) — detaliul complet
|
||||
# (inclusiv nr. prezentare RAR) traieste in modalul de detaliu.
|
||||
assert "68516" not in html, "Nr. prezentare RAR nu trebuie sa mai apara pe randul slim"
|
||||
|
||||
|
||||
def test_tab_eticheta_trimiteri(client):
|
||||
@@ -426,9 +427,9 @@ def test_detaliu_trimitere_404_cross_account(client):
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_rand_slim_vin_operatie_pill(client):
|
||||
"""US-004: fiecare rand slim afiseaza VIN scurt in .slim-vin, operatie+ora in
|
||||
.slim-meta si un pill de stare cu clasa stare_css si eticheta stare_scurt.
|
||||
Lista e inconjurata de .lista-trimiteri-slim.
|
||||
"""5.16: fiecare rand slim are 2 linii — L1 placuta (nr. inmatriculare) in .slim-vin,
|
||||
L2 cod RAR · operatie · data in .slim-meta, plus un pill de stare cu clasa stare_css
|
||||
si eticheta stare_scurt. Lista e inconjurata de .lista-trimiteri-slim.
|
||||
"""
|
||||
acct = _create_account_user("slim1@test.com")
|
||||
_insert_submission(acct, "sent", id_prezentare=80001)
|
||||
@@ -442,14 +443,16 @@ def test_rand_slim_vin_operatie_pill(client):
|
||||
assert "lista-trimiteri-slim" in html, "lista-trimiteri-slim lipseste din raspuns"
|
||||
assert "trimitere-slim" in html, "trimitere-slim lipseste din raspuns"
|
||||
|
||||
# VIN scurt in clasa slim-vin (mono, linia 1)
|
||||
assert "slim-vin" in html, "slim-vin lipseste — linia 1 VIN mono"
|
||||
# L1: placuta (identificator primar) in clasa slim-vin
|
||||
assert "slim-vin" in html, "slim-vin lipseste — linia 1 placuta"
|
||||
assert "B777ZZZ" in html, "placuta (nr. inmatriculare) lipseste de pe rand"
|
||||
|
||||
# Linia 2 muted (operatie + ora/data)
|
||||
assert "slim-meta" in html, "slim-meta lipseste — linia 2 muted"
|
||||
# L2: cod RAR · operatie · data (slim-meta / slim-rand2)
|
||||
assert "slim-meta" in html, "slim-meta lipseste — linia 2"
|
||||
assert "slim-rand2" in html, "slim-rand2 lipseste — linia 2 (cod RAR · operatie · data)"
|
||||
|
||||
# VIN scurt randat (WVWZZZ1JZXW000777 -> …000777)
|
||||
assert "000777" in html, "VIN scurt (ultimele 6 cifre) lipseste"
|
||||
# VIN integral nu mai e pe rand (5.16) — traieste in modalul de detaliu.
|
||||
assert "000777" not in html, "VIN scurt nu mai trebuie randat pe randul slim (2 linii)"
|
||||
|
||||
# Pill de stare: clasa CSS + eticheta scurta
|
||||
assert "s-sent" in html, "clasa pill s-sent lipseste"
|
||||
|
||||
@@ -81,12 +81,13 @@ def client(monkeypatch):
|
||||
get_settings.cache_clear()
|
||||
|
||||
|
||||
def test_vin_pe_rand_separat_sub_nr(client):
|
||||
"""VIN-ul apare intr-un element block-level cu clasa slim-vin (PRD 5.15 US-004).
|
||||
def test_placuta_pe_rand_identificator_primar(client):
|
||||
"""Placuta (nr. inmatriculare) e identificatorul PRIMAR, linia 1 a randului slim
|
||||
(5.16): in <div class="slim-vin"> (block-level, prominent).
|
||||
|
||||
PRD 5.10 (US-005): VIN era <div class="muted"> sub nr in coloana Vehicul.
|
||||
PRD 5.15 (US-004): VIN e acum identificatorul PRINCIPAL, linia 1 a randului slim,
|
||||
in <div class="slim-vin"> (mono, prominent, block-level). NU mai e muted.
|
||||
PRD 5.15 (US-004): VIN era identificatorul primar pe linia 1.
|
||||
5.16 (directiva user): operatorul scaneaza placuta de pe comanda, nu VIN-ul de 17
|
||||
caractere — placuta devine linia 1, VIN integral se muta in modalul de detaliu.
|
||||
"""
|
||||
acct = _create_account_user("vin_layout@test.com")
|
||||
_ins(acct, vin="WVWZZZ1JZXW000001", nr="B123XYZ")
|
||||
@@ -96,46 +97,51 @@ def test_vin_pe_rand_separat_sub_nr(client):
|
||||
assert resp.status_code == 200
|
||||
html = resp.text
|
||||
|
||||
# VIN trunchiat trebuie sa apara in HTML
|
||||
assert "000001" in html, "VIN-ul trunchiat trebuie sa apara in lista slim"
|
||||
# Placuta trebuie sa apara in HTML
|
||||
assert "B123XYZ" in html, "placuta (nr. inmatriculare) trebuie sa apara in lista slim"
|
||||
|
||||
# VIN e intr-un element block-level (div cu clasa slim-vin)
|
||||
# Pattern: <div class="slim-vin">...000001...</div>
|
||||
vin_fragment = "000001"
|
||||
# Placuta e intr-un element block-level (div cu clasa slim-vin)
|
||||
plac = "B123XYZ"
|
||||
found_slim_vin = re.search(
|
||||
rf'<div[^>]*class="slim-vin[^"]*"[^>]*>[^<]*{re.escape(vin_fragment)}[^<]*</div>',
|
||||
rf'<div[^>]*class="slim-vin[^"]*"[^>]*>[^<]*{re.escape(plac)}[^<]*</div>',
|
||||
html,
|
||||
)
|
||||
assert found_slim_vin, (
|
||||
f"VIN '{vin_fragment}' trebuie sa fie in <div class=\"slim-vin\"> (block-level, "
|
||||
f"mono, linia 1 a randului slim). HTML gasit: "
|
||||
+ html[max(0, html.find(vin_fragment) - 80):html.find(vin_fragment) + 80]
|
||||
f"placuta '{plac}' trebuie sa fie in <div class=\"slim-vin\"> (linia 1 a "
|
||||
f"randului slim). HTML gasit: "
|
||||
+ html[max(0, html.find(plac) - 80):html.find(plac) + 80]
|
||||
)
|
||||
|
||||
# VIN integral NU mai e pe rand (max 2 linii) — traieste in modalul de detaliu.
|
||||
assert "000001" not in html, "VIN-ul nu mai trebuie randat pe randul slim (5.16)"
|
||||
|
||||
def test_vin_lipsa_nu_genereaza_rand_gol(client):
|
||||
"""Cand VIN-ul lipseste (sau e EMPTY='—'), slim-vin nu afiseaza '—' izolat.
|
||||
Fallback: slim-vin afiseaza vehicul_nr (nr. inmatriculare) cu clasa muted.
|
||||
(PRD 5.15 US-004: slim-vin are garda vin != '—')
|
||||
|
||||
def test_placuta_lipsa_nu_genereaza_rand_gol(client):
|
||||
"""Cand placuta SI VIN-ul lipsesc, slim-vin nu afiseaza '—' izolat ca identificator.
|
||||
Fallback (5.16): VIN scurt daca exista, altfel mesaj neutru ('fara numar') — niciodata
|
||||
un em-dash singur ca identificator primar.
|
||||
"""
|
||||
acct = _create_account_user("vin_gol@test.com")
|
||||
sid = _ins(acct, vin="", nr="B999TST") # VIN gol -> vin_scurt='—'
|
||||
# Placuta prezenta -> e identificatorul primar pe linia 1.
|
||||
sid1 = _ins(acct, vin="", nr="B999TST")
|
||||
# Placuta SI VIN absente -> fallback 'fara numar' (nu '—' izolat).
|
||||
sid2 = _ins(acct, vin="", nr="")
|
||||
_login(client, "vin_gol@test.com")
|
||||
|
||||
resp = client.get("/_fragments/submissions")
|
||||
assert resp.status_code == 200
|
||||
html = resp.text
|
||||
|
||||
# Randul trebuie sa existe
|
||||
assert f'id="trimitere-row-{sid}"' in html
|
||||
# Ambele randuri exista
|
||||
assert f'id="trimitere-row-{sid1}"' in html
|
||||
assert f'id="trimitere-row-{sid2}"' in html
|
||||
|
||||
# slim-vin NU trebuie sa contina '—' izolat (VIN lipsa -> fallback vehicul_nr)
|
||||
slim_vin_match = re.search(r'<div[^>]*class="slim-vin[^"]*"[^>]*>([^<]*)</div>', html)
|
||||
assert slim_vin_match, "slim-vin lipseste din randul cu VIN gol"
|
||||
slim_vin_content = slim_vin_match.group(1).strip()
|
||||
assert slim_vin_content != "—", (
|
||||
"slim-vin afiseaza '—' izolat cand VIN lipseste — "
|
||||
"trebuie sa afiseze vehicul_nr ca fallback"
|
||||
)
|
||||
# Fallback: nr inmatriculare vizibil
|
||||
assert "B999TST" in html, "Nr inmatriculare (fallback) lipseste cand VIN e gol"
|
||||
# Placuta vizibila cand exista
|
||||
assert "B999TST" in html, "placuta (nr. inmatriculare) lipseste de pe rand"
|
||||
|
||||
# Niciun slim-vin nu contine '—' izolat
|
||||
for m in re.finditer(r'<div[^>]*class="slim-vin[^"]*"[^>]*>([^<]*)</div>', html):
|
||||
assert m.group(1).strip() != "—", "slim-vin afiseaza '—' izolat ca identificator"
|
||||
|
||||
# Fallback neutru cand placuta + VIN lipsesc
|
||||
assert "fara numar" in html, "fallback 'fara numar' lipseste cand placuta+VIN absente"
|
||||
|
||||
Reference in New Issue
Block a user