Files
mesh-catalog/modules/i3status-rust/cmd/i3status-rust-tools/blocks_test.go
T
jochen f2ab795926 Let the bar render blocks other modules contribute, and give it the battery and power draw from the power module (hq ADR 0255)
The bar left the battery out because it belongs to whoever knows the hardware, and had
no way to take it back in. i3status-rust now renders bar-neutral blocks through its
template; the power module contributes the battery where the machine reports one and
the power draw where something measures it, sampling the root-only energy counter as
root and publishing only a rate. The memory block shows what programs hold, the figure
memory-pressure judges by, instead of counting the cache as used.
2026-10-08 14:33:43 +02:00

99 lines
3.5 KiB
Go

package main
import (
"bytes"
"encoding/json"
"fmt"
"os"
"strings"
"testing"
"text/template"
)
// i3status-rust renders the blocks other modules contribute (novox/hq ADR 0255): a bar-neutral piece
// — what it shows, on which bar, where — in its own grammar, through the template its claim gives. The
// controller runs the template; these tests run it the same way, with the one function it is given.
func blockTemplate(t *testing.T) *template.Template {
t.Helper()
m := readManifest(t)
src, err := os.ReadFile("../../files/block.tmpl")
if err != nil {
t.Fatal(err)
}
if m.Claims[0].Renders["block"] != string(src) {
t.Fatal("the claim's template is not files/block.tmpl")
}
quote := func(v any) (string, error) {
b, err := json.Marshal(fmt.Sprint(v))
return string(b), err
}
return template.Must(template.New("block").Funcs(template.FuncMap{"quote": quote}).Parse(string(src)))
}
func render(t *testing.T, tmpl *template.Template, piece string) string {
t.Helper()
view := map[string]any{"module": "power"}
if err := json.Unmarshal([]byte(piece), &view); err != nil {
t.Fatal(err)
}
var b bytes.Buffer
if err := tmpl.Execute(&b, view); err != nil {
t.Fatal(err)
}
if strings.Contains(b.String(), "<no value>") {
t.Fatalf("%s rendered a missing value: %q", piece, b.String())
}
return b.String()
}
func TestAContributedBatteryIsI3statusRustsBatteryBlock(t *testing.T) {
tmpl := blockTemplate(t)
got := render(t, tmpl, `{"bar":"bottom","place":"status","shows":"battery"}`)
if !strings.HasPrefix(got, "[[block]]\nblock = \"battery\"\nformat = ") || strings.Contains(got, "device") ||
!strings.Contains(got, `missing_format = ""`) || !strings.HasSuffix(got, "\n\n") {
t.Fatalf("%q", got)
}
got = render(t, tmpl, `{"bar":"bottom","place":"status","shows":"battery","options":{"device":"BAT1"}}`)
if !strings.Contains(got, "block = \"battery\"\ndevice = \"BAT1\"\nformat = ") {
t.Fatalf("%q", got)
}
}
func TestAContributedCommandIsACustomBlockQuoted(t *testing.T) {
got := render(t, blockTemplate(t),
`{"bar":"bottom","place":"status","shows":"command","options":{"command":"say \"hi\"","interval":5}}`)
want := "[[block]]\nblock = \"custom\"\ncommand = \"say \\\"hi\\\"\"\ninterval = 5\n\n"
if got != want {
t.Fatalf("%q, want %q", got, want)
}
}
func TestEachBarPlacesBothPlacesOnce(t *testing.T) {
m := readManifest(t)
for _, bar := range []string{"bottom", "top"} {
content := m.resource(t, bar+"-bar")["content"].(string)
for _, place := range []string{"resources", "status"} {
ph := "${contribution:node-bar:block:bar=" + bar + ",place=" + place + "}"
if strings.Count(content, ph) != 1 {
t.Errorf("the %s bar places %s %d times", bar, ph, strings.Count(content, ph))
}
}
}
bottom := m.resource(t, "bottom-bar")["content"].(string)
resources := strings.Index(bottom, "place=resources")
if !(strings.Index(bottom, `block = "memory"`) < resources && resources < strings.Index(bottom, `block = "docker"`)) ||
!(strings.Index(bottom, `block = "sound"`) < strings.Index(bottom, "place=status") &&
strings.Index(bottom, "place=status") < strings.Index(bottom, `block = "weather"`)) {
t.Fatal("the places are not beside the memory and beside the sound")
}
}
func TestTheMemoryIsWhatProgramsHoldNotTheCache(t *testing.T) {
bottom := readManifest(t).resource(t, "bottom-bar")["content"].(string)
if !strings.Contains(bottom, `format = "$icon $mem_used.eng(w:2) ($mem_used_percents.eng(w:2))"`) ||
strings.Contains(bottom, "mem_total_used") {
t.Fatal("the memory block counts the cache as used")
}
}