1package client
2
3import (
4 "bytes"
5 "regexp"
6 "testing"
7
8 "github.com/stretchr/testify/require"
9
10 renderer "github.com/bnema/vev-vt"
11 "github.com/bnema/vev/internal/domain"
12 "github.com/bnema/vev/internal/usecase/ui"
13)
14
15func TestDrawClientToastPlacement(t *testing.T) {
16 size := domain.Size{Cols: 100, Rows: 30}
17 tests := []struct {
18 name string
19 anchor domain.Anchor
20 check func(t *testing.T, bounds domain.Rect)
21 }{
22 {name: "notice sits top-right", anchor: domain.AnchorTopRight, check: func(t *testing.T, bounds domain.Rect) {
23 require.Less(t, bounds.Y, 3)
24 require.Greater(t, bounds.X+bounds.Width, size.Cols-3)
25 }},
26 {name: "transition stays centered", anchor: domain.AnchorCenter, check: func(t *testing.T, bounds domain.Rect) {
27 require.Equal(t, (size.Rows-bounds.Height)/2, bounds.Y)
28 require.Equal(t, (size.Cols-bounds.Width)/2, bounds.X)
29 }},
30 }
31 for _, tt := range tests {
32 t.Run(tt.name, func(t *testing.T) {
33 var out bytes.Buffer
34 bounds, err := drawClientToast(&out, size, "SSH authentication failed", tt.anchor, domain.NoticeInfo)
35 require.NoError(t, err)
36 require.NotZero(t, out.Len())
37 tt.check(t, bounds)
38 })
39 }
40}
41
42func TestClientToastLinesKeepExactWidth(t *testing.T) {
43 sgr := regexp.MustCompile("\x1b\\[[0-9;]*m")
44 tests := []struct {
45 name string
46 message string
47 border string
48 }{
49 {name: "ascii", message: "host down"},
50 {name: "wide rune", message: "hôte 東京 down"},
51 {name: "colored border", message: "hôte 東京 down", border: toastBorderSGR(domain.NoticeError)},
52 }
53 for _, tt := range tests {
54 t.Run(tt.name, func(t *testing.T) {
55 bounds := ui.ToastBounds(domain.Size{Cols: 100, Rows: 30}, ui.Toast{Message: tt.message, Anchor: domain.AnchorTopRight})
56 for i, line := range clientToastLines(bounds, tt.message, tt.border) {
57 width := 0
58 for _, r := range sgr.ReplaceAllString(line, "") {
59 width += renderer.RuneWidth(r)
60 }
61 require.Equal(t, bounds.Width, width, "row %d width", i)
62 }
63 })
64 }
65}
66
67func TestDrawClientToastSeverityBorder(t *testing.T) {
68 size := domain.Size{Cols: 100, Rows: 30}
69 tests := []struct {
70 name string
71 severity domain.NoticeSeverity
72 want string
73 }{
74 {name: "error border is red", severity: domain.NoticeError, want: "\x1b[38;5;167m"},
75 {name: "warn border is yellow", severity: domain.NoticeWarn, want: "\x1b[38;5;179m"},
76 {name: "info keeps the default color", severity: domain.NoticeInfo},
77 }
78 for _, tt := range tests {
79 t.Run(tt.name, func(t *testing.T) {
80 var out bytes.Buffer
81 _, err := drawClientToast(&out, size, "host down", domain.AnchorTopRight, tt.severity)
82 require.NoError(t, err)
83 if tt.want == "" {
84 require.NotContains(t, out.String(), "\x1b[38;5;")
85 return
86 }
87 require.Contains(t, out.String(), tt.want)
88 require.Contains(t, out.String(), "host down")
89 })
90 }
91}