internal/issues/page_test.go
Rama main · réplica de lectura del repositorio original.
package issues
import (
"encoding/base64"
"errors"
"slices"
"strconv"
"testing"
"time"
"github.com/sophotechlabs/spinoza/internal/api"
)
func rowsAcrossEveryOrderingField() []api.Issue {
severities := []string{api.SeverityLow, api.SeverityMedium, api.SeverityHigh, "info"}
folded := []int{0, 3, 50}
when := []string{
"",
testNow.Add(-time.Hour).UTC().Format(time.RFC3339),
testNow.UTC().Format(time.RFC3339),
}
clusters := []string{"alpha", "beta"}
out := make([]api.Issue, 0, len(severities)*len(folded)*len(when)*len(clusters))
for _, severity := range severities {
for _, fold := range folded {
for _, since := range when {
for _, cluster := range clusters {
out = append(out, api.Issue{
ID: cluster + "/" + severity + "/" + strconv.Itoa(fold) + "/" + since,
Severity: severity,
Folded: fold,
Since: since,
Cluster: cluster,
})
}
}
}
}
return out
}
func TestTheCursorKeyOrdersRowsTheWayRankDoes(t *testing.T) {
rows := rowsAcrossEveryOrderingField()
Rank(rows, ByWorst)
for at := 1; at < len(rows); at++ {
before := issueKey(rows[at-1], ByWorst)
after := issueKey(rows[at], ByWorst)
if before >= after {
t.Fatalf(
"row %d sorts before row %d but its key does not: %q >= %q",
at-1, at, before, after,
)
}
}
}
func TestPagingWalksTheWholeQueueInOrder(t *testing.T) {
rows := rowsAcrossEveryOrderingField()
Rank(rows, ByWorst)
walked := []api.Issue{}
cursor := ""
for range rows {
page, next := Page(rows, cursorKey(t, cursor, ByWorst), 7, ByWorst)
walked = append(walked, page...)
if next == "" {
break
}
cursor = next
}
if len(walked) != len(rows) {
t.Fatalf("walked %d rows, queue holds %d", len(walked), len(rows))
}
for at := range rows {
if walked[at].ID != rows[at].ID {
t.Fatalf("row %d is %q, ranked order has %q", at, walked[at].ID, rows[at].ID)
}
}
}
func TestEveryPageButTheLastIsFull(t *testing.T) {
rows := rowsAcrossEveryOrderingField()
Rank(rows, ByWorst)
cursor := ""
pages := 0
for {
page, next := Page(rows, cursorKey(t, cursor, ByWorst), 7, ByWorst)
pages++
if next == "" {
if len(page) > 7 {
t.Fatalf("last page carries %d rows, the limit is 7", len(page))
}
break
}
if len(page) != 7 {
t.Fatalf("page %d carries %d rows, the limit is 7", pages, len(page))
}
cursor = next
}
if pages != (len(rows)+6)/7 {
t.Fatalf("walked %d pages, %d rows at 7 a page needs %d", pages, len(rows), (len(rows)+6)/7)
}
}
func TestAPageBigEnoughForTheQueueEndsIt(t *testing.T) {
rows := rowsAcrossEveryOrderingField()
Rank(rows, ByWorst)
page, next := Page(rows, "", len(rows)+1, ByWorst)
if len(page) != len(rows) {
t.Fatalf("page carries %d of %d rows", len(page), len(rows))
}
if next != "" {
t.Fatalf("a page holding the whole queue still offers %q", next)
}
}
func TestAnEmptyQueuePagesToNothing(t *testing.T) {
page, next := Page(nil, "", Shown, ByWorst)
if len(page) != 0 {
t.Fatalf("an empty queue paged to %d rows", len(page))
}
if next != "" {
t.Fatalf("an empty queue offers %q", next)
}
}
func TestAnInvalidPageLimitStillMakesProgress(t *testing.T) {
rows := rowsAcrossEveryOrderingField()
Rank(rows, ByWorst)
for _, limit := range []int{0, -1, -100} {
page, next := Page(rows, "", limit, ByWorst)
if len(page) == 0 {
t.Fatalf("limit %d returned an empty page for a non-empty queue", limit)
}
if len(page) > Shown {
t.Fatalf("limit %d returned %d rows, want at most %d", limit, len(page), Shown)
}
if len(rows) > Shown && next == "" {
t.Fatalf("limit %d lost the continuation", limit)
}
}
}
func TestARowClearingBeforeTheNextPageDoesNotSkipItsNeighbour(t *testing.T) {
rows := rowsAcrossEveryOrderingField()
Rank(rows, ByWorst)
first, next := Page(rows, "", 7, ByWorst)
if next == "" {
t.Fatal("the fixture is too small to have a second page")
}
shorter := slices.Delete(slices.Clone(rows), 0, 1)
second, _ := Page(shorter, cursorKey(t, next, ByWorst), 7, ByWorst)
if len(second) == 0 {
t.Fatal("the second page came back empty")
}
if second[0].ID != rows[len(first)].ID {
t.Fatalf(
"the row after the boundary is %q, a row clearing above it made it %q",
rows[len(first)].ID, second[0].ID,
)
}
}
func TestGarbageInTheCursorIsRefused(t *testing.T) {
_, err := DecodeCursor("not base64 at all!!", ByWorst)
if !errors.Is(err, ErrInvalidCursor) {
t.Fatalf("error = %v, want invalid cursor", err)
}
}
func TestIncompleteCursorsAreRefused(t *testing.T) {
for _, raw := range []string{ByWorst, "\x00key", ByWorst + "\x00"} {
cursor := base64.RawURLEncoding.EncodeToString([]byte(raw))
_, err := DecodeCursor(cursor, ByWorst)
if !errors.Is(err, ErrInvalidCursor) {
t.Fatalf("cursor for %q returned %v, want invalid cursor", raw, err)
}
}
}
func cursorKey(t *testing.T, cursor, order string) string {
t.Helper()
key, err := DecodeCursor(cursor, order)
if err != nil {
t.Fatalf("decode cursor: %v", err)
}
return key
}
func TestAnEmptyCursorEncodesToNothing(t *testing.T) {
if EncodeCursor("", ByWorst) != "" {
t.Fatalf("an empty key encoded to %q", EncodeCursor("", ByWorst))
}
if cursorKey(t, "", ByWorst) != "" {
t.Fatal("an empty cursor decoded to something")
}
}
func TestACursorFromAnotherOrderIsRefused(t *testing.T) {
rows := rowsAcrossEveryOrderingField()
Rank(rows, ByWorst)
_, next := Page(rows, "", 3, ByWorst)
if next == "" {
t.Fatal("the fixture produced no second page")
}
_, err := DecodeCursor(next, ByNewest)
if !errors.Is(err, ErrCursorOrder) {
t.Fatalf("error = %v, want cursor order mismatch", err)
}
}
func TestPageSizeFallsBackToWhatOnePageShows(t *testing.T) {
if PageSize(0) != Shown {
t.Fatalf("an unset size gave %d, one page shows %d", PageSize(0), Shown)
}
if PageSize(-4) != Shown {
t.Fatalf("a negative size gave %d, one page shows %d", PageSize(-4), Shown)
}
if PageSize(9) != 9 {
t.Fatalf("a size of 9 gave %d", PageSize(9))
}
}
func TestCountDownStaysInsideItsWidth(t *testing.T) {
cases := []struct {
value int
want string
}{
{value: 0, want: "999"},
{value: 1, want: "998"},
{value: 999, want: "000"},
{value: -7, want: "999"},
{value: 4000, want: "000"},
}
for _, one := range cases {
got := countDown(one.value, 999)
if got != one.want {
t.Fatalf("countDown(%d, 999) = %q, want %q", one.value, got, one.want)
}
}
}
func TestCountUpStaysInsideItsWidth(t *testing.T) {
cases := []struct {
value int
want string
}{
{value: 0, want: "000"},
{value: 1, want: "001"},
{value: 999, want: "999"},
{value: -7, want: "000"},
{value: 4000, want: "999"},
}
for _, one := range cases {
got := countUp(one.value, 999)
if got != one.want {
t.Fatalf("countUp(%d, 999) = %q, want %q", one.value, got, one.want)
}
}
}
func TestATimeNobodyStampedCountsAsTheOldest(t *testing.T) {
if secondsOf(time.Time{}) != 0 {
t.Fatalf("an unstamped time counted as %d seconds", secondsOf(time.Time{}))
}
stamped := time.Unix(1700000000, 0)
if secondsOf(stamped) != 1700000000 {
t.Fatalf("a stamped time counted as %d seconds", secondsOf(stamped))
}
}
func TestAFoldCountPastTheCeilingStillOutranksASmallOne(t *testing.T) {
huge := api.Issue{ID: "huge", Severity: api.SeverityLow, Folded: foldCeiling + 10}
modest := api.Issue{ID: "modest", Severity: api.SeverityLow, Folded: 1}
if issueKey(huge, ByWorst) >= issueKey(modest, ByWorst) {
t.Fatalf("a fold count past the ceiling wrapped and sorted below a fold of 1")
}
}
func TestNewestFirstOrdersByWhenNotBySeverity(t *testing.T) {
rows := []api.Issue{
{ID: "old-fatal", Severity: api.SeverityHigh, Since: "2026-08-01T00:00:00Z"},
{ID: "new-warning", Severity: api.SeverityLow, Since: "2026-08-29T00:00:00Z"},
}
Rank(rows, ByNewest)
if rows[0].ID != "new-warning" {
t.Fatalf("newest first put %q on top", rows[0].ID)
}
}
func TestOldestFirstIsTheOtherWayRound(t *testing.T) {
rows := []api.Issue{
{ID: "new-warning", Severity: api.SeverityLow, Since: "2026-08-29T00:00:00Z"},
{ID: "old-fatal", Severity: api.SeverityHigh, Since: "2026-08-01T00:00:00Z"},
}
Rank(rows, ByOldest)
if rows[0].ID != "old-fatal" {
t.Fatalf("oldest first put %q on top", rows[0].ID)
}
}
func TestEveryOrderWalksItsWholeQueueWithoutRepeating(t *testing.T) {
for _, order := range []string{ByWorst, ByNewest, ByOldest} {
t.Run(order, func(t *testing.T) {
rows := rowsAcrossEveryOrderingField()
Rank(rows, order)
for at := 1; at < len(rows); at++ {
if issueKey(rows[at-1], order) >= issueKey(rows[at], order) {
t.Fatalf("row %d sorts before row %d but its key does not", at-1, at)
}
}
seen := map[string]bool{}
cursor := ""
for range rows {
page, next := Page(rows, cursorKey(t, cursor, order), 7, order)
for _, row := range page {
if seen[row.ID] {
t.Fatalf("%s came back twice", row.ID)
}
seen[row.ID] = true
}
if next == "" {
break
}
cursor = next
}
if len(seen) != len(rows) {
t.Fatalf("walked %d of %d rows", len(seen), len(rows))
}
})
}
}
func TestAnUnknownOrderFallsBackToWorstFirst(t *testing.T) {
for _, asked := range []string{"", "sideways", "WORST"} {
if OrderOf(asked) != ByWorst {
t.Fatalf("%q read as %q", asked, OrderOf(asked))
}
}
if OrderOf(ByNewest) != ByNewest || OrderOf(ByOldest) != ByOldest {
t.Fatal("a date order was not taken")
}
}