From be2e44994179ee7b64fead51b6c2bc0abdb7ea6f Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Wed, 16 Sep 2026 09:20:44 +0200 Subject: test(palette): assert every GTK template placeholder maps to a role A placeholder with no matching role renders literally into the CSS and GTK drops the declaration without an error. The stylesheets are 8500 lines each, so nothing would catch it by eye. Verified the assertion fires: renaming @ACCENT@ to @NOSUCHROLE@ in one asset template fails the selftest, naming the file and the placeholder. Co-Authored-By: Claude Opus 5 --- bin/udt-palette | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'bin/udt-palette') diff --git a/bin/udt-palette b/bin/udt-palette index bee7dc5..a9aa005 100755 --- a/bin/udt-palette +++ b/bin/udt-palette @@ -725,6 +725,19 @@ def selftest(): assert not missing, f"{scheme} is missing roles: {sorted(missing)}" assert not extra, f"{scheme} has roles no other scheme has: {sorted(extra)}" + # Every placeholder in the GTK templates must correspond to a role, or it + # renders literally and GTK drops the declaration without an error. The + # stylesheets are too large to eyeball, so this is the only thing standing + # between a typo and a silently half-themed desktop. + gtk_dir = REPO / "templates" / "gtk" + known = {f"@{r.upper()}@" for r in GTK_ROLES} + known |= {f"@{r.upper()}_RGB@" for r in GTK_ROLES} + known.add("@MAUVE@") + for tpl in sorted(gtk_dir.glob("*.in")) + sorted((gtk_dir / "assets").glob("*.in")): + used = set(re.findall(r"@[A-Z][A-Z_]*@", tpl.read_text())) + unknown = used - known + assert not unknown, f"{tpl.name} uses unknown placeholders: {sorted(unknown)}" + # Every name the rofi themes reference must be emitted, or rofi refuses to # parse the theme and every launcher on the desktop stops opening. This is # a real regression that shipped: gen_rofi used to emit the scheme's own -- cgit v1.2.3