"""Teste TDD pentru POST /v1/prezentari/valideaza (dry-run, PRD 5.2 US-001).""" from __future__ import annotations import os import tempfile import pytest from fastapi.testclient import TestClient @pytest.fixture() def client(monkeypatch): tmp = tempfile.mkdtemp() monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t.db")) from app.config import get_settings get_settings.cache_clear() from app.main import app with TestClient(app) as c: yield c get_settings.cache_clear() # --- helpere --- def _prez(**over): """Prezentare valida implicita.""" p = { "vin": "WVWZZZ1KZAW000123", "nr_inmatriculare": "B999TST", "data_prestatie": "2026-06-15", "odometru_final": "123456", "prestatii": [{"cod_prestatie": "OE-1"}], } p.update(over) return p def _body_v(prezentari=None, **over): """Body pentru /valideaza — rar_credentials optional.""" if prezentari is None: prezentari = [_prez(**over)] return {"prezentari": prezentari} # --- teste --- def test_payload_valid_returneaza_queued(client): r = client.post("/v1/prezentari/valideaza", json=_body_v()) assert r.status_code == 200 res = r.json()["results"][0] assert res["valid"] is True assert res["status_estimat"] == "queued" assert res["erori"] == [] assert res["index"] == 0 def test_vin_invalid_returneaza_needs_data(client): # VIN cu O/I/Q interzisi r = client.post("/v1/prezentari/valideaza", json=_body_v(vin="WVWZZZ1OZIQ45678")) assert r.status_code == 200 res = r.json()["results"][0] assert res["status_estimat"] == "needs_data" assert res["valid"] is False fields = [e["field"] for e in res["erori"]] assert "vin" in fields def test_data_viitoare_needs_data(client): r = client.post("/v1/prezentari/valideaza", json=_body_v(data_prestatie="2099-01-01")) assert r.status_code == 200 res = r.json()["results"][0] assert res["status_estimat"] == "needs_data" assert res["valid"] is False fields = [e["field"] for e in res["erori"]] assert "data_prestatie" in fields def test_cod_op_nemapat_returneaza_needs_mapping(client): prez = _prez() prez["prestatii"] = [{"cod_op_service": "REP_MOTOR_NECUNOSCUT", "denumire": "Reparatie motor"}] r = client.post("/v1/prezentari/valideaza", json={"prezentari": [prez]}) assert r.status_code == 200 res = r.json()["results"][0] assert res["status_estimat"] == "needs_mapping" assert res["valid"] is False assert len(res["nemapate"]) == 1 assert res["nemapate"][0]["cod_op_service"] == "REP_MOTOR_NECUNOSCUT" def test_mapare_existenta_rezolva_codul(client): # Salveaza mapare op->cod r_map = client.post("/v1/mapari", json={ "cod_op_service": "REP_MOTOR", "cod_prestatie": "OE-1", "auto_send": True, }) assert r_map.status_code == 200 prez = _prez() prez["prestatii"] = [{"cod_op_service": "REP_MOTOR", "denumire": "Reparatie motor"}] r = client.post("/v1/prezentari/valideaza", json={"prezentari": [prez]}) assert r.status_code == 200 res = r.json()["results"][0] assert res["status_estimat"] == "queued" assert res["valid"] is True assert len(res["prestatii_rezolvate"]) == 1 assert res["prestatii_rezolvate"][0]["cod_prestatie"] == "OE-1" def test_fara_creds_merge(client): # rar_credentials absent -> 200 (optional in schema) r = client.post("/v1/prezentari/valideaza", json=_body_v()) assert r.status_code == 200 def test_nu_scrie_in_coada(client): # Verifica zero efecte secundare: COUNT(*) neschimbat r_before = client.get("/v1/prezentari") assert r_before.status_code == 200 nr_before = len(r_before.json()["submissions"]) client.post("/v1/prezentari/valideaza", json=_body_v()) r_after = client.get("/v1/prezentari") assert r_after.status_code == 200 nr_after = len(r_after.json()["submissions"]) assert nr_after == nr_before def test_multi_prezentari_rezultate_per_index(client): prezentari = [ _prez(), # valid -> queued _prez(vin="WVWZZZ1OZIQ45678"), # VIN invalid -> needs_data ] r = client.post("/v1/prezentari/valideaza", json={"prezentari": prezentari}) assert r.status_code == 200 results = r.json()["results"] assert len(results) == 2 # index corect per pozitie assert results[0]["index"] == 0 assert results[1]["index"] == 1 # statusuri diferite assert results[0]["status_estimat"] == "queued" assert results[1]["status_estimat"] == "needs_data" def test_shape_invalid_422(client): # PrestatieItem fara cod_prestatie si fara cod_op_service -> 422 de shape Pydantic prez = _prez() prez["prestatii"] = [{"denumire": "ceva"}] # lipseste cod_prestatie si cod_op_service r = client.post("/v1/prezentari/valideaza", json={"prezentari": [prez]}) assert r.status_code == 422 # Handlerul global dropeaza input/ctx — fara echo parola (desi creds lipseste, testam structura) body = r.json() for err in body.get("detail", []): assert "input" not in err assert "ctx" not in err # --------------------------------------------------------------------------- # # US-003: 3 niveluri in raspunsul /valideaza # # --------------------------------------------------------------------------- # def test_erori_au_3niveluri(client): """/valideaza cu VIN invalid -> erori[i] au cod/problema/cauza/fix (pass-through US-002).""" r = client.post("/v1/prezentari/valideaza", json=_body_v(vin="WVWZZZ1OZIQ45678")) assert r.status_code == 200 res = r.json()["results"][0] assert res["status_estimat"] == "needs_data" erori = res["erori"] assert len(erori) >= 1 for e in erori: assert "cod" in e, f"lipseste 'cod' in {e}" assert "problema" in e, f"lipseste 'problema' in {e}" assert "cauza" in e, f"lipseste 'cauza' in {e}" assert "fix" in e, f"lipseste 'fix' in {e}" def test_nemapate_au_3niveluri(client): """/valideaza cu cod_op nemapat -> nemapate[i] au cod_op_service+denumire PASTRATE + cod==COD_NEMAPAT + cele 3 niveluri.""" prez = _prez() prez["prestatii"] = [{"cod_op_service": "OP_TEST_NEMAPAT", "denumire": "Operatie test"}] r = client.post("/v1/prezentari/valideaza", json={"prezentari": [prez]}) assert r.status_code == 200 res = r.json()["results"][0] assert res["status_estimat"] == "needs_mapping" nemapate = res["nemapate"] assert len(nemapate) == 1 n = nemapate[0] # Campuri originale pastrate assert n["cod_op_service"] == "OP_TEST_NEMAPAT" assert n["denumire"] == "Operatie test" # 3 niveluri adaugate assert n["cod"] == "COD_NEMAPAT" assert n["problema"] assert n["cauza"] assert n["fix"]