Files
taller-wox/tests/test_frontend.py
farentsen a062b45c51 feat: initial implementation taller-wox.fitlabs.dev
Portal FastAPI + 5 endpoints REST para Bootcamp Agentic AI con
watsonx Orchestrate (FactorIT). Single container, Coolify-ready.

- Landing brandeado FIT con formulario de registro (honeypot anti-bot)
- Tokens itsdangerous para descargas (24h expiry)
- 5 endpoints API: historical/available procedures, member-insights,
  schedule, generate-report (Jinja2 + Plotly)
- SQLite con upsert-on-email para leads + log de descargas
- Admin endpoints (HTTP Basic): leads.json, leads.csv, stats
- 23 tests pytest pasando
- Dockerfile listo para Coolify con volúmenes persistentes
  (/app/leads.db, /app/app/data/reports_output, /app/material)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 03:04:28 +00:00

123 lines
3.7 KiB
Python

import os
from pathlib import Path
def test_landing_renders(client):
response = client.get("/")
assert response.status_code == 200
assert "Bootcamp Agentic AI" in response.text
assert 'name="email"' in response.text
assert 'name="website"' in response.text
def test_register_valid_form_redirects_with_token(client):
response = client.post(
"/register",
data={
"nombre": "Felipe Arentsen",
"email": "felipe@factorit.com",
"empresa": "FactorIT",
"consentimiento": "on",
},
follow_redirects=False,
)
assert response.status_code == 303
assert response.headers["location"].startswith("/descargas?token=")
def test_register_honeypot_filled_silently_drops(client):
response = client.post(
"/register",
data={
"nombre": "Bot",
"email": "bot@spam.com",
"empresa": "Spam Inc",
"consentimiento": "on",
"website": "https://spam.com",
},
follow_redirects=False,
)
assert response.status_code == 303
from app.db import get_lead_by_email
assert get_lead_by_email("bot@spam.com") is None
def test_register_duplicate_email_reissues_token(client):
for _ in range(2):
client.post(
"/register",
data={
"nombre": "Felipe",
"email": "dup@factorit.com",
"empresa": "FactorIT",
"consentimiento": "on",
},
follow_redirects=False,
)
from app.db import get_lead_by_email
lead = get_lead_by_email("dup@factorit.com")
assert lead["times_registered"] == 2
def test_descargas_with_invalid_token_redirects_home(client):
response = client.get("/descargas?token=invalid-junk", follow_redirects=False)
assert response.status_code == 307
assert response.headers["location"].startswith("/?error=")
def test_descargas_with_valid_token_renders(client):
reg = client.post(
"/register",
data={
"nombre": "Maria",
"email": "maria@test.com",
"empresa": "Test Co",
"consentimiento": "on",
},
follow_redirects=False,
)
token = reg.headers["location"].split("token=")[1]
response = client.get(f"/descargas?token={token}")
assert response.status_code == 200
assert "Hola Maria" in response.text
assert "Material técnico" in response.text
assert "Material funcional" in response.text
def test_download_with_valid_token_serves_file(client):
material_dir = Path(os.environ["MATERIAL_DIR"])
material_dir.mkdir(parents=True, exist_ok=True)
(material_dir / "taller-wox-tecnico.zip").write_bytes(b"PK\x03\x04 fake zip")
reg = client.post(
"/register",
data={
"nombre": "Test",
"email": "test-dl@test.com",
"empresa": "TC",
"consentimiento": "on",
},
follow_redirects=False,
)
token = reg.headers["location"].split("token=")[1]
response = client.get(f"/download/taller-wox-tecnico.zip?token={token}")
assert response.status_code == 200
assert response.content == b"PK\x03\x04 fake zip"
assert "attachment" in response.headers["content-disposition"]
def test_download_invalid_filename_returns_404(client):
reg = client.post(
"/register",
data={
"nombre": "Test",
"email": "bad-fn@test.com",
"empresa": "TC",
"consentimiento": "on",
},
follow_redirects=False,
)
token = reg.headers["location"].split("token=")[1]
response = client.get(f"/download/etc-passwd?token={token}")
assert response.status_code == 404