feat(infra): auto-commit con 56 cambios

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-21 14:22:55 +02:00
parent c1071a82b3
commit 32c7336bf6
56 changed files with 5307 additions and 100 deletions
@@ -0,0 +1,152 @@
"""Tests para render_glance_config."""
import os
import sys
import yaml
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
from functions.infra.render_glance_config import render_glance_config
SERVICES = [
{
"name": "metabase",
"subdomain": "metabase",
"title": "Metabase",
"icon": "si:metabase",
"category": "Datos",
},
{
"name": "portainer",
"subdomain": "portainer",
"title": "Portainer",
"icon": "", # icon vacío -> debe omitirse
"category": "Infra",
},
]
def test_golden_dos_categorias_dos_widgets():
out = render_glance_config(SERVICES)
cfg = yaml.safe_load(out)
widgets = cfg["pages"][0]["columns"][0]["widgets"]
assert len(widgets) == 2
assert all(w["type"] == "monitor" for w in widgets)
# Categorías ordenadas alfabéticamente: Datos antes que Infra.
assert [w["title"] for w in widgets] == ["Datos", "Infra"]
datos_site = widgets[0]["sites"][0]
assert datos_site["title"] == "Metabase"
assert datos_site["url"] == "http://metabase.localhost"
assert datos_site["icon"] == "si:metabase"
def test_yaml_parseable_y_estructura():
out = render_glance_config(SERVICES)
cfg = yaml.safe_load(out) # no debe lanzar
page = cfg["pages"][0]
assert page["name"] == "Procesos locales"
col = page["columns"][0]
assert col["size"] == "full"
assert isinstance(col["widgets"], list)
assert out.endswith("\n")
def test_icon_omitido_cuando_vacio():
out = render_glance_config(SERVICES)
cfg = yaml.safe_load(out)
infra_site = cfg["pages"][0]["columns"][0]["widgets"][1]["sites"][0]
assert infra_site["title"] == "Portainer"
assert "icon" not in infra_site
def test_host_suffix_custom():
out = render_glance_config(SERVICES, host_suffix="home.lan")
cfg = yaml.safe_load(out)
site = cfg["pages"][0]["columns"][0]["widgets"][0]["sites"][0]
assert site["url"] == "http://metabase.home.lan"
def test_title_es_name_de_pagina():
out = render_glance_config(SERVICES, title="Mi Hub")
cfg = yaml.safe_load(out)
assert cfg["pages"][0]["name"] == "Mi Hub"
def test_servicios_sin_subdomain_se_ignoran():
services = SERVICES + [{"name": "roto", "title": "Roto", "category": "Datos"}]
out = render_glance_config(services)
cfg = yaml.safe_load(out)
datos = cfg["pages"][0]["columns"][0]["widgets"][0]
# Solo Metabase en Datos; el servicio sin subdomain se descarta.
assert len(datos["sites"]) == 1
assert datos["sites"][0]["title"] == "Metabase"
def test_determinismo():
a = render_glance_config(SERVICES)
b = render_glance_config(list(reversed(SERVICES)))
# El orden de entrada no afecta: categorías y sites se ordenan internamente.
assert a == b
def test_orden_sites_por_title():
services = [
{"subdomain": "z-svc", "title": "Zeta", "category": "Datos"},
{"subdomain": "a-svc", "title": "Alfa", "category": "Datos"},
]
out = render_glance_config(services)
cfg = yaml.safe_load(out)
sites = cfg["pages"][0]["columns"][0]["widgets"][0]["sites"]
assert [s["title"] for s in sites] == ["Alfa", "Zeta"]
def test_categoria_default_general():
services = [{"subdomain": "x", "title": "X"}]
out = render_glance_config(services)
cfg = yaml.safe_load(out)
assert cfg["pages"][0]["columns"][0]["widgets"][0]["title"] == "General"
def test_check_url_se_emite_cuando_health_path_no_es_raiz():
services = [
{
"subdomain": "api",
"title": "API",
"category": "Datos",
"health_path": "/api/health",
},
{
"subdomain": "web",
"title": "Web",
"category": "Datos",
"health_path": "/", # raiz -> no debe emitir check-url
},
{
"subdomain": "raw",
"title": "Raw",
"category": "Datos",
# sin health_path -> tampoco debe emitir check-url
},
]
out = render_glance_config(services)
cfg = yaml.safe_load(out) # sigue siendo YAML parseable
sites = {
s["title"]: s
for s in cfg["pages"][0]["columns"][0]["widgets"][0]["sites"]
}
# health_path no-raiz -> check-url = url + health_path; url sigue siendo la raiz.
assert sites["API"]["url"] == "http://api.localhost"
assert sites["API"]["check-url"] == "http://api.localhost/api/health"
# health_path == "/" -> sin check-url.
assert sites["Web"]["url"] == "http://web.localhost"
assert "check-url" not in sites["Web"]
# sin health_path -> sin check-url.
assert sites["Raw"]["url"] == "http://raw.localhost"
assert "check-url" not in sites["Raw"]