1package config
2
3import (
4 "context"
5 "os"
6 "path/filepath"
7 "strings"
8 "testing"
9
10 "github.com/bnema/vev/internal/domain"
11 "github.com/stretchr/testify/require"
12)
13
14func TestParsePaletteAnchor(t *testing.T) {
15 t.Parallel()
16
17 tests := []struct {
18 name string
19 input string
20 want domain.PaletteConfig
21 warnings []domain.Warning
22 }{
23 {name: "default is centered", want: domain.PaletteConfig{Anchor: domain.AnchorCenter, AnchorSet: true}},
24 {name: "explicit auto is case insensitive", input: "palette.anchor = AuTo\n", want: domain.PaletteConfig{}},
25 {name: "concrete anchors are trimmed and case insensitive", input: "palette.anchor = CENTER\npalette.anchor = top-left\npalette.anchor = Top\npalette.anchor = TOP-RIGHT\npalette.anchor = left\npalette.anchor = RIGHT\npalette.anchor = bottom-left\npalette.anchor = Bottom\npalette.anchor = BOTTOM-RIGHT \n", want: domain.PaletteConfig{Anchor: domain.AnchorBottomRight, AnchorSet: true}, warnings: []domain.Warning{{Line: 2, Msg: "duplicate key \"palette.anchor\""}, {Line: 3, Msg: "duplicate key \"palette.anchor\""}, {Line: 4, Msg: "duplicate key \"palette.anchor\""}, {Line: 5, Msg: "duplicate key \"palette.anchor\""}, {Line: 6, Msg: "duplicate key \"palette.anchor\""}, {Line: 7, Msg: "duplicate key \"palette.anchor\""}, {Line: 8, Msg: "duplicate key \"palette.anchor\""}, {Line: 9, Msg: "duplicate key \"palette.anchor\""}}},
26 {name: "invalid first preserves centered default", input: "palette.anchor = diagonal\n", want: domain.PaletteConfig{Anchor: domain.AnchorCenter, AnchorSet: true}, warnings: []domain.Warning{{Line: 1, Msg: "invalid palette.anchor \"diagonal\""}}},
27 {name: "valid then invalid preserves valid", input: "palette.anchor = top\npalette.anchor = diagonal\n", want: domain.PaletteConfig{Anchor: domain.AnchorTop, AnchorSet: true}, warnings: []domain.Warning{{Line: 2, Msg: "duplicate key \"palette.anchor\""}, {Line: 2, Msg: "invalid palette.anchor \"diagonal\""}}},
28 {name: "explicit then auto clears to auto", input: "palette.anchor = left\npalette.anchor = auto\n", want: domain.PaletteConfig{}, warnings: []domain.Warning{{Line: 2, Msg: "duplicate key \"palette.anchor\""}}},
29 }
30 for _, tt := range tests {
31 t.Run(tt.name, func(t *testing.T) {
32 cfg, warnings, err := Parse(strings.NewReader(tt.input))
33 require.NoError(t, err)
34 require.Equal(t, tt.want, cfg.Palette)
35 require.Equal(t, tt.warnings, warnings)
36 require.Empty(t, cfg.BindingEntries)
37 })
38 }
39}
40
41func TestLoadMissingPaletteAnchorDefaultsToCenter(t *testing.T) {
42 t.Parallel()
43 cfg, warnings, err := Load(filepath.Join(t.TempDir(), "missing"))
44 require.NoError(t, err)
45 require.Empty(t, warnings)
46 require.Equal(t, domain.PaletteConfig{Anchor: domain.AnchorCenter, AnchorSet: true}, cfg.Palette)
47}
48
49func TestWatchPaletteAnchorRestoresCenteredDefaultAfterFileRemoval(t *testing.T) {
50 path := filepath.Join(t.TempDir(), "config")
51 require.NoError(t, os.WriteFile(path, []byte("palette.anchor = top-right\n"), 0o600))
52 clk := newWatchClockMock(t)
53 ctx, cancel := context.WithCancel(context.Background())
54 defer cancel()
55 changes := make(chan domain.Config, 2)
56 done := make(chan error, 1)
57 go func() {
58 done <- Watch(ctx, clk.clock, path, func(cfg domain.Config, _ []domain.Warning) { changes <- cfg })
59 }()
60 clk.waitForTimer()
61
62 require.NoError(t, os.WriteFile(path, []byte("palette.anchor = bottom-left\n"), 0o600))
63 clk.fire()
64 require.Equal(t, domain.AnchorBottomLeft, (<-changes).Palette.Anchor)
65
66 require.NoError(t, os.Remove(path))
67 clk.fire()
68 got := <-changes
69 require.Equal(t, domain.PaletteConfig{Anchor: domain.AnchorCenter, AnchorSet: true}, got.Palette)
70 cancel()
71 require.ErrorIs(t, <-done, context.Canceled)
72}