Skip to content
quarry Artifact [889e06c03b]
Login

Artifact [889e06c03b]

Artifact 889e06c03b81d2268c113136f5e918b541d4d82a8097e3e67732631b9035248e:


package api

import (
	"strings"
	"testing"
)

// The page cursor addresses BOTH sources. A cursor that carried only
// notify's position is the bug this replaces: rows the limit truncated
// off the end of page one were never served on page two, because the
// notify cursor had already moved past them.
func TestInboxCursorRoundTrips(t *testing.T) {
	for _, c := range []inboxCursor{
		{},
		{Notify: "n-abc", Skip: 3, Local: 42, LocalSet: true},
		{NotifyDone: true, LocalDone: true},
		// A notify cursor is opaque and may hold the separators the
		// encoding uses; it must survive them.
		{Notify: "a|b:c=d e", Skip: 1},
	} {
		got := decodeInboxCursor(c.encode())
		if got != c {
			t.Fatalf("round trip: %+v -> %q -> %+v", c, c.encode(), got)
		}
	}
	// The empty cursor is the empty string: a first page carries no
	// `before`, and it must not encode to a token that looks like one.
	if s := (inboxCursor{}).encode(); s != "" {
		t.Fatalf("empty cursor = %q", s)
	}
	// Garbage is a first page, not an error: a stale bookmark should
	// show somebody their inbox, not a failure.
	if got := decodeInboxCursor("not-base64!!"); got != (inboxCursor{}) {
		t.Fatalf("garbage cursor = %+v", got)
	}
	// And the token is opaque — no readable sequence numbers in a URL.
	if strings.Contains((inboxCursor{Local: 42, LocalSet: true}).encode(), "42") {
		t.Fatal("the cursor must be opaque")
	}
}

// An absent switch means "unchanged", never "off". The destructive
// reading — a form that posts `toasts` and not `notify_desktop` turning
// desktop notifications off — is what this replaces.
func TestSwitchValueDistinguishesAbsentFromOff(t *testing.T) {
	for in, want := range map[string]string{
		"": "", "on": "on", "ON": "on", "true": "on", "1": "on",
		"off": "off", "false": "off", "0": "off", "no": "off",
	} {
		if got := switchValue(in); got != want {
			t.Errorf("switchValue(%q) = %q, want %q", in, got, want)
		}
	}
}

// The muted set is stored as a JSON array, so a repository name is a
// whole element rather than whatever survives a split on spaces. The
// old space-separated spelling is still read, because an existing forge
// has rows in it.
func TestMuteListEncodingRoundTripsAndReadsTheOldSpelling(t *testing.T) {
	got := decodeMuteList(encodeMuteList([]string{"beta", "alpha"}))
	if len(got) != 2 || got[0] != "alpha" || got[1] != "beta" {
		t.Fatalf("round trip = %+v (sorted)", got)
	}
	if got := decodeMuteList(""); len(got) != 0 {
		t.Fatalf("empty = %+v", got)
	}
	if got := decodeMuteList("alpha beta"); len(got) != 2 || got[0] != "alpha" {
		t.Fatalf("legacy space-separated = %+v", got)
	}
}