import pytest from fastapi_users.authentication import JWTStrategy from app.main import app from httpx import AsyncClient from datetime import datetime, timedelta from app.database.models import Base, RbacUser, RbacPapel, RbacPermissao # from fastapi_users_db_sqlalchemy import SQLAlchemyBaseUserTableUUID from app.config import URL_BD_TESTE, SECRET from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.ext.asyncio import async_sessionmaker from sqlalchemy import text from app.rbac.auth import current_active_user # Criação do engine de testes com o URL do banco de dados engine = create_async_engine(URL_BD_TESTE) selected_user = None # Configurando o async_sessionmaker para usar AsyncSession TestSessionLocal = async_sessionmaker( bind=engine, class_=AsyncSession, autoflush=False, autocommit=False, ) # print("Configuração do sessionmaker concluída") # print(URL_BD_TESTE) def pytest_addoption(parser): parser.addoption( "--usuario", action="store", default="admin", help="Nome do usuário para executar os testes" ) # Função para criar um usuário com permissão e papel def create_user(email, papel_nome, permissoes_ids): permissoes = [RbacPermissao(id=perm_id, nome=f"Permissao_{perm_id}") for perm_id in permissoes_ids] papel = RbacPapel( nome=papel_nome, permissoes=permissoes ) user = RbacUser( email=email, hashed_password="hashed-password", fk_inquilino_uuid="pytest", is_active=True, is_superuser=False, papeis=[papel] ) return user # Fixture para criar múltiplos usuários @pytest.fixture(scope="session") def create_test_users(): users = { "admin": create_user( email="admin@example.com", papel_nome="Admin_Papel", permissoes_ids=[1] ), "comercial": create_user( email="user1@example.com", papel_nome="User1_Papel", permissoes_ids=[2] ), "estoque": create_user( email="user2@example.com", papel_nome="User2_Papel", permissoes_ids=[4] ), "financeiro": create_user( email="user3@example.com", papel_nome="User3_Papel", permissoes_ids=[5] ), "pessoa": create_user( email="user4@example.com", papel_nome="User4_Papel", permissoes_ids=[4, 5, 33] ), } return users # Fixture para selecionar um usuário @pytest.fixture(scope="session") def selecionar_usuario(create_test_users, request): usuario_nome = request.config.getoption("--usuario", default="admin") usuario_selecionado = create_test_users.get(usuario_nome, create_test_users["admin"]) return usuario_selecionado def fake_current_user(selecionar_usuario): return selecionar_usuario async def create_test_database(): tenant_schema = "pytest" # Dropar e recriar o schema "pytest" async with engine.begin() as conn: try: # print("Dropping schema tenant (pytest)...") await conn.execute(text(f"DROP SCHEMA IF EXISTS {tenant_schema} CASCADE")) # print("Creating schema tenant (pytest)...") await conn.execute(text(f"CREATE SCHEMA {tenant_schema}")) except Exception as e: print(f"Erro ao dropar ou recriar o schema '{tenant_schema}': {e}") raise # Propaga o erro para interromper os testes # Atualiza o schema das tabelas que não são do schema "shared" for table in Base.metadata.tables.values(): if table.schema != "shared": table.schema = tenant_schema # Cria as tabelas apenas para o schema tenant tenant_tables = [table for table in Base.metadata.sorted_tables if table.schema == tenant_schema] async with engine.begin() as conn: try: # print("Criando tabelas no schema tenant (pytest)...") await conn.run_sync(Base.metadata.create_all, tables=tenant_tables) except Exception as e: print(f"Erro ao criar as tabelas no schema '{tenant_schema}': {e}") raise @pytest.fixture(scope="session") def anyio_backend(): return "asyncio" @pytest.fixture(scope="session") async def client(selecionar_usuario): # print("Iniciando Cliente") # Chama a função para criar o banco de dados de teste await create_test_database() app.dependency_overrides[current_active_user] = lambda: selecionar_usuario strategy = JWTStrategy(secret=SECRET, lifetime_seconds=3600) token = await strategy.write_token(selecionar_usuario) # print(f"Token gerado: {token}") async with AsyncClient(app=app, base_url="http://test") as client: client.headers.update({"Authorization": f"Bearer {token}"}) yield client # Função para modificar os itens de teste com base nos usuários permitidos def pytest_collection_modifyitems(config, items): usuario = config.getoption("--usuario") def usuario_esta_permitido(usuarios_permitidos_): # print(f"Verificando se o usuário '{usuario}' está na lista de permitidos: {usuarios_permitidos_}") return usuario in usuarios_permitidos_ selected_items = [] for item in items: usuarios_permitidos_marker = item.get_closest_marker("usuarios_permitidos") if usuarios_permitidos_marker: usuarios_permitidos = usuarios_permitidos_marker.args[0] if not usuario_esta_permitido(usuarios_permitidos): # print(f"Ignorando o teste '{item.name}' porque o usuário '{usuario}' não está permitido.") continue # Ignorar o teste se o usuário não estiver permitido selected_items.append(item) # Atualiza a lista de testes que serão executados items[:] = selected_items # FUNÇÕES PARA ROTAS QUE REQUEREM AUTENTICAÇÃO # MODULOS COM UUID PARA TESTES @pytest.fixture(scope="session") def datas_referencia(): data_atual = datetime.now().date() return { "data_atual": data_atual, "data_anterior": data_atual - timedelta(days=1), "data_posterior": data_atual + timedelta(days=1), } @pytest.fixture(scope="session") def uuid_store_relacao_comercial(): return { "uuid_1": "01915caf-2c4d-7270-a071-d928c87f8e20", # UUID inválido para testes "uuid_2": "01915caf-2c4d-7270-a071-d928c87f8e30", # UUID inválido para testes "uuid_3": None, "uuid_4": None, "uuid_5": None, "uuid_6": None, # UUID para Relacionamento "uuid_7": None, # UUID para Relacionamento "uuid_8": None, # UUID para Relacionamento "uuid_9": None, "uuid_10": None, "uuid_11": None, } @pytest.fixture(scope="session") def uuid_store_tipo_endereco(): return { "uuid_1": "01915caf-2c4d-7270-a071-d928c87f8e40", # UUID inválido para testes "uuid_2": "01915caf-2c4d-7270-a071-d928c87f8e50", # UUID inválido para testes "uuid_3": None, "uuid_4": None, "uuid_5": None, "uuid_6": None, # UUID para Relacionamento "uuid_7": None, # UUID para Relacionamento "uuid_8": None, # UUID para Relacionamento } @pytest.fixture(scope="session") def uuid_store_pessoa(): return { "uuid_1": "01915caf-2c4d-7270-a071-d928c87f8e60", # UUID inválido para testes "uuid_2": "01915caf-2c4d-7270-a071-d928c87f8e70", # UUID inválido para testes "uuid_3": None, "uuid_4": None, "uuid_5": None, "uuid_6": None, "uuid_7": None, "uuid_8": None, } @pytest.fixture(scope="session") def uuid_store_endereco(): return { "uuid_1": "01915caf-2c4d-7270-a071-d928c87f8e80", # UUID inválido para testes "uuid_2": "01915caf-2c4d-7270-a071-d928c87f8e90", # UUID inválido para testes "uuid_3": None, "uuid_4": None, "uuid_5": None, "uuid_6": None, "uuid_7": None, "uuid_8": None, } @pytest.fixture(scope="session") def uuid_store_setor(): return { "uuid_1": "01915caf-2c4d-7270-a071-d928c87f8e21", # UUID inválido para testes "uuid_2": "01915caf-2c4d-7270-a071-d928c87f8e32", # UUID inválido para testes "uuid_3": None, "uuid_4": None, "uuid_5": None, "uuid_6": None, # UUID para Relacionamento "uuid_7": None, # UUID para Relacionamento "uuid_8": None, # UUID para Relacionamento "uuid_9": None, "uuid_10": None, "uuid_11": None, } @pytest.fixture(scope="session") def uuid_store_tipo_equipamento(): return { "uuid_1": "01915caf-2c4d-7270-a071-d928c87f8e22", # UUID inválido para testes "uuid_2": "01915caf-2c4d-7270-a071-d928c87f8e31", # UUID inválido para testes "uuid_3": None, "uuid_4": None, "uuid_5": None, "uuid_6": None, # UUID para Relacionamento "uuid_7": None, # UUID para Relacionamento "uuid_8": None, # UUID para Relacionamento "uuid_9": None, "uuid_10": None, "uuid_11": None, } @pytest.fixture(scope="session") def uuid_store_equipamento(): return { "uuid_1": "01915caf-2c4d-7270-a071-d928c87f8e23", # UUID inválido para testes "uuid_2": "01915caf-2c4d-7270-a071-d928c87f8e32", # UUID inválido para testes "uuid_3": None, "uuid_4": None, "uuid_5": None, "uuid_6": None, # UUID para Relacionamento "uuid_7": None, # UUID para Relacionamento "uuid_8": None, # UUID para Relacionamento "uuid_9": None, "uuid_10": None, "uuid_11": None, } @pytest.fixture(scope="session") def uuid_store_itens_equipamento(): return { "uuid_1": "01915caf-2c4d-7270-a071-d928c87f8e24", # UUID inválido para testes "uuid_2": "01915caf-2c4d-7270-a071-d928c87f8e33", # UUID inválido para testes "uuid_3": None, "uuid_4": None, "uuid_5": None, "uuid_6": None, # UUID para Relacionamento "uuid_7": None, # UUID para Relacionamento "uuid_8": None, # UUID para Relacionamento "uuid_9": None, "uuid_10": None, "uuid_11": None, } @pytest.fixture(scope="session") def uuid_store_manutencao_equipamento(): return { "uuid_1": "01915caf-2c4d-7270-a071-d928c87f8e25", # UUID inválido para testes "uuid_2": "01915caf-2c4d-7270-a071-d928c87f8e34", # UUID inválido para testes "uuid_3": None, "uuid_4": None, "uuid_5": None, "uuid_6": None, # UUID para Relacionamento "uuid_7": None, # UUID para Relacionamento "uuid_8": None, # UUID para Relacionamento "uuid_9": None, "uuid_10": None, "uuid_11": None, }