aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_include.py
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-15 23:21:40 +0200
committeruser <user@clank>2026-08-15 23:21:40 +0200
commitb9ae6cbcbce3816c2b2e8f760f082d3eaa3b5184 (patch)
tree8dd1f16ac15edd16f51ba07e37c312ccb89f53f1 /tests/test_include.py
parentsl0ppty: watch what the config was built from, not just what it was called (diff)
downloadslosh-b9ae6cbcbce3816c2b2e8f760f082d3eaa3b5184.tar.gz
slosh-b9ae6cbcbce3816c2b2e8f760f082d3eaa3b5184.tar.xz
slosh-b9ae6cbcbce3816c2b2e8f760f082d3eaa3b5184.zip
sl0ppty: say what the config could not honour
A config that half-applied said nothing. An unknown shader, a binding that does not parse, an include that is not there: the file loaded, that line did not, and the session announced "config reloaded" as though nothing had happened. Every one of those messages was already being produced -- config_load has filled `err` on a successful load since it was written -- and then dropped on the floor by every caller, because a non-zero return meant "fine". So the complaint from the last load is kept, and the front end says it where it would have said "config reloaded". Once at startup too: a config that loaded with a complaint still started the session, and the stderr line goes where nobody attached can read it. The `reload` control verb answers `{"ok":true,"warning":"..."}` -- ok, because the file did apply, with the reason attached for a script that cares. Two things fell out of writing the test for it. An include's complaint was reported by nobody when the file in the middle was fine. apply_includes only looked at the return value, so a theme that loaded while *its* include was missing swallowed the message: the child returned true, and true meant there was nothing to say. The complaint now travels up whether or not the include itself loaded. And a complaint now carries the name of the file it happened in, exactly once -- added by the file that produced it, never by the files that included it, because prefixing at every level builds a chain that truncates before the part that matters. So: t.kdl: unknown shader: bloom keys.kdl: line 2: unknown action fly b.kdl: includes nested too deep (a cycle?) cannot open /home/you/.config/sl0ppty/themes/nope.kdl which is enough to know which file to open, in a message that fits in a toast.
Diffstat (limited to 'tests/test_include.py')
-rwxr-xr-xtests/test_include.py21
1 files changed, 20 insertions, 1 deletions
diff --git a/tests/test_include.py b/tests/test_include.py
index 42baa89..b2f5200 100755
--- a/tests/test_include.py
+++ b/tests/test_include.py
@@ -123,7 +123,8 @@ def test_anything_can_be_included_not_only_a_theme():
def test_a_missing_include_costs_a_line_and_no_more():
"""Losing your keybindings over a mistyped theme name would be a worse
- answer than a session that carries on without the theme (D9)."""
+ answer than a session that carries on without the theme (D9) -- but silence
+ would be its own kind of wrong, so it is a line and not nothing."""
root = tree({"config.kdl": 'include "themes/nope.kdl"\ngap 2\n'})
with Session(SH, cols=60, rows=14, config=root + "/config.kdl") as s:
s.settle()
@@ -131,6 +132,23 @@ def test_a_missing_include_costs_a_line_and_no_more():
check("and the rest of the file applied anyway", s.pane()["x"] == 4,
str(s.pane()))
+ reply = s.api("reload")
+ check("the reload succeeds", reply.get("ok"), str(reply))
+ check("...and says which line it could not honour",
+ "nope.kdl" in reply.get("warning", ""), str(reply))
+ check("the session says it out loud too",
+ "nope.kdl" in s.snapshot().screen(),
+ repr(s.snapshot().screen()[-200:]))
+
+
+def test_a_cycle_says_so():
+ root = tree({"a.kdl": 'include "b.kdl"\n', "b.kdl": 'include "a.kdl"\n'})
+ with Session(SH, cols=70, rows=14, config=root + "/a.kdl") as s:
+ s.settle()
+ reply = s.api("reload")
+ check("a cycle is reported rather than followed",
+ "too deep" in reply.get("warning", ""), str(reply))
+
def test_a_cycle_stops_rather_than_spinning():
"""A config that includes itself is a mistake, and the depth limit is what
@@ -195,6 +213,7 @@ if __name__ == "__main__":
test_a_leading_tilde_is_a_home_directory()
test_anything_can_be_included_not_only_a_theme()
test_a_missing_include_costs_a_line_and_no_more()
+ test_a_cycle_says_so()
test_a_cycle_stops_rather_than_spinning()
test_an_include_is_picked_up_by_a_reload()
test_every_contrib_theme_can_be_included()