1package config
2
3import (
4 "testing"
5
6 "github.com/spf13/viper"
7 "github.com/stretchr/testify/assert"
8 "github.com/stretchr/testify/require"
9)
10
11func TestFloatingPaneConfig_Defaults(t *testing.T) {
12 cfg := DefaultConfig()
13
14 assert.InDelta(t, 0.82, cfg.Workspace.FloatingPane.WidthPct, 0.0001)
15 assert.InDelta(t, 0.72, cfg.Workspace.FloatingPane.HeightPct, 0.0001)
16 assert.Empty(t, cfg.Workspace.FloatingPane.Profiles)
17
18 binding, ok := cfg.Workspace.Shortcuts.Actions["toggle-floating-pane"]
19 require.True(t, ok)
20 assert.Equal(t, []string{"alt+f"}, binding.Keys)
21}
22
23func TestFloatingPaneConfig_DefaultsLoadThroughViper(t *testing.T) {
24 mgr := &Manager{viper: viper.New()}
25 mgr.setDefaults()
26
27 cfg, err := mgr.unmarshalConfig()
28 require.NoError(t, err)
29
30 assert.InDelta(t, 0.82, cfg.Workspace.FloatingPane.WidthPct, 0.0001)
31 assert.InDelta(t, 0.72, cfg.Workspace.FloatingPane.HeightPct, 0.0001)
32 assert.Empty(t, cfg.Workspace.FloatingPane.Profiles)
33
34 binding, ok := cfg.Workspace.Shortcuts.Actions["toggle-floating-pane"]
35 require.True(t, ok)
36 assert.Equal(t, []string{"alt+f"}, binding.Keys)
37}
38
39func TestFloatingPaneConfig_ValidationRanges(t *testing.T) {
40 tests := []struct {
41 name string
42 mutate func(cfg *Config)
43 errorField string
44 }{
45 {
46 name: "width must be > 0",
47 mutate: func(cfg *Config) {
48 cfg.Workspace.FloatingPane.WidthPct = 0
49 },
50 errorField: "workspace.floating_pane.width_pct",
51 },
52 {
53 name: "width must be <= 1",
54 mutate: func(cfg *Config) {
55 cfg.Workspace.FloatingPane.WidthPct = 1.5
56 },
57 errorField: "workspace.floating_pane.width_pct",
58 },
59 {
60 name: "height must be > 0",
61 mutate: func(cfg *Config) {
62 cfg.Workspace.FloatingPane.HeightPct = 0
63 },
64 errorField: "workspace.floating_pane.height_pct",
65 },
66 {
67 name: "height must be <= 1",
68 mutate: func(cfg *Config) {
69 cfg.Workspace.FloatingPane.HeightPct = 1.1
70 },
71 errorField: "workspace.floating_pane.height_pct",
72 },
73 }
74
75 for _, tt := range tests {
76 t.Run(tt.name, func(t *testing.T) {
77 cfg := DefaultConfig()
78 tt.mutate(cfg)
79
80 err := validateConfig(cfg)
81 require.Error(t, err)
82 assert.Contains(t, err.Error(), tt.errorField)
83 })
84 }
85}
86
87func TestFloatingPaneConfig_ProfileValidation(t *testing.T) {
88 t.Run("missing URL", func(t *testing.T) {
89 cfg := DefaultConfig()
90 cfg.Workspace.FloatingPane.Profiles = map[string]FloatingPaneProfile{
91 "google": {
92 URL: "",
93 Keys: []string{"alt+g"},
94 },
95 }
96
97 err := validateConfig(cfg)
98 require.Error(t, err)
99 assert.Contains(t, err.Error(), "workspace.floating_pane.profiles.google.url")
100 })
101
102 t.Run("missing keys", func(t *testing.T) {
103 cfg := DefaultConfig()
104 cfg.Workspace.FloatingPane.Profiles = map[string]FloatingPaneProfile{
105 "google": {
106 URL: "https://google.com",
107 Keys: nil,
108 },
109 }
110
111 err := validateConfig(cfg)
112 require.Error(t, err)
113 assert.Contains(t, err.Error(), "workspace.floating_pane.profiles.google.keys")
114 })
115
116 t.Run("whitespace-only key", func(t *testing.T) {
117 cfg := DefaultConfig()
118 cfg.Workspace.FloatingPane.Profiles = map[string]FloatingPaneProfile{
119 "google": {
120 URL: "https://google.com",
121 Keys: []string{" ", "alt+g"},
122 },
123 }
124
125 err := validateConfig(cfg)
126 require.Error(t, err)
127 assert.Contains(t, err.Error(), "empty or whitespace-only key binding")
128 })
129
130 t.Run("duplicate key binding", func(t *testing.T) {
131 cfg := DefaultConfig()
132 cfg.Workspace.FloatingPane.Profiles = map[string]FloatingPaneProfile{
133 "google": {
134 URL: "https://google.com",
135 Keys: []string{"alt+g"},
136 },
137 "github": {
138 URL: "https://github.com",
139 Keys: []string{"alt+g"},
140 },
141 }
142
143 err := validateConfig(cfg)
144 require.Error(t, err)
145 assert.Contains(t, err.Error(), "duplicate key binding")
146 })
147
148 t.Run("invalid URL scheme", func(t *testing.T) {
149 cfg := DefaultConfig()
150 cfg.Workspace.FloatingPane.Profiles = map[string]FloatingPaneProfile{
151 "invalid-scheme": {
152 URL: "ftp://example.com",
153 Keys: []string{"alt+i"},
154 },
155 }
156
157 err := validateConfig(cfg)
158 require.Error(t, err)
159 assert.Contains(t, err.Error(), "workspace.floating_pane.profiles.invalid-scheme.url")
160 assert.Contains(t, err.Error(), "must use one of: http, https, dumb, file, about")
161 })
162}
163
164func TestFloatingPaneConfig_ProfileMultiplicity(t *testing.T) {
165 cfg := DefaultConfig()
166 cfg.Workspace.FloatingPane.Profiles = map[string]FloatingPaneProfile{
167 "google": {
168 URL: "https://google.com",
169 Keys: []string{"alt+g"},
170 },
171 "github": {
172 URL: "https://github.com",
173 Keys: []string{"alt+h"},
174 },
175 }
176
177 err := validateConfig(cfg)
178 require.NoError(t, err)
179 assert.Len(t, cfg.Workspace.FloatingPane.Profiles, 2)
180}