summaryrefslogtreecommitdiff
path: root/internal/config/config_test.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-02-03 15:16:35 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-02-03 15:16:35 -1000
commit25a5b7ecf9ddd31da54e91f87988b77aea857571 (patch)
tree30654edbdd966cea316a5f54a99474aad337cf58 /internal/config/config_test.go
parent9f35f7149d8fb790bbe8e4f0ee74f895aea1fc58 (diff)
Add comprehensive test coverage across packages
New test files: - api/http_test.go: HTTP client and error handling tests - config/config_test.go: Configuration loading and validation tests - middleware/security_test.go: Security middleware tests - models/atom_test.go: Atom model and conversion tests Expanded test coverage: - api/todoist_test.go: Todoist API client tests - api/trello_test.go: Trello API client tests - auth/auth_test.go: Authentication and CSRF tests - handlers/timeline_logic_test.go: Timeline building logic tests - store/sqlite_test.go: SQLite store operations tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/config/config_test.go')
-rw-r--r--internal/config/config_test.go289
1 files changed, 289 insertions, 0 deletions
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
new file mode 100644
index 0000000..41cd6e0
--- /dev/null
+++ b/internal/config/config_test.go
@@ -0,0 +1,289 @@
+package config
+
+import (
+ "os"
+ "testing"
+ "time"
+)
+
+func TestConfigValidate(t *testing.T) {
+ tests := []struct {
+ name string
+ cfg Config
+ wantErr bool
+ }{
+ {
+ name: "valid config",
+ cfg: Config{
+ TodoistAPIKey: "todoist-key",
+ TrelloAPIKey: "trello-key",
+ TrelloToken: "trello-token",
+ },
+ wantErr: false,
+ },
+ {
+ name: "missing todoist key",
+ cfg: Config{
+ TrelloAPIKey: "trello-key",
+ TrelloToken: "trello-token",
+ },
+ wantErr: true,
+ },
+ {
+ name: "missing trello key",
+ cfg: Config{
+ TodoistAPIKey: "todoist-key",
+ TrelloToken: "trello-token",
+ },
+ wantErr: true,
+ },
+ {
+ name: "missing trello token",
+ cfg: Config{
+ TodoistAPIKey: "todoist-key",
+ TrelloAPIKey: "trello-key",
+ },
+ wantErr: true,
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ err := tc.cfg.Validate()
+ if (err != nil) != tc.wantErr {
+ t.Errorf("Validate() error = %v, wantErr %v", err, tc.wantErr)
+ }
+ })
+ }
+}
+
+func TestConfigHasMethods(t *testing.T) {
+ cfg := Config{
+ PlanToEatAPIKey: "pte-key",
+ TrelloAPIKey: "trello-key",
+ TrelloToken: "trello-token",
+ GoogleCredentialsFile: "/path/to/creds.json",
+ GoogleTasksListID: "@default",
+ }
+
+ if !cfg.HasPlanToEat() {
+ t.Error("HasPlanToEat should return true")
+ }
+
+ if !cfg.HasTrello() {
+ t.Error("HasTrello should return true")
+ }
+
+ if !cfg.HasGoogleCalendar() {
+ t.Error("HasGoogleCalendar should return true")
+ }
+
+ if !cfg.HasGoogleTasks() {
+ t.Error("HasGoogleTasks should return true")
+ }
+
+ // Test with empty config
+ emptyCfg := Config{}
+ if emptyCfg.HasPlanToEat() {
+ t.Error("HasPlanToEat should return false for empty config")
+ }
+ if emptyCfg.HasTrello() {
+ t.Error("HasTrello should return false for empty config")
+ }
+ if emptyCfg.HasGoogleCalendar() {
+ t.Error("HasGoogleCalendar should return false for empty config")
+ }
+ if emptyCfg.HasGoogleTasks() {
+ t.Error("HasGoogleTasks should return false for empty config")
+ }
+
+ // Test session check
+ sessionCfg := Config{PlanToEatSession: "session-cookie"}
+ if !sessionCfg.HasPlanToEat() {
+ t.Error("HasPlanToEat should return true for session")
+ }
+ if !sessionCfg.HasPlanToEatSession() {
+ t.Error("HasPlanToEatSession should return true")
+ }
+}
+
+func TestGetEnvWithDefault(t *testing.T) {
+ // Test with set env var
+ os.Setenv("TEST_CONFIG_VAR", "test_value")
+ defer os.Unsetenv("TEST_CONFIG_VAR")
+
+ if val := getEnvWithDefault("TEST_CONFIG_VAR", "default"); val != "test_value" {
+ t.Errorf("Expected 'test_value', got '%s'", val)
+ }
+
+ // Test with unset env var
+ if val := getEnvWithDefault("UNSET_CONFIG_VAR", "default"); val != "default" {
+ t.Errorf("Expected 'default', got '%s'", val)
+ }
+}
+
+func TestGetEnvAsInt(t *testing.T) {
+ // Test with valid int
+ os.Setenv("TEST_INT_VAR", "42")
+ defer os.Unsetenv("TEST_INT_VAR")
+
+ if val := getEnvAsInt("TEST_INT_VAR", 10); val != 42 {
+ t.Errorf("Expected 42, got %d", val)
+ }
+
+ // Test with invalid int
+ os.Setenv("TEST_INVALID_INT", "not_a_number")
+ defer os.Unsetenv("TEST_INVALID_INT")
+
+ if val := getEnvAsInt("TEST_INVALID_INT", 10); val != 10 {
+ t.Errorf("Expected default 10 for invalid int, got %d", val)
+ }
+
+ // Test with unset var
+ if val := getEnvAsInt("UNSET_INT_VAR", 10); val != 10 {
+ t.Errorf("Expected default 10, got %d", val)
+ }
+}
+
+func TestGetEnvAsBool(t *testing.T) {
+ // Test with true values
+ os.Setenv("TEST_BOOL_TRUE", "true")
+ defer os.Unsetenv("TEST_BOOL_TRUE")
+
+ if val := getEnvAsBool("TEST_BOOL_TRUE", false); !val {
+ t.Error("Expected true")
+ }
+
+ // Test with false values
+ os.Setenv("TEST_BOOL_FALSE", "false")
+ defer os.Unsetenv("TEST_BOOL_FALSE")
+
+ if val := getEnvAsBool("TEST_BOOL_FALSE", true); val {
+ t.Error("Expected false")
+ }
+
+ // Test with invalid bool
+ os.Setenv("TEST_INVALID_BOOL", "maybe")
+ defer os.Unsetenv("TEST_INVALID_BOOL")
+
+ if val := getEnvAsBool("TEST_INVALID_BOOL", true); !val {
+ t.Error("Expected default true for invalid bool")
+ }
+
+ // Test with unset var
+ if val := getEnvAsBool("UNSET_BOOL_VAR", true); !val {
+ t.Error("Expected default true")
+ }
+}
+
+// Timezone tests
+func TestGetDisplayTimezone(t *testing.T) {
+ // Before SetDisplayTimezone is called, should return UTC
+ loc := GetDisplayTimezone()
+ if loc == nil {
+ t.Fatal("GetDisplayTimezone should not return nil")
+ }
+}
+
+func TestNow(t *testing.T) {
+ now := Now()
+ // Just verify it returns a valid time
+ if now.IsZero() {
+ t.Error("Now() should not return zero time")
+ }
+}
+
+func TestToday(t *testing.T) {
+ today := Today()
+
+ // Today should have zero hours, minutes, seconds
+ if today.Hour() != 0 || today.Minute() != 0 || today.Second() != 0 {
+ t.Error("Today() should return midnight")
+ }
+}
+
+func TestParseDateInDisplayTZ(t *testing.T) {
+ parsed, err := ParseDateInDisplayTZ("2024-01-15")
+ if err != nil {
+ t.Fatalf("ParseDateInDisplayTZ failed: %v", err)
+ }
+
+ if parsed.Year() != 2024 || parsed.Month() != time.January || parsed.Day() != 15 {
+ t.Errorf("Unexpected date: %v", parsed)
+ }
+
+ // Test invalid date
+ _, err = ParseDateInDisplayTZ("invalid")
+ if err == nil {
+ t.Error("Expected error for invalid date")
+ }
+}
+
+func TestParseDateTimeInDisplayTZ(t *testing.T) {
+ parsed, err := ParseDateTimeInDisplayTZ("2006-01-02 15:04", "2024-01-15 14:30")
+ if err != nil {
+ t.Fatalf("ParseDateTimeInDisplayTZ failed: %v", err)
+ }
+
+ if parsed.Hour() != 14 || parsed.Minute() != 30 {
+ t.Errorf("Unexpected time: %v", parsed)
+ }
+}
+
+func TestToDisplayTZ(t *testing.T) {
+ utcTime := time.Date(2024, 1, 15, 12, 0, 0, 0, time.UTC)
+ converted := ToDisplayTZ(utcTime)
+
+ // Just verify it doesn't panic and returns a valid time
+ if converted.IsZero() {
+ t.Error("ToDisplayTZ should not return zero time")
+ }
+}
+
+func TestLoad(t *testing.T) {
+ // Set up required env vars
+ os.Setenv("TODOIST_API_KEY", "test-todoist-key")
+ os.Setenv("TRELLO_API_KEY", "test-trello-key")
+ os.Setenv("TRELLO_TOKEN", "test-trello-token")
+ os.Setenv("PORT", "9999")
+ os.Setenv("CACHE_TTL_MINUTES", "10")
+ os.Setenv("DEBUG", "true")
+ defer func() {
+ os.Unsetenv("TODOIST_API_KEY")
+ os.Unsetenv("TRELLO_API_KEY")
+ os.Unsetenv("TRELLO_TOKEN")
+ os.Unsetenv("PORT")
+ os.Unsetenv("CACHE_TTL_MINUTES")
+ os.Unsetenv("DEBUG")
+ }()
+
+ cfg, err := Load()
+ if err != nil {
+ t.Fatalf("Load failed: %v", err)
+ }
+
+ if cfg.TodoistAPIKey != "test-todoist-key" {
+ t.Errorf("Expected TodoistAPIKey 'test-todoist-key', got '%s'", cfg.TodoistAPIKey)
+ }
+ if cfg.Port != "9999" {
+ t.Errorf("Expected Port '9999', got '%s'", cfg.Port)
+ }
+ if cfg.CacheTTLMinutes != 10 {
+ t.Errorf("Expected CacheTTLMinutes 10, got %d", cfg.CacheTTLMinutes)
+ }
+ if !cfg.Debug {
+ t.Error("Expected Debug to be true")
+ }
+}
+
+func TestLoad_ValidationError(t *testing.T) {
+ // Clear required env vars to trigger validation error
+ os.Unsetenv("TODOIST_API_KEY")
+ os.Unsetenv("TRELLO_API_KEY")
+ os.Unsetenv("TRELLO_TOKEN")
+
+ _, err := Load()
+ if err == nil {
+ t.Error("Expected validation error when required env vars are missing")
+ }
+}