- app/validation.py: reguli de continut (VIN ^[A-HJ-NPR-Z0-9]{17}$ fara O/I/Q,
nrInm ^[A-Z0-9]{1,10}$, dataPrestatie ∈ [2024-12-01, azi] TZ Bucuresti,
R-ODO/I-ODO -> odometruInitial obligatoriu, odometruInitial<=odometruFinal,
odometruFinal numeric, prestatii nevide, b64Image base64 valid)
- erori structurate {field, message} (aceeasi forma ca raspunsul RAR), fara exceptii
- modele Pydantic: normalizare strip/upper pe vin/nrInm/coduri
- router /v1/prezentari: validare inainte de enqueue; esec continut -> needs_data
(tinut, vizibil in dashboard cu motiv), NU 422; JSON malformat -> 422 (shape)
- tests/: 29 teste (per regula + rutare API + idempotenta)
Verify: pytest 29 passed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
"""Teste API /v1/prezentari — rutare validare (T3) + idempotenta."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import tempfile
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
@pytest.fixture()
|
|
def client(monkeypatch):
|
|
# DB temporara izolata per test.
|
|
tmp = tempfile.mkdtemp()
|
|
monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t.db"))
|
|
from app.config import get_settings
|
|
get_settings.cache_clear() # reincarca settings cu noul env
|
|
from app.main import app
|
|
with TestClient(app) as c:
|
|
yield c
|
|
get_settings.cache_clear()
|
|
|
|
|
|
def _body(**over):
|
|
prez = {
|
|
"vin": "WVWZZZ1KZAW000123",
|
|
"nr_inmatriculare": "B999TST",
|
|
"data_prestatie": "2026-06-15",
|
|
"odometru_final": "123456",
|
|
"prestatii": [{"cod_prestatie": "OE-1"}],
|
|
}
|
|
prez.update(over)
|
|
return {"rar_credentials": {"email": "x@y.ro", "password": "s"}, "prezentari": [prez]}
|
|
|
|
|
|
def test_prezentare_valida_queued(client):
|
|
r = client.post("/v1/prezentari", json=_body())
|
|
assert r.status_code == 200
|
|
assert r.json()["results"][0]["status"] == "queued"
|
|
|
|
|
|
def test_vin_invalid_needs_data(client):
|
|
r = client.post("/v1/prezentari", json=_body(vin="WVWZZZ1OZIQ45678"))
|
|
assert r.status_code == 200
|
|
sid = r.json()["results"][0]
|
|
assert sid["status"] == "needs_data"
|
|
|
|
|
|
def test_data_viitoare_needs_data(client):
|
|
r = client.post("/v1/prezentari", json=_body(data_prestatie="2099-01-01"))
|
|
assert r.json()["results"][0]["status"] == "needs_data"
|
|
|
|
|
|
def test_idempotenta_dedup(client):
|
|
b = _body()
|
|
r1 = client.post("/v1/prezentari", json=b)
|
|
r2 = client.post("/v1/prezentari", json=b)
|
|
id1 = r1.json()["results"][0]["submission_id"]
|
|
res2 = r2.json()["results"][0]
|
|
assert res2["submission_id"] == id1
|
|
assert res2["deduped"] is True
|
|
|
|
|
|
def test_json_malformat_422(client):
|
|
# Lipseste vin -> validare de shape Pydantic -> 422 (NU needs_data).
|
|
bad = {"rar_credentials": {"email": "x", "password": "y"},
|
|
"prezentari": [{"nr_inmatriculare": "B1", "data_prestatie": "2026-06-15",
|
|
"odometru_final": "1", "prestatii": [{"cod_prestatie": "OE-1"}]}]}
|
|
r = client.post("/v1/prezentari", json=bad)
|
|
assert r.status_code == 422
|