mirror of
https://github.com/hoshikawa2/compass_backoffice.git
synced 2026-07-09 22:04:20 +00:00
first commit
This commit is contained in:
141
tests_original_develop/unit/test_anatel_validation.py
Normal file
141
tests_original_develop/unit/test_anatel_validation.py
Normal file
@@ -0,0 +1,141 @@
|
||||
import pytest
|
||||
from src.api.schemas.anatel_schemas import (
|
||||
TicketRequestEvent, ReasonCode, ERROR_CODE_MAPPING,
|
||||
Customer, Address, Subscriber, Complaint, Origin, SubmittedBy
|
||||
)
|
||||
from src.agent.logic.validation import validate_required_fields
|
||||
from datetime import datetime
|
||||
|
||||
# ---- Fixture compartilhada ----------------------------------------
|
||||
|
||||
@pytest.fixture
|
||||
def valid_ticket_payload():
|
||||
"""Retorna um payload compatível com TicketRequestEvent (Swagger v0.0.5)"""
|
||||
return {
|
||||
"caseType": "anatel",
|
||||
"origin": {
|
||||
"sourceSystem": "test",
|
||||
"submittedBy": {"userId": "u1", "name": "n1"}
|
||||
},
|
||||
"ticketId": "DS-98765",
|
||||
"transactionId": "trans-123",
|
||||
"customer": {
|
||||
"cpfCnpj": "12345678901",
|
||||
"phones": ["+5511999999999"],
|
||||
"msisdn": "5511999999999",
|
||||
"name": "Cliente Exemplo",
|
||||
"odcCustomer": False,
|
||||
"contumazCustomer": False,
|
||||
"address": {
|
||||
"cep": "01001-000",
|
||||
"street": "Praca da Se",
|
||||
"neighborhood": "Se",
|
||||
"city": "Sao Paulo",
|
||||
"state": "SP"
|
||||
},
|
||||
"subscriber": {
|
||||
"cpfCnpj": "12345678901",
|
||||
"subscriberName": "Parente do Cliente"
|
||||
}
|
||||
},
|
||||
"complaint": {
|
||||
"complaintProtocol": "202603270001",
|
||||
"actionType": "nova",
|
||||
"inputChannel": "Anatel",
|
||||
"service": "S",
|
||||
"firstService": "FS",
|
||||
"modality": "M",
|
||||
"motive": "M",
|
||||
"description": "Descricao da reclamacao",
|
||||
"openedAt": datetime.now()
|
||||
}
|
||||
}
|
||||
|
||||
# ---- Testes de caminho feliz (happy path) --------------------------
|
||||
|
||||
def test_validate_valid_ticket(valid_ticket_payload):
|
||||
"""Valida um ticket 100% preenchido conforme o novo contrato."""
|
||||
ticket = TicketRequestEvent(**valid_ticket_payload)
|
||||
result = validate_required_fields(ticket)
|
||||
assert result.is_valid is True
|
||||
|
||||
# ---- Testes de cobertura total de ReasonCodes (Exaustivo) -----------
|
||||
|
||||
@pytest.mark.parametrize("loc_tuple, mapping_val", ERROR_CODE_MAPPING.items())
|
||||
def test_exhaustive_reason_code_coverage(valid_ticket_payload, loc_tuple, mapping_val):
|
||||
"""
|
||||
Testa cada entrada do ERROR_CODE_MAPPING removendo o campo correspondente
|
||||
e verificando se o validate_required_fields retorna o ReasonCode e a mensagem esperados.
|
||||
"""
|
||||
reason_code, expected_text = mapping_val
|
||||
|
||||
# Navega no dicionário para remover o campo
|
||||
data_ptr = valid_ticket_payload
|
||||
for part in loc_tuple[:-1]:
|
||||
data_ptr = data_ptr[part]
|
||||
|
||||
# Remove ou limpa o campo
|
||||
field_to_clear = loc_tuple[-1]
|
||||
data_ptr[field_to_clear] = "" if isinstance(data_ptr[field_to_clear], str) else None
|
||||
|
||||
# Reconstrói os modelos aninhados usando model_construct para evitar o Pydantic
|
||||
# mas permitir acesso por atributo (.) na lógica de validação manual
|
||||
address = Address.model_construct(**valid_ticket_payload["customer"]["address"])
|
||||
|
||||
cust_data = valid_ticket_payload["customer"].copy()
|
||||
cust_data.pop("address", None)
|
||||
cust_data.pop("subscriber", None)
|
||||
|
||||
sub_data = valid_ticket_payload["customer"]["subscriber"].copy()
|
||||
subscriber = Subscriber.model_construct(**sub_data)
|
||||
|
||||
customer = Customer.model_construct(
|
||||
address=address,
|
||||
subscriber=subscriber,
|
||||
**cust_data
|
||||
)
|
||||
|
||||
comp_data = valid_ticket_payload["complaint"].copy()
|
||||
complaint = Complaint.model_construct(**comp_data)
|
||||
|
||||
orig_data = valid_ticket_payload["origin"].copy()
|
||||
sub_by_data = orig_data.pop("submittedBy", {})
|
||||
sub_by = SubmittedBy.model_construct(**sub_by_data)
|
||||
origin = Origin.model_construct(
|
||||
submittedBy=sub_by,
|
||||
**orig_data
|
||||
)
|
||||
|
||||
top_data = valid_ticket_payload.copy()
|
||||
top_data.pop("customer", None)
|
||||
top_data.pop("complaint", None)
|
||||
top_data.pop("origin", None)
|
||||
|
||||
ticket = TicketRequestEvent.model_construct(
|
||||
customer=customer,
|
||||
complaint=complaint,
|
||||
origin=origin,
|
||||
**top_data
|
||||
)
|
||||
|
||||
result = validate_required_fields(ticket)
|
||||
|
||||
assert result.is_valid is False
|
||||
codes = [m["code"] for m in result.error_response["detail"]["messages"]]
|
||||
texts = [m["text"] for m in result.error_response["detail"]["messages"]]
|
||||
|
||||
assert reason_code.value in codes
|
||||
assert expected_text in texts
|
||||
|
||||
def test_validate_error_response_format(valid_ticket_payload):
|
||||
"""Verifica se o formato do erro segue o padrão Swagger (title, status, detail)."""
|
||||
valid_ticket_payload["complaint"]["motive"] = ""
|
||||
ticket = TicketRequestEvent(**valid_ticket_payload)
|
||||
result = validate_required_fields(ticket)
|
||||
assert result.is_valid is False
|
||||
# Verificando formato fixo exigido pela TIM/Swagger
|
||||
assert result.error_response["title"] == "validation error"
|
||||
assert result.error_response["status"] == 400
|
||||
assert "detail" in result.error_response
|
||||
assert "messages" in result.error_response["detail"]
|
||||
assert isinstance(result.error_response["detail"]["messages"], list)
|
||||
Reference in New Issue
Block a user