Files
mesh-catalog/modules/dmenu/cmd/dmenu-tools/dmenu_test.go
T
jochen 838a6e510b dmenu: the package, which makes the notifier's menu work, and a menu tool (hq to-be 42 phase 2.7)
Research 026/04 counted two plain dmenu calls failing with dmenu installed
nowhere. Measured, they are one line on each workstation: dunst's
`dmenu = /usr/bin/dmenu -p dunst:`. Installing the package fixes both by
existing; the line stays the dunst module's.

No claim: node-launcher is not in the controller's seat table yet, and the
module says so. Two Go tools: menu, shaped like that seat's verb (chosen
line, index, typed, cancelled, timed out within 25 s), and session.
2026-10-04 13:02:23 +02:00

109 lines
3.8 KiB
Go

package main
import (
"strings"
"testing"
"time"
)
func TestTheManifestIsThePackageAndClaimsNoSeatYet(t *testing.T) {
m := readManifest(t)
// holdsTheBundle also holds it to no claim: node-launcher is not in the controller's seat table
// yet (README).
holdsTheBundle(t, m, "dmenu")
if got := strings.Join(m.packages(), ","); got != "dmenu" || len(m.Resources) != 1 {
t.Errorf("packages %s, resources %v", got, m.Resources)
}
}
func aSession(t *testing.T) {
t.Helper()
_, sockets := aMachine(t, map[string]string{"DISPLAY": ":1", "XAUTHORITY": "/home/op/.Xauthority"})
aSocket(t, sockets, "X1")
}
func TestMenuShowsTheChoicesInTheSessionAndAnswersTheOneTaken(t *testing.T) {
aSession(t)
f := using(t, func(string, Cmd) Result { return ok("Lock\n") })
got, err := Menu(Ask{Choices: []string{"Shutdown", "Lock"}, Prompt: "power:", Lines: 5, CaseInsensitive: true, Timeout: 20})
if err != nil || got.Chosen != "Lock" || got.Index != 1 || got.Typed || got.Cancelled || got.TimedOut {
t.Fatalf("%+v %v", got, err)
}
c := f.asked[0]
if f.lines()[0] != "dmenu -i -l 5 -p power:" || c.Stdin != "Shutdown\nLock\n" || c.Timeout != 20*time.Second {
t.Errorf("%v %+v", f.lines(), c)
}
if strings.Join(c.Env, " ") != "DISPLAY=:1 XAUTHORITY=/home/op/.Xauthority" {
t.Errorf("env %v", c.Env)
}
}
func TestMenuTellsTypedDismissedAndUnansweredApart(t *testing.T) {
aSession(t)
answer := ok("something else\n")
using(t, func(string, Cmd) Result { return answer })
got, err := Menu(Ask{Choices: []string{"a"}, Timeout: 5})
if err != nil || !got.Typed || got.Index != -1 || got.Chosen != "something else" {
t.Errorf("typed: %+v %v", got, err)
}
answer = Result{Status: 1}
got, err = Menu(Ask{Choices: []string{"a"}, Timeout: 5})
if err != nil || !got.Cancelled || got.Chosen != "" {
t.Errorf("dismissed: %+v %v", got, err)
}
answer = Result{Status: 124, Error: "timeout"}
got, err = Menu(Ask{Choices: []string{"a"}, Timeout: 5})
if err != nil || !got.TimedOut {
t.Errorf("unanswered: %+v %v", got, err)
}
answer = Result{Status: 1, Stderr: "cannot grab keyboard\n"}
if _, err := Menu(Ask{Choices: []string{"a"}, Timeout: 5}); err == nil || !strings.Contains(err.Error(), "keyboard") {
t.Errorf("a held keyboard: %v", err)
}
answer = Result{Status: 1, Stderr: "cannot open display\n"}
if _, err := Menu(Ask{Choices: []string{"a"}, Timeout: 5}); err == nil || !strings.Contains(err.Error(), "refused") {
t.Errorf("a refusing display: %v", err)
}
}
func TestMenuRefusesWhatCannotBeShownAndRunsNothingWithoutASession(t *testing.T) {
aSession(t)
f := using(t, func(string, Cmd) Result { return ok("") })
for _, bad := range []Ask{{}, {Choices: []string{"a\nb"}}, {Choices: []string{"a"}, Prompt: "x\ny"}, {Choices: make([]string, MostChoices+1)}} {
if _, err := Menu(bad); err == nil {
t.Errorf("%+v accepted", bad)
}
}
aMachine(t, map[string]string{})
if _, err := Menu(Ask{Choices: []string{"a"}, Timeout: 5}); err == nil || !strings.Contains(err.Error(), "no graphical session") {
t.Errorf("%v", err)
}
if len(f.asked) != 0 {
t.Errorf("ran %v", f.lines())
}
}
func TestTheWaitIsBelowTheRuntimesCallLimit(t *testing.T) {
if MostWait >= 30 {
t.Fatalf("a menu may stay open %d s; the runtime gives a call 30", MostWait)
}
n, _ := optWhole(map[string]any{"timeout_seconds": float64(600)}, "timeout_seconds", 20, 1, MostWait)
if n != MostWait {
t.Errorf("%d", n)
}
}
func TestSessionCheckSaysTheVersionAndTheSession(t *testing.T) {
aSession(t)
using(t, func(string, Cmd) Result { return ok("dmenu-5.4\n") })
got, err := SessionCheck()
if err != nil || got["dmenu"] != "dmenu-5.4" || got["found"] != true {
t.Fatalf("%v %v", got, err)
}
using(t, func(string, Cmd) Result { return Result{Status: 127, Error: "not-found"} })
got, _ = SessionCheck()
if !strings.Contains(got["dmenu"].(string), "not installed") {
t.Errorf("%v", got)
}
}