From 626ba699346df0ae0acced3a9492725b25f2ccc2 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Thu, 18 Jun 2026 22:04:11 -0400 Subject: [PATCH] test(docker): parse-check templates + smoke routes/_human_bytes (milestone 77 #943) CI never renders docker templates through the app (the unit-lane app uses testing=True, which skips plugin loading), so a Jinja syntax error could ship green. Add unit tests that parse every docker template, smoke-import the routes module + confirm the #942 view functions exist, and cover the _human_bytes / _human_uptime presentation helpers. Closes the render-regression gap the new UI pages introduced. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_016Jg27rgypiW2efULXJDtMC --- tests/plugins/docker/test_routes.py | 50 +++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/plugins/docker/test_routes.py diff --git a/tests/plugins/docker/test_routes.py b/tests/plugins/docker/test_routes.py new file mode 100644 index 0000000..d74776b --- /dev/null +++ b/tests/plugins/docker/test_routes.py @@ -0,0 +1,50 @@ +"""Unit tests for the docker plugin's presentation layer (no DB). + +CI never renders these templates through the running app (the unit-lane app is +created with testing=True, which skips plugin loading), so a Jinja syntax error +would otherwise ship green. These tests parse every docker template and smoke +the routes module so a broken tag or import is caught in the unit lane. +""" +import pathlib + +import jinja2 + +from plugins.docker import routes as r + +_TEMPLATES = pathlib.Path(r.__file__).parent / "templates" / "docker" + + +def test_all_docker_templates_parse(): + env = jinja2.Environment() + files = sorted(_TEMPLATES.glob("*.html")) + assert files, "no docker templates found" + for f in files: + # Raises TemplateSyntaxError on an unbalanced/typo'd tag. + env.parse(f.read_text()) + + +def test_routes_module_exposes_new_views(): + # Import-smoke + confirms the #942 view functions are defined. + for name in ("container_detail", "container_history", "swarm", "disk", "index", "rows"): + assert callable(getattr(r, name)), name + assert r.docker_bp.name == "docker" + + +def test_human_bytes_formats_binary_units(): + assert r._human_bytes(None) == "—" + assert r._human_bytes(0) == "0 B" + assert r._human_bytes(512) == "512 B" + assert r._human_bytes(1024) == "1.0 KiB" + assert r._human_bytes(1536) == "1.5 KiB" + assert r._human_bytes(1024 ** 2) == "1.0 MiB" + assert r._human_bytes(int(1.5 * 1024 ** 3)) == "1.5 GiB" + assert r._human_bytes(1024 ** 4) == "1.0 TiB" + + +def test_human_uptime_compact(): + from datetime import datetime, timedelta, timezone + now = datetime.now(timezone.utc) + assert r._human_uptime(None) is None + assert r._human_uptime(now - timedelta(minutes=8)).endswith("m") + assert "h" in r._human_uptime(now - timedelta(hours=5, minutes=12)) + assert "d" in r._human_uptime(now - timedelta(days=3, hours=4))