aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-19 14:10:52 +0200
committeruser <user@clank>2026-08-19 14:10:52 +0200
commit1f5b55bc323e89399ec82eca392612ce2c0167a4 (patch)
tree84cffc149d0329117013debf04df8ac9c984f144 /tests
parentslosh: split app.c into five units, mechanically (diff)
downloadslosh-1f5b55bc323e89399ec82eca392612ce2c0167a4.tar.gz
slosh-1f5b55bc323e89399ec82eca392612ce2c0167a4.tar.xz
slosh-1f5b55bc323e89399ec82eca392612ce2c0167a4.zip
slosh: greet an attach with the logo, wearing a random shader
logo.txt is the source of truth; the Makefile bakes it into build/logo.h the way version.h is baked. When a client attaches (MSG_HELLO turning a connection into the display), the logo appears centered over everything for splash_ms (900, 0 for never), on a cleared backdrop, in the accent -- and one of six effects runs over its rect through the ordinary shader pass: a diagonal sheen, plasma, rings, sparkle, a left-to-right reveal, a breathe. Which one is picked by the splash's own timestamp, so every attach looks a little different without anybody keeping a counter. Every effect reads the clock, so the frame clock runs only while the splash is up (note_animation, same as any animated chain), and `since` in a splash context is milliseconds since it appeared, so one-shot effects sweep exactly once. Any key or click ends it and still lands where it was aimed: a greeting is not a modal. A screen the box does not fit on gets no greeting rather than a cropped one. Headless and scripted sessions never attach, so the whole fast suite never sees it; {"cmd":"splash"} triggers it on demand, which is what makes it testable from a scripted session -- and lets you replay the greeting whenever you like.
Diffstat (limited to 'tests')
-rw-r--r--tests/test_splash.py91
1 files changed, 91 insertions, 0 deletions
diff --git a/tests/test_splash.py b/tests/test_splash.py
new file mode 100644
index 0000000..1122662
--- /dev/null
+++ b/tests/test_splash.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+"""The logo splash: a greeting on attach, briefly, wearing a shader effect.
+
+A scripted session never attaches, so these drive it through the control
+API's `splash` verb -- the same call the server makes on MSG_HELLO. What is
+asserted is the contract: centered, temporary, ended early by input, and
+absent when splash_ms says never.
+"""
+
+import os
+import sys
+import tempfile
+
+from harness import Session, check, report
+
+SH = ["/bin/sh", "-c", 'printf "\\033]2;p\\007"; stty raw -echo; cat']
+GLYPHS = "\u2584\u2588\u2588\u2588\u2588\u2588\u2588\u2584" # ▄██████▄, line one
+
+
+def cfg(text):
+ f = tempfile.NamedTemporaryFile("w", suffix=".kdl", delete=False)
+ f.write(text)
+ f.close()
+ return f.name
+
+
+def test_the_splash_shows_centered_and_goes_away():
+ conf = cfg("splash_ms 400\n")
+ with Session(SH, cols=80, rows=24, config=conf) as s:
+ s.settle(30)
+ check("no greeting until asked", GLYPHS not in s.snapshot().screen(), "")
+ s.api("splash")
+ snap = s.snapshot()
+ check("the logo is up", GLYPHS in snap.screen(), snap.screen()[:200])
+
+ # Centered: the logo is 44 columns in an 80-column screen, so its
+ # first glyph lands at (80 - 44) / 2 give or take the box margin.
+ rows = [i for i, line in enumerate(snap.text) if GLYPHS in line]
+ line = snap.text[rows[0]]
+ x = line.index("\u2584")
+ check("h-centered", 14 <= x <= 22, f"x={x}")
+ check("v-centered", 6 <= rows[0] <= 12, f"y={rows[0]}")
+
+ snap = s.until(lambda sn: GLYPHS not in sn.screen())
+ check("and it goes away by itself", GLYPHS not in snap.screen(), "")
+ os.unlink(conf)
+
+
+def test_any_key_ends_it_and_still_lands():
+ conf = cfg("splash_ms 10000\n") # long enough that expiry cannot pass this
+ with Session(SH, cols=80, rows=24, config=conf) as s:
+ s.settle(30)
+ s.api("splash")
+ check("up", GLYPHS in s.snapshot().screen(), "")
+ s.send("marker") # plain keys: dismiss the greeting, reach the shell
+ snap = s.until(lambda sn: GLYPHS not in sn.screen())
+ check("a keystroke puts it away", GLYPHS not in snap.screen(), "")
+ snap = s.until_text("marker")
+ check(
+ "...and still reaches the pane it was aimed at",
+ "marker" in snap.screen(),
+ snap.screen()[:200],
+ )
+ os.unlink(conf)
+
+
+def test_splash_ms_zero_means_never():
+ conf = cfg("splash_ms 0\n")
+ with Session(SH, cols=80, rows=24, config=conf) as s:
+ s.settle(30)
+ s.api("splash")
+ s.settle(30)
+ check("nothing appears", GLYPHS not in s.snapshot().screen(), "")
+ os.unlink(conf)
+
+
+def test_a_screen_too_small_gets_no_greeting():
+ """Cropped branding is worse than none: the box needs its 48 columns."""
+ conf = cfg("splash_ms 10000\n")
+ with Session(SH, cols=40, rows=12, config=conf) as s:
+ s.settle(30)
+ s.api("splash")
+ s.settle(30)
+ check("no logo on 40 columns", GLYPHS not in s.snapshot().screen(), "")
+ os.unlink(conf)
+
+
+for name, fn in sorted(list(globals().items())):
+ if name.startswith("test_"):
+ fn()
+sys.exit(report())