Files
relspecgo/pkg/writers/template/loop_helpers_test.go
T
warkanum 495a21b67b test: expand coverage across readers, writers, cmd, ui, diff and merge
Implements tests/_plans and previously deferred packages; updates plan
README with new coverage numbers.
2026-10-03 21:33:59 +02:00

143 lines
3.8 KiB
Go

package template
import (
"reflect"
"testing"
)
type loopItem struct {
Name string
Group string
N int
}
func ints(vs ...interface{}) []interface{} { return vs }
func TestEnumerate(t *testing.T) {
got := Enumerate([]string{"a", "b"})
want := []EnumeratedItem{{0, "a"}, {1, "b"}}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v", got)
}
if got := Enumerate([2]int{5, 6}); len(got) != 2 || got[1].Value != 6 {
t.Errorf("array: %v", got)
}
if got := Enumerate("nope"); len(got) != 0 {
t.Errorf("non-slice: %v", got)
}
if got := Enumerate(nil); len(got) != 0 {
t.Errorf("nil: %v", got)
}
if got := Enumerate([]int{}); len(got) != 0 {
t.Errorf("empty: %v", got)
}
}
func TestBatchChunk(t *testing.T) {
in := []int{1, 2, 3, 4, 5}
got := Batch(in, 2)
want := [][]interface{}{{1, 2}, {3, 4}, {5}}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v", got)
}
if got := Chunk(in, 10); len(got) != 1 || len(got[0]) != 5 {
t.Errorf("size > len: %v", got)
}
for _, size := range []int{0, -1} {
if got := Batch(in, size); len(got) != 0 {
t.Errorf("size %d: %v", size, got)
}
}
if got := Batch([]int{}, 2); len(got) != 0 {
t.Errorf("empty: %v", got)
}
if got := Batch("x", 2); len(got) != 0 {
t.Errorf("non-slice: %v", got)
}
}
func TestReverseFirstLastSkipTake(t *testing.T) {
in := []int{1, 2, 3, 4}
tests := []struct {
name string
got []interface{}
want []interface{}
}{
{"reverse", Reverse(in), ints(4, 3, 2, 1)},
{"reverse empty", Reverse([]int{}), ints()},
{"reverse non-slice", Reverse(5), ints()},
{"first 2", First(in, 2), ints(1, 2)},
{"first n>len", First(in, 9), ints(1, 2, 3, 4)},
{"first 0", First(in, 0), ints()},
{"first non-slice", First(5, 1), ints()},
{"last 2", Last(in, 2), ints(3, 4)},
{"last n>len", Last(in, 9), ints(1, 2, 3, 4)},
{"last neg", Last(in, -1), ints()},
{"last non-slice", Last(5, 1), ints()},
{"skip 1", Skip(in, 1), ints(2, 3, 4)},
{"skip neg", Skip(in, -3), ints(1, 2, 3, 4)},
{"skip all", Skip(in, 4), ints()},
{"skip n>len", Skip(in, 10), ints()},
{"skip non-slice", Skip(5, 1), ints()},
{"take", Take(in, 3), ints(1, 2, 3)},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if len(tt.got) != len(tt.want) || (len(tt.want) > 0 && !reflect.DeepEqual(tt.got, tt.want)) {
t.Errorf("got %v, want %v", tt.got, tt.want)
}
})
}
}
func TestConcatUnique(t *testing.T) {
got := Concat([]int{1, 2}, []string{"a"}, 5, nil, [1]int{9})
if !reflect.DeepEqual(got, ints(1, 2, "a", 9)) {
t.Errorf("concat: %v", got)
}
if got := Concat(); len(got) != 0 {
t.Errorf("concat none: %v", got)
}
if got := Unique([]int{1, 2, 1, 3, 2}); !reflect.DeepEqual(got, ints(1, 2, 3)) {
t.Errorf("unique: %v", got)
}
if got := Unique("x"); len(got) != 0 {
t.Errorf("unique non-slice: %v", got)
}
}
func TestSortByGroupByCountIf(t *testing.T) {
items := []loopItem{{"c", "x", 3}, {"a", "y", 1}, {"b", "x", 2}}
sorted := SortBy(items, "Name")
if sorted[0].(loopItem).Name != "a" || sorted[2].(loopItem).Name != "c" {
t.Errorf("sortBy Name: %v", sorted)
}
sorted = SortBy(items, "N")
if sorted[0].(loopItem).N != 1 || sorted[2].(loopItem).N != 3 {
t.Errorf("sortBy N: %v", sorted)
}
if items[0].Name != "c" {
t.Errorf("SortBy must not mutate input")
}
if got := SortBy(5, "Name"); len(got) != 0 {
t.Errorf("sortBy non-slice")
}
groups := GroupBy(items, "Group")
if len(groups) != 2 || len(groups["x"]) != 2 || len(groups["y"]) != 1 {
t.Errorf("groupBy: %v", groups)
}
if got := GroupBy(5, "Group"); len(got) != 0 {
t.Errorf("groupBy non-slice")
}
n := CountIf(items, func(v interface{}) bool { return v.(loopItem).Group == "x" })
if n != 2 {
t.Errorf("countIf: %d", n)
}
if got := CountIf(5, func(interface{}) bool { return true }); got != 0 {
t.Errorf("countIf non-slice: %d", got)
}
}