1package config
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8
9 "github.com/bnema/vev/internal/domain"
10 "github.com/stretchr/testify/require"
11)
12
13func TestParseThemeAccent(t *testing.T) {
14 t.Parallel()
15
16 tests := []struct {
17 name string
18 input string
19 want domain.ThemeAccent
20 warnings []domain.Warning
21 }{
22 {
23 name: "auto",
24 input: "theme.accent = auto\n",
25 want: domain.ThemeAccent{Mode: domain.ThemeAccentAuto},
26 },
27 {
28 name: "slot zero is valid but warns",
29 input: "theme.accent = 0\n",
30 want: domain.ThemeAccent{Mode: domain.ThemeAccentSlot, Slot: 0},
31 warnings: []domain.Warning{
32 {Line: 1, Msg: "theme.accent slot 0 is conventionally neutral"},
33 },
34 },
35 {
36 name: "slot fifteen is valid but warns",
37 input: "theme.accent = 15\n",
38 want: domain.ThemeAccent{Mode: domain.ThemeAccentSlot, Slot: 15},
39 warnings: []domain.Warning{
40 {Line: 1, Msg: "theme.accent slot 15 is conventionally neutral"},
41 },
42 },
43 {
44 name: "chromatic slot",
45 input: "theme.accent = 2\n",
46 want: domain.ThemeAccent{Mode: domain.ThemeAccentSlot, Slot: 2},
47 },
48 {
49 name: "negative slot falls back to auto",
50 input: "theme.accent = -1\n",
51 want: domain.ThemeAccent{Mode: domain.ThemeAccentAuto},
52 warnings: []domain.Warning{
53 {Line: 1, Msg: "invalid theme.accent \"-1\""},
54 },
55 },
56 {
57 name: "out of range slot falls back to auto",
58 input: "theme.accent = 16\n",
59 want: domain.ThemeAccent{Mode: domain.ThemeAccentAuto},
60 warnings: []domain.Warning{
61 {Line: 1, Msg: "invalid theme.accent \"16\""},
62 },
63 },
64 {
65 name: "non numeric value falls back to auto",
66 input: "theme.accent = teal\n",
67 want: domain.ThemeAccent{Mode: domain.ThemeAccentAuto},
68 warnings: []domain.Warning{
69 {Line: 1, Msg: "invalid theme.accent \"teal\""},
70 },
71 },
72 {
73 name: "non canonical slot falls back to auto",
74 input: "theme.accent = 02\n",
75 want: domain.ThemeAccent{Mode: domain.ThemeAccentAuto},
76 warnings: []domain.Warning{
77 {Line: 1, Msg: "invalid theme.accent \"02\""},
78 },
79 },
80 {
81 name: "case sensitive auto falls back to auto",
82 input: "theme.accent = AUTO\n",
83 want: domain.ThemeAccent{Mode: domain.ThemeAccentAuto},
84 warnings: []domain.Warning{
85 {Line: 1, Msg: "invalid theme.accent \"AUTO\""},
86 },
87 },
88 }
89
90 for _, tt := range tests {
91 t.Run(tt.name, func(t *testing.T) {
92 t.Parallel()
93
94 cfg, warnings, err := Parse(strings.NewReader(tt.input))
95 require.NoError(t, err)
96 require.Equal(t, tt.want, cfg.ThemeAccent)
97 require.Equal(t, tt.warnings, warnings)
98 })
99 }
100}
101
102func TestDefaultsThemeAccent(t *testing.T) {
103 t.Parallel()
104
105 require.Equal(t, domain.ThemeAccent{Mode: domain.ThemeAccentAuto}, domain.Defaults().ThemeAccent)
106}
107
108func TestWatchThemeAccentInvalidReloadFallsBackToAuto(t *testing.T) {
109 t.Parallel()
110
111 path := filepath.Join(t.TempDir(), "config")
112 require.NoError(t, os.WriteFile(path, []byte("theme.accent = 2\n"), 0o600))
113 initial, warnings, err := Load(path)
114 require.NoError(t, err)
115 require.Empty(t, warnings)
116 require.Equal(t, domain.ThemeAccent{Mode: domain.ThemeAccentSlot, Slot: 2}, initial.ThemeAccent)
117
118 changes, stop := startWatch(t, path)
119 require.NoError(t, os.WriteFile(path, []byte("theme.accent = invalid\n"), 0o600))
120
121 got := nextChange(t, changes)
122 require.Equal(t, domain.ThemeAccent{Mode: domain.ThemeAccentAuto}, got.cfg.ThemeAccent)
123 require.Equal(t, []domain.Warning{{Line: 1, Msg: "invalid theme.accent \"invalid\""}}, got.warnings)
124 stop()
125}