cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm leaflet readability golang
29
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 318 lines 8.1 kB view raw
1package handlers 2 3import ( 4 "bytes" 5 "io" 6 "os" 7 "path/filepath" 8 "strings" 9 "testing" 10 11 "github.com/stormlightlabs/noteleaf/internal/shared" 12 "github.com/stormlightlabs/noteleaf/internal/store" 13) 14 15func TestConfigHandler(t *testing.T) { 16 t.Run("Get", func(t *testing.T) { 17 tempDir, cleanup := shared.CreateTempDir("noteleaf-config-handler-get-test-*", t) 18 defer cleanup() 19 20 customConfigPath := filepath.Join(tempDir, "test-config.toml") 21 originalEnv := os.Getenv("NOTELEAF_CONFIG") 22 os.Setenv("NOTELEAF_CONFIG", customConfigPath) 23 defer os.Setenv("NOTELEAF_CONFIG", originalEnv) 24 25 config := store.DefaultConfig() 26 config.ColorScheme = "test-scheme" 27 config.Editor = "vim" 28 if err := store.SaveConfig(config); err != nil { 29 t.Fatalf("Failed to save config: %v", err) 30 } 31 32 t.Run("Get all config values", func(t *testing.T) { 33 handler, err := NewConfigHandler() 34 if err != nil { 35 t.Fatalf("Failed to create handler: %v", err) 36 } 37 38 oldStdout := os.Stdout 39 r, w, _ := os.Pipe() 40 os.Stdout = w 41 42 err = handler.Get("") 43 if err != nil { 44 t.Fatalf("Get failed: %v", err) 45 } 46 47 w.Close() 48 os.Stdout = oldStdout 49 50 var buf bytes.Buffer 51 io.Copy(&buf, r) 52 output := buf.String() 53 54 if !strings.Contains(output, "color_scheme") { 55 t.Error("Output should contain color_scheme") 56 } 57 if !strings.Contains(output, "test-scheme") { 58 t.Error("Output should contain test-scheme value") 59 } 60 }) 61 62 t.Run("Get specific config value", func(t *testing.T) { 63 handler, err := NewConfigHandler() 64 if err != nil { 65 t.Fatalf("Failed to create handler: %v", err) 66 } 67 68 oldStdout := os.Stdout 69 r, w, _ := os.Pipe() 70 os.Stdout = w 71 72 err = handler.Get("editor") 73 if err != nil { 74 t.Fatalf("Get failed: %v", err) 75 } 76 77 w.Close() 78 os.Stdout = oldStdout 79 80 var buf bytes.Buffer 81 io.Copy(&buf, r) 82 output := buf.String() 83 84 if !strings.Contains(output, "editor = vim") { 85 t.Errorf("Output should contain 'editor = vim', got: %s", output) 86 } 87 }) 88 89 t.Run("Get unknown config key", func(t *testing.T) { 90 handler, err := NewConfigHandler() 91 if err != nil { 92 t.Fatalf("Failed to create handler: %v", err) 93 } 94 95 err = handler.Get("nonexistent_key") 96 if err == nil { 97 t.Error("Get should fail for unknown key") 98 } 99 if !strings.Contains(err.Error(), "unknown config key") { 100 t.Errorf("Error should mention unknown config key, got: %v", err) 101 } 102 }) 103 }) 104 105 t.Run("Set", func(t *testing.T) { 106 tempDir, cleanup := shared.CreateTempDir("noteleaf-config-handler-set-test-*", t) 107 defer cleanup() 108 109 customConfigPath := filepath.Join(tempDir, "test-config.toml") 110 originalEnv := os.Getenv("NOTELEAF_CONFIG") 111 os.Setenv("NOTELEAF_CONFIG", customConfigPath) 112 defer os.Setenv("NOTELEAF_CONFIG", originalEnv) 113 114 t.Run("Set string config value", func(t *testing.T) { 115 handler, err := NewConfigHandler() 116 if err != nil { 117 t.Fatalf("Failed to create handler: %v", err) 118 } 119 120 oldStdout := os.Stdout 121 r, w, _ := os.Pipe() 122 os.Stdout = w 123 124 err = handler.Set("editor", "emacs") 125 if err != nil { 126 t.Fatalf("Set failed: %v", err) 127 } 128 129 w.Close() 130 os.Stdout = oldStdout 131 132 var buf bytes.Buffer 133 io.Copy(&buf, r) 134 output := buf.String() 135 136 if !strings.Contains(output, "Set editor = emacs") { 137 t.Errorf("Output should confirm setting, got: %s", output) 138 } 139 140 loadedConfig, err := store.LoadConfig() 141 if err != nil { 142 t.Fatalf("Failed to load config: %v", err) 143 } 144 145 if loadedConfig.Editor != "emacs" { 146 t.Errorf("Expected editor 'emacs', got '%s'", loadedConfig.Editor) 147 } 148 }) 149 150 t.Run("Set boolean config value", func(t *testing.T) { 151 handler, err := NewConfigHandler() 152 if err != nil { 153 t.Fatalf("Failed to create handler: %v", err) 154 } 155 156 err = handler.Set("auto_archive", "true") 157 if err != nil { 158 t.Fatalf("Set failed: %v", err) 159 } 160 161 loadedConfig, err := store.LoadConfig() 162 if err != nil { 163 t.Fatalf("Failed to load config: %v", err) 164 } 165 166 if !loadedConfig.AutoArchive { 167 t.Error("Expected auto_archive to be true") 168 } 169 }) 170 171 t.Run("Set boolean config value with various formats", func(t *testing.T) { 172 tc := []struct { 173 value string 174 expected bool 175 }{ 176 {"true", true}, 177 {"1", true}, 178 {"yes", true}, 179 {"false", false}, 180 {"0", false}, 181 {"no", false}, 182 } 183 184 for _, tt := range tc { 185 handler, err := NewConfigHandler() 186 if err != nil { 187 t.Fatalf("Failed to create handler: %v", err) 188 } 189 190 err = handler.Set("sync_enabled", tt.value) 191 if err != nil { 192 t.Fatalf("Set failed for value '%s': %v", tt.value, err) 193 } 194 195 loadedConfig, err := store.LoadConfig() 196 if err != nil { 197 t.Fatalf("Failed to load config: %v", err) 198 } 199 200 if loadedConfig.SyncEnabled != tt.expected { 201 t.Errorf("For value '%s', expected sync_enabled %v, got %v", tt.value, tt.expected, loadedConfig.SyncEnabled) 202 } 203 } 204 }) 205 206 t.Run("Set unknown config key", func(t *testing.T) { 207 handler, err := NewConfigHandler() 208 if err != nil { 209 t.Fatalf("Failed to create handler: %v", err) 210 } 211 212 err = handler.Set("nonexistent_key", "value") 213 if err == nil { 214 t.Error("Set should fail for unknown key") 215 } 216 if !strings.Contains(err.Error(), "unknown config key") { 217 t.Errorf("Error should mention unknown config key, got: %v", err) 218 } 219 }) 220 }) 221 t.Run("Path", func(t *testing.T) { 222 tempDir, cleanup := shared.CreateTempDir("noteleaf-config-handler-path-test-*", t) 223 defer cleanup() 224 225 customConfigPath := filepath.Join(tempDir, "my-config.toml") 226 originalEnv := os.Getenv("NOTELEAF_CONFIG") 227 os.Setenv("NOTELEAF_CONFIG", customConfigPath) 228 defer os.Setenv("NOTELEAF_CONFIG", originalEnv) 229 230 t.Run("Path returns correct config file path", func(t *testing.T) { 231 handler, err := NewConfigHandler() 232 if err != nil { 233 t.Fatalf("Failed to create handler: %v", err) 234 } 235 236 oldStdout := os.Stdout 237 r, w, _ := os.Pipe() 238 os.Stdout = w 239 240 err = handler.Path() 241 if err != nil { 242 t.Fatalf("Path failed: %v", err) 243 } 244 245 w.Close() 246 os.Stdout = oldStdout 247 248 var buf bytes.Buffer 249 io.Copy(&buf, r) 250 output := strings.TrimSpace(buf.String()) 251 252 if output != customConfigPath { 253 t.Errorf("Expected path '%s', got '%s'", customConfigPath, output) 254 } 255 }) 256 }) 257 258 t.Run("Reset", func(t *testing.T) { 259 tempDir, cleanup := shared.CreateTempDir("noteleaf-config-handler-reset-test-*", t) 260 defer cleanup() 261 262 customConfigPath := filepath.Join(tempDir, "test-config.toml") 263 originalEnv := os.Getenv("NOTELEAF_CONFIG") 264 os.Setenv("NOTELEAF_CONFIG", customConfigPath) 265 defer os.Setenv("NOTELEAF_CONFIG", originalEnv) 266 267 t.Run("Reset restores default config", func(t *testing.T) { 268 config := store.DefaultConfig() 269 config.ColorScheme = "custom" 270 config.AutoArchive = true 271 config.Editor = "emacs" 272 if err := store.SaveConfig(config); err != nil { 273 t.Fatalf("Failed to save config: %v", err) 274 } 275 276 handler, err := NewConfigHandler() 277 if err != nil { 278 t.Fatalf("Failed to create handler: %v", err) 279 } 280 281 oldStdout := os.Stdout 282 r, w, _ := os.Pipe() 283 os.Stdout = w 284 285 err = handler.Reset() 286 if err != nil { 287 t.Fatalf("Reset failed: %v", err) 288 } 289 290 w.Close() 291 os.Stdout = oldStdout 292 293 var buf bytes.Buffer 294 io.Copy(&buf, r) 295 output := buf.String() 296 297 if !strings.Contains(output, "reset to defaults") { 298 t.Errorf("Output should confirm reset, got: %s", output) 299 } 300 301 loadedConfig, err := store.LoadConfig() 302 if err != nil { 303 t.Fatalf("Failed to load config: %v", err) 304 } 305 306 defaultConfig := store.DefaultConfig() 307 if loadedConfig.ColorScheme != defaultConfig.ColorScheme { 308 t.Errorf("ColorScheme should be reset to default '%s', got '%s'", defaultConfig.ColorScheme, loadedConfig.ColorScheme) 309 } 310 if loadedConfig.AutoArchive != defaultConfig.AutoArchive { 311 t.Errorf("AutoArchive should be reset to default %v, got %v", defaultConfig.AutoArchive, loadedConfig.AutoArchive) 312 } 313 if loadedConfig.Editor != defaultConfig.Editor { 314 t.Errorf("Editor should be reset to default '%s', got '%s'", defaultConfig.Editor, loadedConfig.Editor) 315 } 316 }) 317 }) 318}