carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package console
2
3import (
4 "strings"
5 "testing"
6)
7
8// The three legibility failures #9 caught in a browser that the render tests
9// could not see, because each of them is a fact about pixels rather than
10// about strings.
11
12// TestFlagshipBoxNamesSurviveTheirAlarms is the truncation, pinned with the
13// exact strings it was caught on.
14//
15// The four flagship boxes are `carlos-flagship-au/ie/uk/us` — 18 characters,
16// differing only in the last two. #322 stopped text overflowing its box by
17// making the title stop before the alarm marks, which reserved
18// len(Alarms)*14+5 pixels of the title line; with the two alarms every box on
19// the flagship has carried since 2026-08-28 that leaves 133px, and 133px at
20// 13px and the 0.58 glyph ratio is 17 characters. Every box truncated exactly
21// one character before the character that tells it apart from the other
22// three, which is the worst available place to run out of room.
23func TestFlagshipBoxNamesSurviveTheirAlarms(t *testing.T) {
24 two := []NodeAlarm{
25 {Name: "carlos-flagship-ie-mem-low", State: "OK"},
26 {Name: "carlos-flagship-ie-reachability", State: "OK"},
27 }
28 // ArchBand, not ArchView: #387 split the page into two estates drawn one
29 // above the other and #390 split each estate into one band per region,
30 // and layout/RenderArchSVG each take one band now. These pins are about
31 // a box's own pixels, so they belong to a band and are otherwise
32 // unchanged.
33 var v ArchBand
34 v.Nodes = []Node{
35 {ID: "box:ie", Kind: "box", Title: "carlos-flagship-ie",
36 Subtitle: "t4g.medium running", Alarms: two},
37 {ID: "box:au", Kind: "box", Title: "carlos-flagship-au",
38 Subtitle: "t4g.small running", Alarms: two},
39 }
40 layout(&v)
41 out := string(RenderArchSVG(v))
42 for _, want := range []string{"carlos-flagship-ie", "carlos-flagship-au"} {
43 if !strings.Contains(out, ">"+want+"<") {
44 t.Errorf("box name %q was truncated — the region is the character that tells these boxes apart:\n%s", want, out)
45 }
46 }
47 // The subtitle keeps the full width too: moving the marks down must not
48 // pay for the title out of the line below it.
49 for _, want := range []string{"t4g.medium running", "t4g.small running"} {
50 if !strings.Contains(out, ">"+want+"<") {
51 t.Errorf("subtitle %q was truncated:\n%s", want, out)
52 }
53 }
54}
55
56// TestAlarmMarksClearEveryTextLine: the marks moved off the title's line, so
57// they have to sit below the LAST baseline rather than merely somewhere else
58// — otherwise the fix trades a truncated title for a mark drawn over the
59// words — and inside the rect they belong to. Since #390 a box card carries
60// Extra lines (its apps, its instance counts) under the subtitle, each
61// nodeLineH further down, so the last baseline is not the subtitle's and the
62// check runs at every line count a card can have.
63func TestAlarmMarksClearEveryTextLine(t *testing.T) {
64 for _, extra := range [][]string{nil, {"console, kass"}, {"console, kass", "static 3 · resident 4"}} {
65 n := Node{ID: "box:ie", Kind: "box", Title: "carlos-flagship-ie", Y: 24,
66 Extra: extra, Alarms: []NodeAlarm{{Name: "a", State: "OK"}}}
67 n.H = nodeHeight(n)
68 // Where RenderArchSVG draws the last .archsub: the subtitle at +44,
69 // then one nodeLineH per Extra line. The mark's TOP edge has to clear
70 // the descenders below that baseline, not just its centre.
71 last := 44 + len(extra)*nodeLineH
72 const descender = 3
73 if top := alarmRow(n) - alarmR - n.Y; top <= last+descender {
74 t.Errorf("%d extra lines: alarm top at +%d, want below the last baseline (+%d) and its descenders", len(extra), top, last)
75 }
76 if alarmRow(n)+alarmR > n.Y+n.H {
77 t.Errorf("%d extra lines: alarm at +%d (r=%d) overflows a node %d tall", len(extra), alarmRow(n)-n.Y, alarmR, n.H)
78 }
79 }
80}
81
82// TestFiringAlarmsAreSummarisedForTheHeader: the marks ride their nodes,
83// which is right, but on a drawing wider than the window they are off-screen
84// and the Alarms table is thousands of pixels down. A page that knows
85// something is firing has to be able to say so above the fold.
86func TestFiringAlarmsAreSummarisedForTheHeader(t *testing.T) {
87 nodes := []Node{
88 {ID: "box:ie", Title: "carlos-flagship-ie", Alarms: []NodeAlarm{
89 {Name: "mem-low", State: "ALARM", Firing: true},
90 {Name: "reachability", State: "OK"},
91 }},
92 {ID: "box:au", Title: "carlos-flagship-au", Alarms: []NodeAlarm{
93 {Name: "reachability", State: "OK"},
94 }},
95 }
96 got := firingAlarms(nodes)
97 if len(got) != 1 {
98 t.Fatalf("firingAlarms = %v, want exactly the firing one", got)
99 }
100 // It names the alarm AND the thing it watches: "mem-low" on its own sends
101 // a reader to four near-identical box names.
102 if !strings.Contains(got[0], "mem-low") || !strings.Contains(got[0], "carlos-flagship-ie") {
103 t.Errorf("summary %q must name both the alarm and the node it watches", got[0])
104 }
105 if len(firingAlarms(nil)) != 0 {
106 t.Error("no nodes must summarise to nothing, not to an empty-but-present banner")
107 }
108}
109