Files
rar-autopass/tests/test_web_mapcoloane.py
Claude Agent b26dbb79e1 feat(5.12): modal editare + cont obligatoriu la import; design.md + PRD 5.13 revizuit (/autoplan)
5.12 (livrat): editare in modal a randurilor de preview, cont obligatoriu inainte de
import, formular editare extras (_form_editare, _editare_preview_modal), plus suita de
teste aferenta (preview edit/compact, mapare op, form editare, signup, admin panel).

Design + planificare:
- docs/design.md: sistem de design (tokeni, breakpoints, scara control, componente, a11y).
- docs/prd/prd-5.12-* si prd-5.13-* (5.13 cu raport /autoplan: CEO+Design+Eng, audit trail).

Curatare: sterse PNG-urile de test/mockup temporare din radacina.

Nota: implementarea CSS 5.13 (responsive compact + sistem butoane) NU e inca facuta —
planul revizuit cere refactorul testelor fragile din test_web_responsive.py INAINTE de CSS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 18:52:20 +00:00

166 lines
6.4 KiB
Python

"""Teste US-003 — pasul „Potriveste coloanele" arata antet + prima inregistrare.
Acceptance criteria:
- Deasupra/langa randurile de mapare, un mic tabel orizontal:
cap de tabel = numele coloanelor din fisier,
rand = valorile primei inregistrari (truncate; `title` pe valoarea integrala).
- Foloseste .tablewrap pentru scroll orizontal pe mobil.
- Fiecare coloana din cap ramane asociata vizual cu select-ul ei de mapare.
- Fisier fara randuri de date -> doar capul de tabel + mesaj explicit
„antet fara randuri de date" (D#11) + butonul „Continua" dezactivat.
"""
from __future__ import annotations
import io
import os
import tempfile
import pytest
@pytest.fixture()
def client(monkeypatch):
tmp = tempfile.mkdtemp()
monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t.db"))
monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "false")
from app.config import get_settings
get_settings.cache_clear()
from app.main import app
from fastapi.testclient import TestClient
with TestClient(app) as c:
yield c
get_settings.cache_clear()
def _make_xlsx_bytes(rows: list[dict]) -> bytes:
"""Construieste un xlsx minimal cu openpyxl."""
openpyxl = pytest.importorskip("openpyxl")
wb = openpyxl.Workbook()
ws = wb.active
if not rows:
return b""
headers = list(rows[0].keys())
ws.append(headers)
for row in rows:
ws.append([row.get(h) for h in headers])
buf = io.BytesIO()
wb.save(buf)
return buf.getvalue()
def _make_xlsx_only_header(headers: list[str]) -> bytes:
"""Construieste un xlsx cu doar antet (fara randuri de date)."""
openpyxl = pytest.importorskip("openpyxl")
wb = openpyxl.Workbook()
ws = wb.active
ws.append(headers)
buf = io.BytesIO()
wb.save(buf)
return buf.getvalue()
_COLOANE = ["VIN", "Nr inmatriculare", "Data prestatie", "Odometru final", "Operatie"]
_SAMPLE_ROWS = [
{
"VIN": "WVWZZZ1KZAW000123",
"Nr inmatriculare": "B001TST",
"Data prestatie": "15.06.2026",
"Odometru final": "123456",
"Operatie": "Revizie",
},
{
"VIN": "WVWZZZ1KZAW000456",
"Nr inmatriculare": "B002TST",
"Data prestatie": "16.06.2026",
"Odometru final": "200000",
"Operatie": "Revizie",
},
]
def _upload_csv_and_get_mapare(client, rows=None, headers=None) -> tuple[int, str]:
"""Incarca un xlsx si intoarce (import_id, html_text) din pasul de mapare coloane."""
if headers is not None:
# Fisier cu doar antet
xlsx = _make_xlsx_only_header(headers)
else:
xlsx = _make_xlsx_bytes(rows or _SAMPLE_ROWS)
r = client.post(
"/_import/upload",
files={"file": ("test.xlsx", xlsx, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")},
)
return r.status_code, r.text
# --------------------------------------------------------------------------- #
# test_mapcoloane_arata_cap_tabel_coloane #
# --------------------------------------------------------------------------- #
def test_mapcoloane_arata_cap_tabel_coloane(client):
"""Pasul de mapare coloane afiseaza un tabel orizontal cu antetul fisierului.
Fiecare coloana din fisier trebuie sa apara ca <th> in capul tabelului.
Tabelul trebuie inconjurat de .tablewrap pentru scroll orizontal.
"""
status, html = _upload_csv_and_get_mapare(client)
assert status == 200
# Tabelul de preview al antetului trebuie sa fie prezent
assert "tablewrap" in html, "Trebuie .tablewrap pentru scroll orizontal"
# Fiecare coloana din fisier trebuie sa apara ca <th> in tabel
for col in _COLOANE:
assert f"<th" in html, "Trebuie elemente <th> in capul tabelului"
assert col in html, f"Coloana '{col}' trebuie sa apara in antetul tabelului"
# Tabelul de preview (cu class sau id distinct pentru antet preview)
assert "preview-antet" in html, "Tabelul de preview trebuie sa aiba class/id 'preview-antet'"
# --------------------------------------------------------------------------- #
# test_mapcoloane_arata_valori_prima_inregistrare #
# --------------------------------------------------------------------------- #
def test_mapcoloane_arata_valori_prima_inregistrare(client):
"""Pasul de mapare coloane afiseaza valorile primei inregistrari din fisier.
Valorile din primul rand de date trebuie sa apara in tabel.
"""
status, html = _upload_csv_and_get_mapare(client, rows=_SAMPLE_ROWS)
assert status == 200
# Valorile primei inregistrari trebuie sa apara
assert "WVWZZZ1KZAW000123" in html, "VIN-ul primei inregistrari trebuie sa apara"
assert "B001TST" in html, "Nr inmatriculare al primei inregistrari trebuie sa apara"
assert "15.06.2026" in html, "Data prestatiei primei inregistrari trebuie sa apara"
assert "123456" in html, "Odometrul primei inregistrari trebuie sa apara"
# Valorile celui de-al doilea rand NU trebuie sa apara ca rand de date (numai primul rand)
# (Nota: pot aparea ca exemple in alt context, dar randul de date e primul)
# --------------------------------------------------------------------------- #
# test_mapcoloane_fara_randuri_degradeaza #
# --------------------------------------------------------------------------- #
def test_mapcoloane_fara_randuri_degradeaza(client):
"""Fisier xlsx cu antet dar fara randuri de date → degradare grijulie.
Trebuie sa:
- Nu crape (status 200)
- Arate capul de tabel cu coloanele
- Arate mesajul explicit 'antet fara randuri de date'
- Dezactiveze butonul 'Salveaza si continua' (disabled)
"""
status, html = _upload_csv_and_get_mapare(client, headers=_COLOANE)
assert status == 200, f"Status neasteptat: {status}"
# Nu trebuie sa crape — formular de mapare afisat
assert "Mapare coloane" in html, "Formularul de mapare trebuie afisat"
# Capul de tabel cu coloanele trebuie afisat
for col in _COLOANE:
assert col in html, f"Coloana '{col}' trebuie sa apara in antet chiar si fara date"
# Mesaj explicit despre lipsa datelor
assert "antet fara randuri de date" in html.lower() or "fara randuri de date" in html.lower(), \
"Trebuie mesaj explicit despre lipsa randurilor de date"
# Butonul Continua trebuie dezactivat
assert "disabled" in html, "Butonul 'Salveaza si continua' trebuie dezactivat cand nu sunt randuri"