diff --git a/graph/common/common.go b/graph/common/common.go index d1a6ae7..5882c4f 100644 --- a/graph/common/common.go +++ b/graph/common/common.go @@ -8,7 +8,7 @@ import ( ) var ( - colorScheme []sc.SimpleColor + colorScheme []sc.SimpleColor ) func CreateGraph() bytes.Buffer { diff --git a/graph/common/common_test.go b/graph/common/common_test.go new file mode 100644 index 0000000..e793e18 --- /dev/null +++ b/graph/common/common_test.go @@ -0,0 +1,125 @@ +package common + +import ( + "testing" + + sc "github.com/taigrr/simplecolorpalettes/simplecolor" +) + +func TestMinMax(t *testing.T) { + tests := []struct { + name string + input []int + wantMin int + wantMax int + }{ + { + name: "normal values", + input: []int{3, 1, 4, 1, 5, 9, 2, 6}, + wantMin: 1, + wantMax: 9, + }, + { + name: "with zeros", + input: []int{0, 3, 0, 7, 0, 2}, + wantMin: 2, + wantMax: 7, + }, + { + name: "all zeros", + input: []int{0, 0, 0}, + wantMin: 0, + wantMax: 0, + }, + { + name: "single element", + input: []int{5}, + wantMin: 5, + wantMax: 5, + }, + { + name: "single zero", + input: []int{0}, + wantMin: 0, + wantMax: 0, + }, + { + name: "all same non-zero", + input: []int{4, 4, 4}, + wantMin: 4, + wantMax: 4, + }, + { + name: "empty slice", + input: []int{}, + wantMin: 0, + wantMax: 0, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + min, max := MinMax(tt.input) + if min != tt.wantMin { + t.Errorf("min: expected %d, got %d", tt.wantMin, min) + } + if max != tt.wantMax { + t.Errorf("max: expected %d, got %d", tt.wantMax, max) + } + }) + } +} + +func TestColorForFrequency(t *testing.T) { + // freq=0 should always return SimpleColor(0) + c := ColorForFrequency(0, 1, 10) + if c != sc.SimpleColor(0) { + t.Errorf("expected SimpleColor(0) for freq=0, got %v", c) + } + + // Non-zero freq with small spread should return a valid color + c = ColorForFrequency(1, 1, 3) + if c == sc.SimpleColor(0) { + t.Error("expected non-zero color for freq=1 with small spread") + } + + // Non-zero freq with large spread + c = ColorForFrequency(50, 1, 100) + if c == sc.SimpleColor(0) { + t.Error("expected non-zero color for freq=50 in range 1-100") + } + + // Max frequency should return the last color + c = ColorForFrequency(100, 1, 100) + if c == sc.SimpleColor(0) { + t.Error("expected non-zero color for max frequency") + } + + // Min frequency should return first real color + c = ColorForFrequency(1, 1, 100) + if c == sc.SimpleColor(0) { + t.Error("expected non-zero color for min frequency") + } +} + +func TestCreateGraph(t *testing.T) { + buf := CreateGraph() + if buf.Len() != 0 { + t.Errorf("expected empty buffer, got %d bytes", buf.Len()) + } +} + +func TestSetColorScheme(t *testing.T) { + // Save original length + origLen := len(colorScheme) + + // Reset after test + defer func() { + colorScheme = colorScheme[:origLen] + }() + + // SetColorScheme should append colors + SetColorScheme(nil) + if len(colorScheme) != origLen { + t.Errorf("expected length %d after nil input, got %d", origLen, len(colorScheme)) + } +} diff --git a/types/types_test.go b/types/types_test.go new file mode 100644 index 0000000..0219703 --- /dev/null +++ b/types/types_test.go @@ -0,0 +1,137 @@ +package types + +import ( + "strings" + "testing" + "time" +) + +func TestNewDataSet(t *testing.T) { + ds := NewDataSet() + if ds == nil { + t.Fatal("NewDataSet returned nil") + } + if len(ds) != 0 { + t.Fatalf("expected empty DataSet, got %d entries", len(ds)) + } +} + +func TestNewCommit(t *testing.T) { + c := NewCommit("Alice", "alice@example.com", "initial commit", "myrepo", "/tmp/myrepo", 10, 2, 3) + if c.Author.Name != "Alice" { + t.Errorf("expected author name Alice, got %s", c.Author.Name) + } + if c.Author.Email != "alice@example.com" { + t.Errorf("expected author email alice@example.com, got %s", c.Author.Email) + } + if c.Message != "initial commit" { + t.Errorf("expected message 'initial commit', got %s", c.Message) + } + if c.Added != 10 { + t.Errorf("expected Added=10, got %d", c.Added) + } + if c.Deleted != 2 { + t.Errorf("expected Deleted=2, got %d", c.Deleted) + } + if c.FilesChanged != 3 { + t.Errorf("expected FilesChanged=3, got %d", c.FilesChanged) + } + if c.Repo != "myrepo" { + t.Errorf("expected Repo=myrepo, got %s", c.Repo) + } + if c.Path != "/tmp/myrepo" { + t.Errorf("expected Path=/tmp/myrepo, got %s", c.Path) + } + if c.TimeStamp.IsZero() { + t.Error("expected non-zero timestamp") + } +} + +func TestCommitString(t *testing.T) { + ts := time.Date(2025, 6, 15, 14, 30, 0, 0, time.UTC) + c := Commit{ + TimeStamp: ts, + Author: Author{Name: "Bob", Email: "bob@example.com"}, + Repo: "testrepo", + Message: "fix bug", + } + s := c.String() + if !strings.Contains(s, "testrepo") { + t.Errorf("expected string to contain repo name, got: %s", s) + } + if !strings.Contains(s, "fix bug") { + t.Errorf("expected string to contain message, got: %s", s) + } +} + +func TestFreqMerge(t *testing.T) { + tests := []struct { + name string + a, b Freq + want Freq + }{ + { + name: "equal length", + a: Freq{1, 2, 3}, + b: Freq{4, 5, 6}, + want: Freq{5, 7, 9}, + }, + { + name: "a shorter than b", + a: Freq{1, 2}, + b: Freq{3, 4, 5}, + want: Freq{4, 6, 5}, + }, + { + name: "b shorter than a", + a: Freq{1, 2, 3}, + b: Freq{4, 5}, + want: Freq{5, 7, 3}, + }, + { + name: "empty a", + a: Freq{}, + b: Freq{1, 2, 3}, + want: Freq{1, 2, 3}, + }, + { + name: "empty b", + a: Freq{1, 2, 3}, + b: Freq{}, + want: Freq{1, 2, 3}, + }, + { + name: "both empty", + a: Freq{}, + b: Freq{}, + want: Freq{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.a.Merge(tt.b) + if len(got) != len(tt.want) { + t.Fatalf("expected length %d, got %d", len(tt.want), len(got)) + } + for i := range tt.want { + if got[i] != tt.want[i] { + t.Errorf("index %d: expected %d, got %d", i, tt.want[i], got[i]) + } + } + }) + } +} + +func TestDataSetOperations(t *testing.T) { + ds := NewDataSet() + now := time.Now().Truncate(24 * time.Hour) + ds[now] = WorkDay{ + Day: now, + Count: 5, + } + if wd, ok := ds[now]; !ok { + t.Fatal("expected to find workday for today") + } else if wd.Count != 5 { + t.Errorf("expected count 5, got %d", wd.Count) + } +} diff --git a/ui/settings.go b/ui/settings.go index 1cbb769..4c787e2 100644 --- a/ui/settings.go +++ b/ui/settings.go @@ -17,13 +17,13 @@ const ( type ( SettingsCursor int Settings struct { - AllAuthors selectablelist - SelectedAuthors []string - AllRepos selectablelist - SelectedRepos []string - cursor SettingsCursor - AuthorList list.Model - RepoList list.Model + AllAuthors selectablelist + SelectedAuthors []string + AllRepos selectablelist + SelectedRepos []string + cursor SettingsCursor + AuthorList list.Model + RepoList list.Model } )