Trimiteri desktop = tabel grid cu header, un rand per trimitere: status = bulina cu tooltip, mediu = litera T/P, multi-cod = primul cod + badge +N, sub-linie de eroare cu textul brut RAR doar pe error/needs_data. Mobil: 2 linii prin grid-areas, fara header. Actiunile bulk apar doar la selectie (bara contextuala cu contor + texte explicite). Mapari: exemplu concret in loc de descriere la Reguli automate. Fix buton "+" chips (nu facea nimic, fara eroare): hx-disabled-elt="find button" mostenit de la form-ul parinte crapa htmx inainte de request -> hx-disabled-elt="this" explicit pe butoanele chips; separat, no-op-urile silentioase din post_form_chips au acum mesaje (cod invalid/duplicat) si confirmare cu chip evidentiat la succes. Suita: 1622 passed. Verify E2E in browser (desktop 1280 + mobil 390). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
235 lines
8.5 KiB
Python
235 lines
8.5 KiB
Python
"""Teste helper pur payload -> campuri afisabile.
|
|
|
|
Helper partajat web + API (DRY). Defensiv: nu arunca pe payload
|
|
malformat; tolerant la diferentele de chei intre canale (numar vs
|
|
numarInmatriculare) si la coercion Excel (odometru "123.0", VIN non-string).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from app.payload_view import prezentare_din_payload, EMPTY
|
|
|
|
|
|
def test_detalii_din_payload():
|
|
"""Payload complet -> toate campurile afisabile corecte."""
|
|
payload = json.dumps({
|
|
"vin": "WVWZZZ1JZXW000001",
|
|
"nr_inmatriculare": "B123XYZ",
|
|
"odometru_final": "123456",
|
|
"data_prestatie": "2026-06-18",
|
|
"prestatii": [{"cod_prestatie": "R-FRANE", "denumire": "Reparatie frane"}],
|
|
})
|
|
d = prezentare_din_payload(payload)
|
|
assert d["vehicul_nr"] == "B123XYZ"
|
|
assert d["vin"] == "WVWZZZ1JZXW000001"
|
|
assert "000001" in d["vin_scurt"] # trunchiat dar identificabil
|
|
assert d["operatie"] == "Reparatie frane"
|
|
assert d["cod"] == "R-FRANE"
|
|
assert d["data_prestatie"] == "2026-06-18"
|
|
assert d["odometru"] == "123456"
|
|
|
|
|
|
def test_payload_partial():
|
|
"""Campuri lipsa -> EMPTY, fara exceptie."""
|
|
d = prezentare_din_payload(json.dumps({"vin": "WVWZZZ1JZXW000002"}))
|
|
assert d["vin"] == "WVWZZZ1JZXW000002"
|
|
assert d["vehicul_nr"] == EMPTY
|
|
assert d["operatie"] == EMPTY
|
|
assert d["cod"] == EMPTY
|
|
assert d["data_prestatie"] == EMPTY
|
|
assert d["odometru"] == EMPTY
|
|
|
|
|
|
def test_payload_gol():
|
|
"""Payload gol / None -> toate EMPTY, fara exceptie."""
|
|
for p in (None, "", "{}", {}):
|
|
d = prezentare_din_payload(p)
|
|
assert d["vehicul_nr"] == EMPTY
|
|
assert d["vin"] == EMPTY
|
|
|
|
|
|
def test_payload_invalid():
|
|
"""JSON invalid / tip neasteptat -> fallback grijuliu (nu arunca)."""
|
|
for bad in ("nu-e-json", "[1,2,3]", "null", "12345"):
|
|
d = prezentare_din_payload(bad)
|
|
assert d["vin"] == EMPTY # degradeaza curat
|
|
|
|
|
|
def test_payload_coercion_excel():
|
|
"""Odometru '123.0'/numeric si VIN non-string afisate curat; chei API alternative."""
|
|
# Excel coercion: odometru float-string si numeric
|
|
d1 = prezentare_din_payload({"odometru_final": "123456.0"})
|
|
assert d1["odometru"] == "123456"
|
|
d2 = prezentare_din_payload({"odometru_final": 123456})
|
|
assert d2["odometru"] == "123456"
|
|
# VIN non-string (coercion Excel)
|
|
d3 = prezentare_din_payload({"vin": 12345678901234567})
|
|
assert d3["vin"] == "12345678901234567"
|
|
# Chei alternative canal API (numar / numarInmatriculare / odometru)
|
|
d4 = prezentare_din_payload({"numar": "CJ99ABC", "odometru": "777.0"})
|
|
assert d4["vehicul_nr"] == "CJ99ABC"
|
|
assert d4["odometru"] == "777"
|
|
d5 = prezentare_din_payload({"numarInmatriculare": "TM01AAA"})
|
|
assert d5["vehicul_nr"] == "TM01AAA"
|
|
|
|
|
|
def test_operatie_fallback_la_cod():
|
|
"""Fara denumire -> operatie afiseaza codul; cod intern cand lipseste cel RAR."""
|
|
d = prezentare_din_payload({"prestatii": [{"cod_op_service": "OP-77"}]})
|
|
assert d["cod"] == "OP-77"
|
|
assert d["operatie"] == "OP-77"
|
|
|
|
|
|
# --- cod_rar distinct ---
|
|
|
|
def test_cod_rar_prezent_cand_mapat():
|
|
"""cod_prestatie prezent -> cod_rar e uppercase + strip '.0'."""
|
|
d = prezentare_din_payload({
|
|
"prestatii": [{"cod_prestatie": "r-frane", "denumire": "Reparatie frane"}]
|
|
})
|
|
assert d["cod_rar"] == "R-FRANE"
|
|
|
|
# defensiv ca odometru: strip '.0' chiar daca codurile RAR nu au zecimale
|
|
d2 = prezentare_din_payload({
|
|
"prestatii": [{"cod_prestatie": "oe-2.0"}]
|
|
})
|
|
assert d2["cod_rar"] == "OE-2"
|
|
|
|
# deja uppercase + fara zecimale -> trece neschimbat
|
|
d3 = prezentare_din_payload({
|
|
"prestatii": [{"cod_prestatie": "OE-2", "denumire": "Verificare"}]
|
|
})
|
|
assert d3["cod_rar"] == "OE-2"
|
|
|
|
|
|
def test_cod_rar_gol_cand_nemapat():
|
|
"""cod_prestatie absent/None -> cod_rar == EMPTY; NU cade pe cod_op_service."""
|
|
# doar cod_op_service prezent
|
|
d = prezentare_din_payload({
|
|
"prestatii": [{"cod_op_service": "OP-77", "denumire": "Verificare faruri"}]
|
|
})
|
|
assert d["cod_rar"] == EMPTY
|
|
|
|
# fara prestatii deloc
|
|
d2 = prezentare_din_payload({"vin": "WVWZZZ1JZXW000001"})
|
|
assert d2["cod_rar"] == EMPTY
|
|
|
|
# cod_prestatie explicit None
|
|
d3 = prezentare_din_payload({
|
|
"prestatii": [{"cod_prestatie": None, "cod_op_service": "OP-99"}]
|
|
})
|
|
assert d3["cod_rar"] == EMPTY
|
|
|
|
|
|
def test_operatie_ramane_denumire_sau_op():
|
|
"""operatie si cod raman neschimbate (compatibilitate cu apelantii existenti)."""
|
|
# cu ambele coduri -> operatie=denumire, cod=cod_prestatie (neschimbat)
|
|
d = prezentare_din_payload({
|
|
"prestatii": [{"cod_prestatie": "R-FRANE", "cod_op_service": "OP-1",
|
|
"denumire": "Reparatie frane"}]
|
|
})
|
|
assert d["operatie"] == "Reparatie frane"
|
|
assert d["cod"] == "R-FRANE"
|
|
|
|
# fara denumire, doar cod_op_service -> operatie=cod intern, cod=cod intern
|
|
d2 = prezentare_din_payload({
|
|
"prestatii": [{"cod_op_service": "OP-77"}]
|
|
})
|
|
assert d2["operatie"] == "OP-77"
|
|
assert d2["cod"] == "OP-77"
|
|
|
|
# cod_rar nu afecteaza cod si operatie
|
|
d3 = prezentare_din_payload({
|
|
"prestatii": [{"cod_prestatie": "oe-2", "denumire": "Verificare"}]
|
|
})
|
|
assert d3["operatie"] == "Verificare"
|
|
assert d3["cod"] == "oe-2" # cod ramas neschimbat (nu uppercase)
|
|
|
|
|
|
# --- op_service_cod + op_service_denumire distincte ---
|
|
|
|
def test_operatie_service_din_cod_op_service():
|
|
"""cod_op_service prezent -> op_service_cod contine valoarea; string gol cand lipseste."""
|
|
# cod_op_service prezent -> op_service_cod populated
|
|
d = prezentare_din_payload({
|
|
"prestatii": [{"cod_op_service": "OP-77", "denumire": "Verificare faruri"}]
|
|
})
|
|
assert d["op_service_cod"] == "OP-77"
|
|
|
|
# cod_op_service absent (vine direct cu cod_prestatie) -> op_service_cod == "" (NU EMPTY="—")
|
|
d2 = prezentare_din_payload({
|
|
"prestatii": [{"cod_prestatie": "R-FRANE", "denumire": "Reparatie frane"}]
|
|
})
|
|
assert d2["op_service_cod"] == ""
|
|
assert d2["op_service_cod"] != "—"
|
|
|
|
|
|
def test_operatie_service_din_denumire():
|
|
"""denumire prezenta cu cod_op_service -> op_service_denumire contine valoarea."""
|
|
# ambele prezente -> op_service_denumire = denumire
|
|
d = prezentare_din_payload({
|
|
"prestatii": [{"cod_op_service": "OP-77", "denumire": "Verificare faruri"}]
|
|
})
|
|
assert d["op_service_denumire"] == "Verificare faruri"
|
|
|
|
# cod_op_service prezent dar fara denumire -> op_service_denumire == ""
|
|
d2 = prezentare_din_payload({
|
|
"prestatii": [{"cod_op_service": "OP-77"}]
|
|
})
|
|
assert d2["op_service_denumire"] == ""
|
|
|
|
# cod_op_service absent + denumire prezenta -> op_service_denumire == "" (nu expune denumire RAR)
|
|
d3 = prezentare_din_payload({
|
|
"prestatii": [{"cod_prestatie": "R-FRANE", "denumire": "Reparatie frane"}]
|
|
})
|
|
assert d3["op_service_denumire"] == ""
|
|
|
|
|
|
def test_fara_operatie_service_cand_lipseste():
|
|
"""Payload fara cod_op_service -> op_service_cod si op_service_denumire sunt "" (nu "—"), fara exceptie."""
|
|
# vine direct cu cod_prestatie
|
|
d = prezentare_din_payload({
|
|
"prestatii": [{"cod_prestatie": "R-FRANE"}]
|
|
})
|
|
assert d["op_service_cod"] == ""
|
|
assert d["op_service_denumire"] == ""
|
|
assert d["op_service_cod"] != "—"
|
|
assert d["op_service_denumire"] != "—"
|
|
|
|
# fara prestatii deloc
|
|
d2 = prezentare_din_payload({"vin": "WVWZZZ1JZXW000001"})
|
|
assert d2["op_service_cod"] == ""
|
|
assert d2["op_service_denumire"] == ""
|
|
|
|
# payload None/gol
|
|
d3 = prezentare_din_payload(None)
|
|
assert d3["op_service_cod"] == ""
|
|
assert d3["op_service_denumire"] == ""
|
|
|
|
# payload JSON invalid
|
|
d4 = prezentare_din_payload("nu-e-json")
|
|
assert d4["op_service_cod"] == ""
|
|
assert d4["op_service_denumire"] == ""
|
|
|
|
|
|
def test_coduri_rar_lista_ordonata_dedup():
|
|
from app.payload_view import prezentare_din_payload
|
|
p = prezentare_din_payload({
|
|
"vin": "WVWZZZ1JZXW000111",
|
|
"prestatii": [
|
|
{"cod_prestatie": "OE-1", "cod_op_service": "A"},
|
|
{"cod_prestatie": "oe-2", "cod_op_service": "B"},
|
|
{"cod_prestatie": "OE-1", "cod_op_service": "C"}, # duplicat
|
|
{"cod_op_service": "D"}, # nemapat, fara cod
|
|
],
|
|
})
|
|
assert p["coduri_rar"] == ["OE-1", "OE-2"]
|
|
|
|
|
|
def test_coduri_rar_gol_fara_prestatii():
|
|
from app.payload_view import prezentare_din_payload
|
|
assert prezentare_din_payload({"vin": "X"})["coduri_rar"] == []
|
|
assert prezentare_din_payload(None)["coduri_rar"] == []
|