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
|
package worktime
import (
"strings"
"testing"
"time"
"codeberg.org/snonux/timesamurai/internal/config"
)
func TestComprehensiveDBRoundTripAndReportFixture(t *testing.T) {
dbDir := t.TempDir()
host := "fixture-host"
// Seed deterministic fixture entries via public operations.
if _, err := Login(dbDir, host, "work", mustDate(2026, 1, 5, 9, 0, 0), "start"); err != nil {
t.Fatalf("Login() error = %v", err)
}
if _, err := Logout(dbDir, host, "work", mustDate(2026, 1, 5, 17, 0, 0), "stop"); err != nil {
t.Fatalf("Logout() error = %v", err)
}
if _, err := Add(dbDir, host, "lunch", time.Hour, mustDate(2026, 1, 5, 12, 0, 0), "lunch"); err != nil {
t.Fatalf("Add(lunch) error = %v", err)
}
if _, err := Add(dbDir, host, "off", 8*time.Hour, mustDate(2026, 1, 6, 10, 0, 0), "off"); err != nil {
t.Fatalf("Add(off) error = %v", err)
}
// Round-trip from host file back to merged entries.
hostDB, err := LoadHost(dbDir, host)
if err != nil {
t.Fatalf("LoadHost() error = %v", err)
}
if len(hostDB.Entries[host]) != 4 {
t.Fatalf("host entries len = %d, want 4", len(hostDB.Entries[host]))
}
merged, err := LoadAll(dbDir)
if err != nil {
t.Fatalf("LoadAll() error = %v", err)
}
if len(merged) != 4 {
t.Fatalf("merged entries len = %d, want 4", len(merged))
}
cfg := config.Default()
report, err := BuildReport(merged, cfg)
if err != nil {
t.Fatalf("BuildReport() error = %v", err)
}
if len(report) != 1 {
t.Fatalf("weeks len = %d, want 1", len(report))
}
week := report[0]
if week.RequiredSeconds != 32*secondsPerHour {
t.Fatalf("required seconds = %d, want %d", week.RequiredSeconds, 32*secondsPerHour)
}
if week.Values["work"] != 7*secondsPerHour {
t.Fatalf("week work seconds = %d, want %d", week.Values["work"], 7*secondsPerHour)
}
if week.WeeklyBalanceSeconds != -25*secondsPerHour {
t.Fatalf("weekly balance = %d, want %d", week.WeeklyBalanceSeconds, -25*secondsPerHour)
}
rendered := FormatReport(report, false, false)
if !strings.Contains(rendered, "work:7.00h") {
t.Fatalf("rendered report missing expected work value: %q", rendered)
}
if !strings.Contains(rendered, "off:8.00h") {
t.Fatalf("rendered report missing expected off value: %q", rendered)
}
if !strings.Contains(rendered, "balance:-25.00h") {
t.Fatalf("rendered report missing expected balance value: %q", rendered)
}
}
func mustDate(year int, month time.Month, day int, hour int, minute int, second int) time.Time {
return time.Date(year, month, day, hour, minute, second, 0, time.Local)
}
|