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>
110 lines
3.7 KiB
Python
110 lines
3.7 KiB
Python
"""
|
|
Integration test — Hypothesis #4: diacritice encoding end-to-end.
|
|
|
|
Verifies that RAISE_APPLICATION_ERROR(-20001, 'mesaj cu ă î ș ț â') flows correctly
|
|
through the full chain: Oracle → oracledb → _handle_oracle_error → HTTPException.detail
|
|
|
|
Two layers tested:
|
|
L1 (live Oracle) — PL/SQL anonymous block raises ORA-20001 with diacritice;
|
|
oracledb.DatabaseError.args[0].message must contain them intact.
|
|
L2 (_handle_oracle_error) — the HTTPException.detail must contain diacritice,
|
|
ORA prefix stripped.
|
|
|
|
No HTTP server needed. Requires live Oracle connection (mariusm_test pool credentials).
|
|
|
|
Run:
|
|
cd /workspace/roa2web
|
|
python -m pytest backend/modules/service_auto/tests/test_diacritice_encoding.py -v -m integration
|
|
"""
|
|
import os
|
|
import sys
|
|
import pytest
|
|
import oracledb
|
|
from fastapi import HTTPException
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
|
|
|
|
from backend.modules.service_auto.services.comanda_service import _handle_oracle_error
|
|
|
|
HOST = "10.0.20.121"
|
|
PORT = 1521
|
|
SERVICE_NAME = "ROA"
|
|
SECRETS_FILE = os.path.join(
|
|
os.path.dirname(__file__), '..', '..', '..', 'secrets', 'mariusm_test.oracle_pass'
|
|
)
|
|
USER = "ROA_WEB"
|
|
|
|
# Romanian diacritice in error message — full set
|
|
DIACRITICE_MSG = "Client invalid: ă î ș ț â Ă Î Ș Ț Â"
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def oracle_conn():
|
|
"""Live connection as ROA_WEB for the duration of this test module."""
|
|
with open(SECRETS_FILE) as f:
|
|
pwd = f.read().strip()
|
|
conn = oracledb.connect(user=USER, password=pwd, host=HOST, port=PORT, service_name=SERVICE_NAME)
|
|
yield conn
|
|
conn.close()
|
|
|
|
|
|
@pytest.mark.integration
|
|
def test_l1_oracle_encodes_diacritice_in_raise_application_error(oracle_conn):
|
|
"""
|
|
L1: Oracle sends diacritice in RAISE_APPLICATION_ERROR message.
|
|
oracledb decodes them correctly through the NLS chain.
|
|
"""
|
|
raised = None
|
|
with oracle_conn.cursor() as cur:
|
|
try:
|
|
cur.execute(
|
|
f"BEGIN RAISE_APPLICATION_ERROR(-20001, :msg); END;",
|
|
{"msg": DIACRITICE_MSG},
|
|
)
|
|
except oracledb.DatabaseError as e:
|
|
raised = e
|
|
|
|
assert raised is not None, "Expected ORA-20001 to be raised"
|
|
err = raised.args[0]
|
|
assert err.code == 20001, f"Expected code 20001, got {err.code}"
|
|
|
|
# Every Romanian diacritic character must survive the Oracle → Python round-trip
|
|
for char in "ăîșțâĂÎȘȚÂ":
|
|
assert char in err.message, (
|
|
f"Diacritic '{char}' lost in Oracle→oracledb encoding. "
|
|
f"Full message: {err.message!r}"
|
|
)
|
|
|
|
|
|
@pytest.mark.integration
|
|
def test_l2_handle_oracle_error_preserves_diacritice_in_http_detail(oracle_conn):
|
|
"""
|
|
L2: _handle_oracle_error strips ORA prefix and passes diacritice into HTTPException.detail.
|
|
"""
|
|
raised_db = None
|
|
with oracle_conn.cursor() as cur:
|
|
try:
|
|
cur.execute(
|
|
"BEGIN RAISE_APPLICATION_ERROR(-20001, :msg); END;",
|
|
{"msg": DIACRITICE_MSG},
|
|
)
|
|
except oracledb.DatabaseError as e:
|
|
raised_db = e
|
|
|
|
assert raised_db is not None
|
|
|
|
# Pass through the same handler used in production
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
_handle_oracle_error(raised_db)
|
|
|
|
http_exc = exc_info.value
|
|
assert http_exc.status_code == 422
|
|
assert not http_exc.detail.startswith("ORA-"), (
|
|
f"ORA prefix not stripped from detail: {http_exc.detail!r}"
|
|
)
|
|
for char in "ăîșțâĂÎȘȚÂ":
|
|
assert char in http_exc.detail, (
|
|
f"Diacritic '{char}' lost in _handle_oracle_error. "
|
|
f"detail: {http_exc.detail!r}"
|
|
)
|