Acoperire 49 tests offline (fără Oracle real): test_comanda_helpers (16): _build_pc_nr toate prefixele VFP + fallback, _build_sir_id_operatii csv + limit 4000 chars, _PREFIX_MAP regression. test_router_authorization (9): _company_id fallback JWT companies[0], 403 firmă neautorizată, 400 companies[] gol, string→int coercion; _server_id extragere din request.state. test_lookup_endpoints (15): cache hit/miss per schema pentru tip_deviz, masini, asiguratori, inspectori (per-asig), operatii; LIKE escape %/_/\; min 2 chars short-circuit; server_id propagat la get_connection. test_partener_create (9): 5 Pydantic validation (denumire min 2, id_firma ge 1, cui opțional), 4 service mocked (happy path, 409 duplicat CUI, fără CUI, lipsă GRANT → 500 log.critical). Pattern mock Oracle: fake context managers (async get_connection + sync cursor), monkeypatch pe lookup_service.get_schema (not _context, din cauza binding copy la import). Rulare: pytest backend/modules/service_auto/tests/ -q → 62 passed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
90 lines
2.8 KiB
Python
90 lines
2.8 KiB
Python
"""
|
|
Unit tests pentru _company_id() și _server_id() din routers/comanda.py.
|
|
|
|
Acoperă izolarea multi-tenant:
|
|
- fallback la JWT companies[0] când nu e specificat id_firma
|
|
- 403 dacă id_firma nu e în JWT companies[]
|
|
- 400 dacă JWT nu are nicio firmă
|
|
- extragere server_id din request.state
|
|
"""
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
|
|
from backend.modules.service_auto.routers.comanda import _company_id, _server_id
|
|
|
|
|
|
def _user(companies, username="MARIUS M", user_id=1):
|
|
"""Construiește un CurrentUser minimal pentru teste (duck typing)."""
|
|
return SimpleNamespace(
|
|
username=username,
|
|
user_id=user_id,
|
|
companies=companies,
|
|
permissions=["read", "write"],
|
|
)
|
|
|
|
|
|
# ---- _company_id ----
|
|
|
|
def test_company_id_explicit_in_allowed_list_passes():
|
|
"""id_firma explicit + în JWT → OK."""
|
|
user = _user(["110", "167", "169"])
|
|
assert _company_id(user, 167) == 167
|
|
|
|
|
|
def test_company_id_explicit_not_in_allowed_raises_403():
|
|
"""id_firma explicit NU în JWT → 403."""
|
|
user = _user(["110", "167"])
|
|
with pytest.raises(HTTPException) as exc:
|
|
_company_id(user, 999)
|
|
assert exc.value.status_code == 403
|
|
assert "neautorizat" in exc.value.detail.lower()
|
|
|
|
|
|
def test_company_id_none_falls_back_to_first_company():
|
|
"""Fără id_firma → prima firmă din JWT companies[]."""
|
|
user = _user(["167", "110", "169"])
|
|
assert _company_id(user, None) == 167
|
|
|
|
|
|
def test_company_id_empty_companies_raises_400():
|
|
"""JWT fără companies[] → 400 (nu putem alege firmă implicită)."""
|
|
user = _user([])
|
|
with pytest.raises(HTTPException) as exc:
|
|
_company_id(user, None)
|
|
assert exc.value.status_code == 400
|
|
|
|
|
|
def test_company_id_string_companies_converted_to_int():
|
|
"""JWT stochează companies[] ca list[str]; comparația se face pe int."""
|
|
user = _user(["110", "167", "169"])
|
|
# comparație cu int funcționează
|
|
assert _company_id(user, 110) == 110
|
|
|
|
|
|
def test_company_id_accepts_string_id_from_first_company():
|
|
"""Prima firmă e string în JWT → e convertită corect la int."""
|
|
user = _user(["42"])
|
|
assert _company_id(user, None) == 42
|
|
|
|
|
|
# ---- _server_id ----
|
|
|
|
def test_server_id_from_request_state():
|
|
"""Extragere server_id injectat de AuthenticationMiddleware."""
|
|
request = SimpleNamespace(state=SimpleNamespace(server_id="mariusm_test"))
|
|
assert _server_id(request) == "mariusm_test"
|
|
|
|
|
|
def test_server_id_none_when_missing():
|
|
"""request.state fără server_id → None (pool folosește primul server)."""
|
|
request = SimpleNamespace(state=SimpleNamespace())
|
|
assert _server_id(request) is None
|
|
|
|
|
|
def test_server_id_none_when_explicit_none():
|
|
"""server_id explicit None în state → None."""
|
|
request = SimpleNamespace(state=SimpleNamespace(server_id=None))
|
|
assert _server_id(request) is None
|