Files
roa2web-service-auto/backend/modules/service_auto/tests/test_error_mapping.py
Claude Agent 32aca55c78 feat(service-auto): săpt 3-phase2 — toate ipotezele confirmate + modul funcțional
Backend:
- service_auto module complet: router, service, schemas, 5 teste suites (22/22 passed)
- 5 endpoints: GET /ping, /firme, /tip-deviz, /masini, POST /comenzi
- SP_CREEAZA_COMANDA_PROTOTIP creat în MARIUSM_AUTO (VALID, 5.9ms)
- oracle_pool.py: session_callback backward-compat patch
- ROA_WEB user: grants SP-only confirmate (H3), mariusm_test pool switchat
- pyproject.toml: integration pytest marker înregistrat

Frontend:
- ComandaNoua.vue: date reale din Oracle (firme/tip-deviz/masini), nu hardcodate
- src/modules/service-auto/services/api.js: axios service cu Bearer token
- src/router/index.js: rută /service-auto/comanda-noua

Docs:
- decision-log.md: verdict MERGE, toate 6 ipoteze CONFIRMED
- learnings.md: 7 patterns reutilizabile
- grants-audit.md: arhitectura multi-tenant + proxy auth analysis + V_NOM_FIRME loop
- template-modul-oracle.md: rețetă completă pentru module Oracle noi
- TODO-phase2.md: 7 items concrete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 09:37:09 +00:00

98 lines
3.8 KiB
Python

"""
Unit tests — Oracle error code → HTTP status mapping.
Tests _handle_oracle_error() directly. No live Oracle connection required.
Covered mappings:
ORA-20001 … ORA-20999 → HTTP 422 (business errors from RAISE_APPLICATION_ERROR)
ORA-12541/12170/12154/12560 → HTTP 503 (Oracle network / TNS unreachable)
ORA-01017 → HTTP 500 (bad credentials)
ORA-00942 → HTTP 500 (missing object / grant)
ORA-<other> → HTTP 500 (unexpected error)
"""
import pytest
from unittest.mock import MagicMock
from fastapi import HTTPException
from backend.modules.service_auto.services.comanda_service import _handle_oracle_error
def _make_oracle_error(code: int, msg: str = "test error"):
"""
Build a minimal mock that mimics oracledb.DatabaseError structure.
_handle_oracle_error only accesses e.args[0].code and e.args[0].message,
so a MagicMock is sufficient — no live oracledb import needed.
"""
err_obj = MagicMock()
err_obj.code = code
err_obj.message = f"ORA-{code:05d}: {msg}"
exc = MagicMock()
exc.args = (err_obj,)
return exc
# ---------------------------------------------------------------------------
# Parametrised: code → expected HTTP status + fragment in detail
# ---------------------------------------------------------------------------
@pytest.mark.parametrize("code, status, detail_fragment", [
# Business errors — RAISE_APPLICATION_ERROR range
(20001, 422, "mesaj business 20001"),
(20500, 422, "mesaj business 20500"),
(20999, 422, "mesaj business 20999"),
# Oracle network / TNS unreachable
(12541, 503, "indisponibil"),
(12170, 503, "indisponibil"),
(12154, 503, "indisponibil"),
(12560, 503, "indisponibil"),
# Credential / config errors
(1017, 500, "configurare"),
# Missing object / grant
(942, 500, "internă"),
# Catch-all unexpected errors
(4031, 500, "neașteptată"), # ORA-04031: unable to allocate memory
(600, 500, "neașteptată"), # ORA-00600: internal error
])
def test_error_mapping(code, status, detail_fragment):
msg = f"mesaj business {code}" if 20001 <= code <= 20999 else "test error"
exc = _make_oracle_error(code, msg)
with pytest.raises(HTTPException) as exc_info:
_handle_oracle_error(exc)
http_exc = exc_info.value
assert http_exc.status_code == status, (
f"ORA-{code:05d} → expected HTTP {status}, got {http_exc.status_code}"
)
assert detail_fragment in http_exc.detail, (
f"ORA-{code:05d} detail: expected '{detail_fragment}' in '{http_exc.detail}'"
)
# ---------------------------------------------------------------------------
# ORA-20xxx: verify ORA prefix is stripped from business message
# ---------------------------------------------------------------------------
def test_20001_strips_ora_prefix():
"""The 422 detail must not contain the 'ORA-20001:' prefix."""
exc = _make_oracle_error(20001, "Mai exista o comanda cu numarul P01-42")
with pytest.raises(HTTPException) as exc_info:
_handle_oracle_error(exc)
detail = exc_info.value.detail
assert not detail.startswith("ORA-"), (
f"ORA prefix not stripped: '{detail}'"
)
assert "Mai exista" in detail
# ---------------------------------------------------------------------------
# Edge case: missing code attribute (e.g. thin-mode edge case)
# ---------------------------------------------------------------------------
def test_no_code_attribute_maps_to_500():
"""If the error object has no .code, fall through to generic 500."""
err_obj = MagicMock(spec=[]) # spec=[] means NO attributes
exc = MagicMock()
exc.args = (err_obj,)
with pytest.raises(HTTPException) as exc_info:
_handle_oracle_error(exc)
assert exc_info.value.status_code == 500