Files
GTI_GERENCIADOR_FISCAL/gerenciador/tests/test_main.py
T
gti d95165fc8f Add 'gerenciador/' from commit '34cc9c75a57dedbf61a6e6a1ba1f35f76e72434b'
git-subtree-dir: gerenciador
git-subtree-mainline: f4f546c928
git-subtree-split: 34cc9c75a5
2026-09-29 14:43:12 -03:00

131 lines
4.9 KiB
Python

from fastapi.testclient import TestClient
from app import session
from app.main import app
client = TestClient(app)
def _cookie_sessao_admin() -> dict:
return {session.SESSION_COOKIE_NAME: session.criar_token("admin", "admin", "ADMIN")}
def test_raiz_sem_login_redireciona_para_login():
resposta = client.get("/", follow_redirects=False)
assert resposta.status_code == 303
assert resposta.headers["location"] == "/login?next=/"
def test_docs_desabilitado_retorna_404():
assert client.get("/docs").status_code == 404
assert client.get("/redoc").status_code == 404
assert client.get("/openapi.json").status_code == 404
def test_raiz_redireciona_para_clientes_com_login(monkeypatch):
from app.routers import clientes as router_clientes
monkeypatch.setattr(router_clientes.db_clientes, "listar_clientes", lambda busca=None, limite=100, offset=0, ordenar_por="razao", direcao="asc", filtro_ativo=1: [])
monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None, ordenar_por="razao", filtro_ativo=1: 0)
resposta = client.get("/", cookies=_cookie_sessao_admin(), follow_redirects=False)
assert resposta.status_code == 307
assert resposta.headers["location"] == "/clientes"
def test_csrf_middleware_define_cookie_em_qualquer_resposta():
client.cookies.clear()
resposta = client.get("/docs")
assert resposta.status_code == 404
assert "csrf_token" in resposta.cookies
def test_csrf_bloqueia_post_com_token_que_nao_bate_com_cookie():
client.cookies.clear()
resposta = client.post(
"/clientes/1/excluir", cookies=_cookie_sessao_admin(), data={"csrf_token": "token-forjado-sem-cookie"}
)
assert resposta.status_code == 403
def test_csrf_libera_post_quando_token_bate_com_cookie(monkeypatch):
from app.routers import clientes as router_clientes
monkeypatch.setattr(router_clientes.db_clientes, "excluir_cliente", lambda cliente_id: None)
client.cookies.clear()
client.get("/docs") # só para o middleware definir o cookie csrf_token no client de teste
token_cookie = client.cookies.get("csrf_token")
assert token_cookie
cookies = {**_cookie_sessao_admin(), "csrf_token": token_cookie}
resposta = client.post(
"/clientes/1/excluir", cookies=cookies, data={"csrf_token": token_cookie}, follow_redirects=False
)
assert resposta.status_code == 303
def test_pagina_clientes_tem_csrf_token_preenchido_no_botao_sair(monkeypatch):
"""
Regressão: GET /clientes (a página onde todo login cai) não passava
csrf_token no contexto do template, então o formulário de logout em
base.html renderizava com value="" e POST /logout era rejeitado com
403 por app/csrf.py. base.html agora usa
"{{ csrf_token or request.state.csrf_token }}" como fallback.
"""
from app.routers import clientes as router_clientes
monkeypatch.setattr(
router_clientes.db_clientes,
"listar_clientes",
lambda busca=None, limite=100, offset=0, ordenar_por="razao", direcao="asc", filtro_ativo=1: [],
)
monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None, ordenar_por="razao", filtro_ativo=1: 0)
client.cookies.clear()
resposta = client.get("/clientes", cookies=_cookie_sessao_admin())
assert resposta.status_code == 200
assert 'name="csrf_token" value=""' not in resposta.text
import re
match = re.search(r'name="csrf_token" value="([^"]*)"', resposta.text)
assert match is not None
assert len(match.group(1)) > 0
def test_logout_funciona_depois_de_visitar_clientes(monkeypatch):
"""
Regressão complementar: simula o fluxo real — visitar /clientes (onde
o cookie csrf_token é definido pelo middleware) e então enviar
POST /logout usando o csrf_token real do cookie do navegador, sem
passar csrf_token manualmente no contexto do template.
"""
from app.routers import clientes as router_clientes
monkeypatch.setattr(
router_clientes.db_clientes,
"listar_clientes",
lambda busca=None, limite=100, offset=0, ordenar_por="razao", direcao="asc", filtro_ativo=1: [],
)
monkeypatch.setattr(router_clientes.db_clientes, "contar_clientes", lambda busca=None, ordenar_por="razao", filtro_ativo=1: 0)
client.cookies.clear()
client.cookies.update(_cookie_sessao_admin())
resposta_clientes = client.get("/clientes")
assert resposta_clientes.status_code == 200
token_cookie = client.cookies.get("csrf_token")
assert token_cookie
resposta_logout = client.post("/logout", data={"csrf_token": token_cookie}, follow_redirects=False)
assert resposta_logout.status_code == 303
def test_estilo_css_tem_versao_de_cache_busting():
resposta = client.get("/login")
assert resposta.status_code == 200
import re
m = re.search(r'/static/estilo\.css\?v=(\d+)', resposta.text)
assert m is not None, "link do estilo.css deveria ter ?v=<versao>"
assert m.group(1) != "0"