summaryrefslogtreecommitdiff
path: root/internal/cli/root_test.go
blob: 2b12514c61950986557f8adfd85d52f01537a229 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package cli

import (
	"bytes"
	"io"
	"os"
	"path/filepath"
	"strings"
	"testing"

	timr "codeberg.org/snonux/timr/internal"
)

func TestRootVersionFlag(t *testing.T) {
	var out bytes.Buffer
	cmd := NewRootCmd()
	cmd.SetOut(&out)
	cmd.SetErr(io.Discard)
	cmd.SetArgs([]string{"--version"})

	if err := cmd.Execute(); err != nil {
		t.Fatalf("Execute() error = %v", err)
	}

	if strings.TrimSpace(out.String()) != timr.Version {
		t.Fatalf("output = %q, want %q", strings.TrimSpace(out.String()), timr.Version)
	}
}

func TestRootLoadsConfigInPersistentPreRun(t *testing.T) {
	tempHome := t.TempDir()
	t.Setenv("HOME", tempHome)

	cfgPath := filepath.Join(t.TempDir(), "config.json")
	content := `{
  "hostname": "from-config",
  "worktime_db_dir": "~/custom-db"
}`
	if err := os.WriteFile(cfgPath, []byte(content), 0o644); err != nil {
		t.Fatalf("WriteFile() error = %v", err)
	}

	cmd := NewRootCmd()
	cmd.SetOut(io.Discard)
	cmd.SetErr(io.Discard)
	cmd.SetArgs([]string{"--config", cfgPath})

	if err := cmd.Execute(); err != nil {
		t.Fatalf("Execute() error = %v", err)
	}

	cfg := currentConfig(cmd)
	if cfg.Hostname != "from-config" {
		t.Fatalf("Hostname = %q, want %q", cfg.Hostname, "from-config")
	}

	wantDir := filepath.Join(tempHome, "custom-db")
	if cfg.WorktimeDBDir != wantDir {
		t.Fatalf("WorktimeDBDir = %q, want %q", cfg.WorktimeDBDir, wantDir)
	}
}

func TestRootInvalidConfigFileReturnsError(t *testing.T) {
	cfgPath := filepath.Join(t.TempDir(), "config.json")
	if err := os.WriteFile(cfgPath, []byte(`{"hostname":`), 0o644); err != nil {
		t.Fatalf("WriteFile() error = %v", err)
	}

	cmd := NewRootCmd()
	cmd.SetOut(io.Discard)
	cmd.SetErr(io.Discard)
	cmd.SetArgs([]string{"--config", cfgPath})

	err := cmd.Execute()
	if err == nil {
		t.Fatal("Execute() error = nil, want config parse error")
	}
	if !strings.Contains(err.Error(), "load config") {
		t.Fatalf("Execute() error = %v, want load config context", err)
	}
}

func TestVersionSkipsConfigLoading(t *testing.T) {
	cfgPath := filepath.Join(t.TempDir(), "config.json")
	if err := os.WriteFile(cfgPath, []byte(`{"hostname":`), 0o644); err != nil {
		t.Fatalf("WriteFile() error = %v", err)
	}

	var out bytes.Buffer
	cmd := NewRootCmd()
	cmd.SetOut(&out)
	cmd.SetErr(io.Discard)
	cmd.SetArgs([]string{"--config", cfgPath, "--version"})

	if err := cmd.Execute(); err != nil {
		t.Fatalf("Execute() error = %v", err)
	}

	if strings.TrimSpace(out.String()) != timr.Version {
		t.Fatalf("output = %q, want %q", strings.TrimSpace(out.String()), timr.Version)
	}
}

func TestRootUsesDefaultConfigWhenNoFileExists(t *testing.T) {
	tempHome := t.TempDir()
	t.Setenv("HOME", tempHome)
	t.Setenv("XDG_CONFIG_HOME", filepath.Join(tempHome, ".config"))

	cmd := NewRootCmd()
	cmd.SetOut(io.Discard)
	cmd.SetErr(io.Discard)

	if err := cmd.Execute(); err != nil {
		t.Fatalf("Execute() error = %v", err)
	}

	cfg := currentConfig(cmd)
	if cfg.WeekWorkHours != 40 {
		t.Fatalf("WeekWorkHours = %v, want 40", cfg.WeekWorkHours)
	}

	wantDir := filepath.Join(tempHome, "git", "worktime")
	if cfg.WorktimeDBDir != wantDir {
		t.Fatalf("WorktimeDBDir = %q, want %q", cfg.WorktimeDBDir, wantDir)
	}
}