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) } }