- #
Stare
Vehicul
Operatie
Data
- KM final
- Note
Actiuni
diff --git a/app/web/templates/_preview_rand.html b/app/web/templates/_preview_rand.html
index ad1ff3d..3026bf4 100644
--- a/app/web/templates/_preview_rand.html
+++ b/app/web/templates/_preview_rand.html
@@ -23,9 +23,21 @@
{% if _sent_dup %}class="preview-sent-row"{% endif %}
{% if oob_tr %}hx-swap-oob="outerHTML:#preview-row-{{ row.row_index }}"{% endif %}
style="{% if status == 'needs_review' %}background:rgba(230,179,74,.04);{% elif _sent_dup %}opacity:.6;{% endif %}">
- {{ row.row_index + 1 }}
+ {#- Motivul (validare / deja-trimis / duplicat) — fost coloana Note, acum tooltip pe pill.
+ KM final iese din tabel (se editeaza in modal). -#}
+ {%- if status == 'already_sent' and row.get('already_sent_info') -%}
+ {%- set ai = row.already_sent_info -%}
+ {%- set _nota = 'deja trimis ' ~ ((ai.get('created_at') or '')[:10]) ~ ((' (#' ~ ai.id_prezentare ~ ')') if ai.get('id_prezentare') else '') -%}
+ {%- elif status == 'duplicate_in_file' and row.get('duplicate_with') -%}
+ {%- set _dwith = [] -%}
+ {%- for idx in row.duplicate_with -%}{{ _dwith.append(idx + 1) or '' }}{%- endfor -%}
+ {%- set _nota = 'dubla cu randul ' ~ (_dwith | join(', ')) -%}
+ {%- else -%}
+ {%- set _nota = row.nota_umana or '' -%}
+ {%- endif -%}
-
+
{{ row.stare_eticheta }}
@@ -43,20 +55,6 @@
{% endif %}
{{ row.prez.data_prestatie }}
- {{ row.prez.odometru }}
-
- {% if status == 'already_sent' and row.get('already_sent_info') %}
- {% set ai = row.already_sent_info %}
- deja trimis {{ (ai.get('created_at') or '')[:10] }}
- {% if ai.get('id_prezentare') %}(#{{ ai.id_prezentare }}){% endif %}
- {% elif status == 'duplicate_in_file' and row.get('duplicate_with') %}
- dubla cu randul
- {% for idx in row.duplicate_with %}{{ idx + 1 }}{% if not loop.last %}, {% endif %}{% endfor %}
- {% else %}
- {{ row.nota_umana or '' }}
- {% endif %}
-
{% if status not in ('already_sent', 'duplicate_in_file') %}
Mapari{% if mapari_badge %}{{ mapari_badge }} {% endif %}
- {# US-006 (5.17): linia de plan — consum/trial (secundar, sub navigatie, non-blocant).
- Warn=culoare+text (accesibilitate): >=80% -> --warn; limita atinsa -> --err.
- Ierarhie: nu concureaza cu stripul de sanatate (E zero-silent-failures pastrat). #}
- {% if plan_linie is defined and plan_linie %}
+ {# US-006 (5.17) + T-6 (5.16): linia de plan in CORP apare DOAR in starea de avertizare
+ (>=80% -> --warn; limita atinsa -> --err). Consumul normal (N/60) traieste in badge-ul
+ din antet + linia din meniul burger, nu ca rand permanent in corp (densitate redusa).
+ Ierarhie: nu concureaza cu stripul de sanatate (zero-silent-failures pastrat). #}
+ {% if plan_linie and (plan_warn|default(false) or plan_limita_atinsa|default(false)) %}
- {# Linia 1: VIN mono scurt (slim-vin).
- Guard: vin_scurt='—' inseamna VIN lipsa; fallback la vehicul_nr. #}
- {% if r.prez.vin_scurt and r.prez.vin_scurt != '—' %}
-
{{ r.prez.vin_scurt }}
+ {# Linia 1: nr. inmatriculare (placuta) — identificatorul primar pe care il
+ scaneaza operatorul. .slim-vin reumplut (acelasi nume de clasa, churn minim).
+ Fallback cand placuta lipseste ('—'): VIN scurt, apoi mesaj neutru
+ (nu randa em-dash izolat ca identificator). #}
+ {% if r.prez.vehicul_nr and r.prez.vehicul_nr != '—' %}
+
{{ r.prez.vehicul_nr }}
+ {% elif r.prez.vin_scurt and r.prez.vin_scurt != '—' %}
+
{{ r.prez.vin_scurt }}
{% else %}
-
{{ r.prez.vehicul_nr }}
+
fara numar
{% endif %}
- {# Linia 2: Operatie · ora/data (slim-meta muted) #}
-
{{ r.prez.operatie }} · {{ r.updated_at }}
-
- {# Cod RAR sau indicatorul 'nemapat': discret sub operatie.
- Mentine compatibilitatea cu testele cod_rar: OE-2 vizibil, fara prefix 'cod RAR:'. #}
- {% if r.prez.cod_rar and r.prez.cod_rar != '—' %}
-
{{ r.prez.cod_rar }}
- {% else %}
-
nemapat
- {% endif %}
-
- {# Linia meta discreta: nr inmatriculare · data prestatie · nr prezentare RAR.
- Accesibila pe rand; informatia completa e in modalul de detaliu. #}
-
diff --git a/app/web/templates/base.html b/app/web/templates/base.html
index 14b0476..1faa321 100644
--- a/app/web/templates/base.html
+++ b/app/web/templates/base.html
@@ -143,6 +143,9 @@
.s-needs_review{color:var(--warn);}
.s-already_sent,.s-duplicate_in_file{color:var(--muted);}
.muted { color:var(--muted); }
+ /* Heading/eticheta accesibila doar pentru cititoare de ecran (vizual ascunsa). */
+ .sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden;
+ clip:rect(0 0 0 0); white-space:nowrap; border:0; }
a { color:var(--accent); }
/* Drop zone upload fisier */
.drop-zone { border:2px dashed var(--line); border-radius:8px; padding:32px 20px;
@@ -410,7 +413,9 @@
.tabel-trimiteri th, .tabel-trimiteri td { white-space:normal; word-break:break-word; vertical-align:top; }
.tabel-trimiteri .col-chk { width:30px; }
.tabel-trimiteri .col-id { width:48px; }
- .tabel-trimiteri .col-stare { width:104px; }
+ /* col-stare largita (bug 4a 5.16): cu table-layout:fixed + pill nowrap, 104px era
+ prea ingusta -> pill-ul de stare se revarsa peste col-vehicul. 140px o contine. */
+ .tabel-trimiteri .col-stare { width:140px; }
.tabel-trimiteri .col-data { width:104px; }
.tabel-trimiteri .col-rar { width:96px; }
.tabel-trimiteri .col-actualizat { width:128px; }
@@ -722,8 +727,27 @@
.trimitere-slim:last-child { border-bottom:none; }
.trimitere-slim:hover { background:color-mix(in srgb, var(--accent) 6%, transparent); }
.trimitere-slim:focus, .trimitere-slim:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
- .slim-vin { font-family:var(--font-mono); font-size:var(--fs-md); font-weight:500; color:var(--ink); }
+ .slim-vin { font-family:var(--font-mono); font-size:var(--fs-md); font-weight:600; color:var(--ink); }
.slim-meta { font-size:var(--fs-sm); color:var(--muted); margin-top:3px; }
+ /* Linia 2 a randului slim (5.16): cod RAR · operatie (ellipsis) · data, pe UN rand.
+ Ellipsis-ul pe operatie garanteaza 2 linii MAX si la 390px. */
+ .slim-rand2 { display:flex; align-items:baseline; gap:6px; min-width:0; }
+ .slim-rand2 .cod-rar-cod { flex:0 0 auto; font-family:var(--font-mono); font-weight:600;
+ color:var(--accent); }
+ .slim-rand2 .cod-rar-cod.muted { color:var(--muted); font-weight:500; }
+ .slim-rand2 .slim-op { flex:1 1 auto; min-width:0; white-space:nowrap; overflow:hidden;
+ text-overflow:ellipsis; color:var(--ink); }
+ .slim-rand2 .slim-data { flex:0 0 auto; }
+ .slim-rand2 .slim-op::before, .slim-rand2 .slim-data::before {
+ content:"·"; color:var(--muted); margin-right:6px; }
+ .lista-trimiteri-slim .eticheta-problema { font-size:var(--fs-xs); line-height:1.3; margin-top:2px; }
+ /* Pill slim (5.16): fill-tint + dot 7px + text colorat per stare (currentColor din .s-*).
+ Pastrat pe FIECARE rand inclusiv Finalizat (linistit dar prezent). */
+ .lista-trimiteri-slim .pill { display:inline-flex; align-items:center; gap:5px; font-weight:600;
+ background:color-mix(in srgb, currentColor 14%, transparent);
+ border-color:color-mix(in srgb, currentColor 35%, transparent); }
+ .lista-trimiteri-slim .pill::before { content:""; width:7px; height:7px; border-radius:99px;
+ background:currentColor; flex-shrink:0; }
/* .camp-slim — varianta compacta camp formular: label --fs-sm muted deasupra, input --fs-md, fundal --card2.
Mono pentru campuri VIN/odometru/nr: adauga clasa .camp-mono pe input. */
.camp-slim { margin-bottom:8px; }
@@ -756,7 +780,9 @@
.op-row { display:flex; align-items:center; justify-content:space-between; gap:10px;
padding:8px 10px; border:1px solid var(--line); border-radius:6px;
background:var(--card2); margin-bottom:8px; }
- .op-row-name { font-size:var(--fs-xs); font-weight:500; color:var(--ink); }
+ /* Nume operatie emfatic (T-9 5.16): proeminent (bold) ca in mockup — e ancora
+ vizuala a randului de mapare op<->cod. */
+ .op-row-name { font-size:var(--fs-sm); font-weight:700; color:var(--ink); }
.op-row-warn { border-color:color-mix(in srgb, var(--warn) 45%, var(--line)); }
/* Mobil: tinta touch pentru trimitere-slim (deja garantata prin min-height:44px in regula de baza) */
@media (max-width:767px) {
diff --git a/docs/raport-comparatie-mockup-5.16.md b/docs/raport-comparatie-mockup-5.16.md
index edfbe6c..51aeb19 100644
--- a/docs/raport-comparatie-mockup-5.16.md
+++ b/docs/raport-comparatie-mockup-5.16.md
@@ -471,17 +471,18 @@ risc regresie vizuala fara baza AC). **Auto-decis: doar instanta sub-12px** (`et
- **Fallback**: `vehicul_nr == '—'` → nu randa em-dash singur (mesaj fallback).
- Pastreaza numele claselor `slim-vin`/`slim-meta` (reumple, nu redenumi) — minimizeaza churn teste.
-### Implementation Tasks (agregat)
-- [ ] **T-1 (INALTA) — `_submissions.html`** — refactor rand 4→2 linii cu placuta+codRAR+operatie+data_prestatie+pill; fallback placuta; pastreaza clase. Update teste: rescrie test_vin_pe_rand_separat_sub_nr, test_rand_slim_vin_operatie_pill, test_submissions_coloane_umane; adauga test 2-linii + test fallback placuta.
-- [ ] **T-2 (INALTA) — `base.html` (CSS pill) + `_submissions.html`** — restilare pill slim ca mockup (fill tint + dot + text colorat per `stare_css`); pill ramane pe finalizat.
-- [ ] **T-3 (INALTA) — `_preview_import.html` / `base.html:401`** — bug 4a: `.col-stare` width 104px→~140px (+ `overflow:hidden` sau pill wrap). NU atinge nowrap pe col-vehicul (test_web_preview_compact). Reducere 8→4 coloane (densitate) ca task separat.
-- [ ] **T-4 (MEDIE) — `_preview_import.html`** — reducere la 4 coloane esentiale (Stare/Vehicul/Operatie/Data + Editeaza); muta KM + mesaj validare in randul de editare/tooltip.
-- [ ] **T-5 (MEDIE) — `_coada.html:10-19`** — scoate titlul "Trimiterile tale" (h2); relocare export CSV langa tab-uri / meniu cont (PRD 5.16/US-002).
-- [ ] **T-6 (MEDIE) — `_status.html:140`** — scoate randul plan "N/60 luna asta" din corp; pastreaza badge antet + linie burger (PRD 5.17/US-006). Daca >=80% consum, afiseaza doar in starea de avertizare.
-- [ ] **T-7 (MEDIE) — `_chips_prestatii.html:122`** — guard `{% if _extra %}` pe containerul `.chips` (operatii-mode), elimina chenarul gol.
-- [ ] **T-8 (MICA) — `_submissions.html:133`** — `font-size:10px`→`var(--fs-xs)` (doar instanta sub-12px).
-- [ ] **T-9 (MICA) — copy/stil** — "Anuleaza"→"Renunta" (form editare); nume operatie emfatic (bold) in editorul de chips per mockup.
-- [ ] **Defer TODOS** — stare eroare HTMX lista (D-4); teste regresie vizuala; dropzone zona-mare (sec.5); retokenizare px completa; diacritice (decis: nu).
+### Implementation Tasks (agregat) — LIVRAT 2026-06-29 (toate verzi, 1392 teste)
+- [x] **T-1 (INALTA) — `_submissions.html`** — refactor rand 4→2 linii cu placuta+codRAR+operatie+data_prestatie+pill; fallback placuta; clase pastrate. Teste rescrise: test_rand_slim_vin_operatie_pill, test_submissions_coloane_umane, test_placuta_pe_rand_identificator_primar (fost test_vin_pe_rand_separat_sub_nr), test_placuta_lipsa_nu_genereaza_rand_gol (fallback "fara numar").
+- [x] **T-2 (INALTA) — `base.html` (CSS pill) + `_submissions.html`** — pill slim restilat (fill tint + dot 7px + text colorat per `stare_css` via currentColor), scopat `.lista-trimiteri-slim .pill`; ramane pe finalizat.
+- [x] **T-3 (INALTA) — `base.html`** — bug 4a: `.tabel-trimiteri .col-stare` 104px→140px. nowrap pe col-vehicul neatins.
+- [x] **T-4 (MEDIE) — `_preview_import.html` + `_preview_rand.html`** — reducere la 5 coloane (Stare/Vehicul/Operatie/Data/Actiuni); scoase col-id, col-km, col-note; motivul mutat in `title` pe pill, KM in modal.
+- [x] **T-5 (MEDIE) — `_coada.html`** — titlu vizibil "Trimiterile tale" → `
` (a11y pastrat); badge "de rezolvat" + export CSV intr-un rand discret. `.sr-only` adaugat in base.html.
+- [x] **T-6 (MEDIE) — `_status.html`** — linia plan in corp DOAR pe avertizare (`plan_warn`/`plan_limita_atinsa`); consum normal in badge antet + burger. Teste status mutate pe pagina completa.
+- [x] **T-7 (MEDIE) — `_chips_prestatii.html`** — guard `{% if _extra_chips %}` pe containerul `.chips`, chenarul gol eliminat.
+- [x] **T-8 (MICA) — `_submissions.html` / base.html** — `font-size:10px`→`var(--fs-xs)` (eticheta-problema, prin clasa scopata `.lista-trimiteri-slim .eticheta-problema`).
+- [x] **T-9 (MICA) — `_form_editare.html` + base.html** — "Anuleaza"→"Renunta" (default); `.op-row-name` emfatic (bold, `--fs-sm`).
+- [ ] **Defer — tracked in `TODOS.md`** (la cererea userului 2026-06-29): stare eroare HTMX lista (D-4); retokenizare px completa; diacritice in textul vizibil.
+- [x] **Defer — inchis ca acceptabil** (netrackuit): teste regresie vizuala (tooling viitor); dropzone zona-mare (sec.5, raportul il marcheaza acceptabil).
### Verificare la implementare
`python3 -m pytest tests/test_web_submissions.py tests/test_web_submissions_layout.py tests/test_web_responsive.py tests/test_web_preview_compact.py -q`
diff --git a/tests/test_web_status.py b/tests/test_web_status.py
index 97512b6..0afcd0a 100644
--- a/tests/test_web_status.py
+++ b/tests/test_web_status.py
@@ -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]}"
diff --git a/tests/test_web_submissions.py b/tests/test_web_submissions.py
index 4c14a7b..04d3aa4 100644
--- a/tests/test_web_submissions.py
+++ b/tests/test_web_submissions.py
@@ -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"
diff --git a/tests/test_web_submissions_layout.py b/tests/test_web_submissions_layout.py
index acee272..fb2b28c 100644
--- a/tests/test_web_submissions_layout.py
+++ b/tests/test_web_submissions_layout.py
@@ -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 (block-level, prominent).
- PRD 5.10 (US-005): VIN era
sub nr in coloana Vehicul.
- PRD 5.15 (US-004): VIN e acum identificatorul PRINCIPAL, linia 1 a randului slim,
- in
(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:
...000001...
- vin_fragment = "000001"
+ # Placuta e intr-un element block-level (div cu clasa slim-vin)
+ plac = "B123XYZ"
found_slim_vin = re.search(
- rf'
]*class="slim-vin[^"]*"[^>]*>[^<]*{re.escape(vin_fragment)}[^<]*
',
+ rf'
]*class="slim-vin[^"]*"[^>]*>[^<]*{re.escape(plac)}[^<]*
',
html,
)
assert found_slim_vin, (
- f"VIN '{vin_fragment}' trebuie sa fie in
(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
(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'
]*class="slim-vin[^"]*"[^>]*>([^<]*)
', 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'
]*class="slim-vin[^"]*"[^>]*>([^<]*)
', 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"