package main import ( "reflect" "strings" "testing" ) // rofi's shape (novox/hq ADR 0208, research 026/04): it claims node-launcher and serves its verb // `menu`, requires the X display on its own machine, owns its configuration and its two themes, and // places the seat's dmenu-compatible command, its launcher and power menu, and its key bindings as // its own i3 drop-in. func TestItClaimsTheLauncherSeatServingMenuAndRequiresTheXDisplay(t *testing.T) { m := readManifest(t) if m.Module != "rofi" || m.Seats != nil { t.Fatalf("module %q declares seats %v", m.Module, m.Seats) } if !reflect.DeepEqual(m.Claims, []claim{{Name: "node-launcher", Scope: "node", Serves: []string{"menu"}}}) { t.Fatalf("claims: %+v", m.Claims) } if !reflect.DeepEqual(m.Requires, []string{"x11-display"}) { t.Fatalf("requires: %v", m.Requires) } if present, absent := m.packages(); !reflect.DeepEqual(present, []string{"rofi"}) || absent != nil { t.Fatalf("packages: %v, absent %v", present, absent) } } func TestItOwnsItsFilesAsWrittenInTheModule(t *testing.T) { m := readManifest(t) for id, source := range map[string]string{ "configuration": "files/config.rasi", "theme": "files/themes/mesh.rasi", "theme-powermenu": "files/themes/mesh-powermenu.rasi", "dmenu": "files/bin/dmenu", "launch": "files/bin/rofi-launch", "powermenu": "files/bin/rofi-powermenu", "i3-bindings": "files/i3/50-rofi.conf", } { m.sameAsSource(t, id, source) } for _, id := range []string{"dmenu", "launch", "powermenu"} { if m.resource(t, id)["mode"] != "0755" { t.Errorf("%s is executable", id) } } if p := m.resource(t, "dmenu")["path"]; p != "${machine:account-home}/.local/bin/dmenu" { t.Fatalf("the seat's command is dmenu on the account's PATH: %v", p) } } func TestTheThemesAreTheMeshsFacesAndTheConfigurationNamesOne(t *testing.T) { m := readManifest(t) conf := m.resource(t, "configuration")["content"].(string) if !strings.Contains(conf, `@theme "mesh"`) || strings.Contains(conf, "@import") { t.Fatal("the configuration names the theme mesh and imports nothing") } for _, id := range []string{"theme", "theme-powermenu"} { c := m.resource(t, id)["content"].(string) if !strings.Contains(c, `"JetBrainsMono Nerd Font`) || strings.Contains(c, "@import") || strings.Contains(c, "Hack") || strings.Contains(c, "Iosevka") { t.Errorf("%s: the monospace face, and no imported file", id) } } if !strings.Contains(m.resource(t, "theme")["content"].(string), `"Inter 11"`) { t.Error("the theme's prose is in the interface face") } } func TestThePowerMenuNamesNoWindowManagerAndNoLocker(t *testing.T) { m := readManifest(t) menu := m.resource(t, "powermenu")["content"].(string) for _, never := range []string{"i3-msg", "i3lock", "betterlockscreen", "openbox", "bspc", "qdbus", "mpc"} { if strings.Contains(menu, never) { t.Errorf("the power menu names %s", never) } } for _, want := range []string{"loginctl lock-session", "loginctl terminate-session", "systemctl suspend", "systemctl reboot", "systemctl poweroff"} { if !strings.Contains(menu, want) { t.Errorf("the power menu lacks %s", want) } } } func TestTheKeyBindingsAreAnI3DropInRunningTheModulesOwnCommands(t *testing.T) { m := readManifest(t) bindings := m.resource(t, "i3-bindings")["content"].(string) for _, line := range strings.Split(bindings, "\n") { if line == "" || strings.HasPrefix(line, "#") { continue } if !strings.HasPrefix(line, "bindsym $mod+") || !strings.Contains(line, "exec --no-startup-id ~/.local/bin/rofi-") { t.Errorf("a binding that is not the launcher's: %s", line) } } for _, key := range []string{"$mod+d ", "$mod+Escape "} { if !strings.Contains(bindings, "bindsym "+key) { t.Errorf("no %s", key) } } if m.Shell != nil { t.Fatalf("the launcher starts nothing at session start: %+v", m.Shell) } } func TestTheToolsAgreeWithTheManifest(t *testing.T) { m := readManifest(t) checkTheToolsAgree(t, m) checkNoSecretsOrInstallationNames(t) }