import asyncio import os import sys from pathlib import Path from typing import Any, Dict, List import pytest from fastapi import HTTPException pytest.importorskip("email_validator") PROJECT_ROOT = Path(__file__).resolve().parents[1] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) os.environ.setdefault("APPWRITE_ENDPOINT", "http://localhost/v1") os.environ.setdefault("APPWRITE_PROJECT_ID", "test-project") os.environ.setdefault("APPWRITE_API_KEY", "test-key") os.environ.setdefault("APPWRITE_DATABASE_ID", "test-db") os.environ.setdefault("APPWRITE_COLLECTION_EMPRESAS_ID", "test-companies") os.environ.setdefault("APPWRITE_COLLECTION_EMPRESAS_DADOS_ID", "test-companies-data") os.environ.setdefault("APPWRITE_COLLECTION_ENDERECOS_ID", "test-addresses") from appwrite.exception import AppwriteException from src.modules.empresas.schemas import EmpresaCreate, EmpresaUpdate from src.modules.empresas.service import EmpresasService class _SyncEmpresasService(EmpresasService): async def _run(self, func: Any, *args: Any, **kwargs: Any) -> Any: # pragma: no cover - helper override return func(*args, **kwargs) class _DummyDatabases: def __init__(self, *, existing_enderecos: List[str]) -> None: self._existing_enderecos = set(existing_enderecos) self.created_payloads: List[Dict[str, Any]] = [] self.updated_payloads: List[Dict[str, Any]] = [] self.endereco_lookups: List[str] = [] def get_document(self, database_id: str, collection_id: str, document_id: str) -> Dict[str, Any]: if collection_id != "test-addresses": # pragma: no cover - defensive raise AssertionError("Unexpected collection lookup during tests") self.endereco_lookups.append(document_id) if document_id not in self._existing_enderecos: raise AppwriteException("Not found", 404) return {"$id": document_id} def create_document( self, database_id: str, collection_id: str, document_id: str, data: Dict[str, Any], ) -> Dict[str, Any]: self.created_payloads.append(data) return { "$id": "emp_1", "cnpj": data.get("cnpj"), "enderecos": data.get("enderecos"), "$createdAt": "2024-01-01T00:00:00Z", "$updatedAt": "2024-01-01T00:00:00Z", } def update_document( self, database_id: str, collection_id: str, document_id: str, data: Dict[str, Any], ) -> Dict[str, Any]: self.updated_payloads.append(data) return { "$id": document_id, "cnpj": "27865757000102", "enderecos": data.get("enderecos"), "$createdAt": "2024-01-01T00:00:00Z", "$updatedAt": "2024-01-02T00:00:00Z", } def test_create_empresa_validates_and_normalizes_enderecos() -> None: databases = _DummyDatabases(existing_enderecos=["addr_1"]) service = _SyncEmpresasService(databases, "test-db", "test-companies-data", "test-addresses") payload = EmpresaCreate(cnpj="27865757000102", enderecos=["addr_1", "addr_1 "]) result = asyncio.run(service.create(payload)) assert databases.endereco_lookups == ["addr_1"] assert databases.created_payloads[0]["enderecos"] == ["addr_1"] assert result.enderecos == ["addr_1"] def test_create_empresa_accepts_single_endereco_id_alias() -> None: databases = _DummyDatabases(existing_enderecos=["addr_1"]) service = _SyncEmpresasService(databases, "test-db", "test-companies-data", "test-addresses") payload = EmpresaCreate(cnpj="27865757000102", enderecos="addr_1") result = asyncio.run(service.create(payload)) assert databases.created_payloads[0]["enderecos"] == ["addr_1"] assert result.enderecos == ["addr_1"] def test_create_empresa_raises_when_endereco_missing() -> None: databases = _DummyDatabases(existing_enderecos=[]) service = _SyncEmpresasService(databases, "test-db", "test-companies-data", "test-addresses") payload = EmpresaCreate(cnpj="27865757000102", enderecos=["missing"]) with pytest.raises(HTTPException) as excinfo: asyncio.run(service.create(payload)) assert excinfo.value.status_code == 404 assert "Endereco" in excinfo.value.detail def test_update_empresa_allows_clearing_enderecos() -> None: databases = _DummyDatabases(existing_enderecos=["addr_1"]) service = _SyncEmpresasService(databases, "test-db", "test-companies-data", "test-addresses") payload = EmpresaUpdate(enderecos=[]) result = asyncio.run(service.update("emp_1", payload)) assert databases.updated_payloads[0]["enderecos"] == [] assert result.enderecos == [] def test_update_empresa_validates_new_enderecos() -> None: databases = _DummyDatabases(existing_enderecos=["addr_1"]) service = _SyncEmpresasService(databases, "test-db", "test-companies-data", "test-addresses") payload = EmpresaUpdate(enderecos=["addr_1"]) result = asyncio.run(service.update("emp_1", payload)) assert databases.endereco_lookups == ["addr_1"] assert databases.updated_payloads[0]["enderecos"] == ["addr_1"] assert result.enderecos == ["addr_1"]