internal/control/cursor_test.go
96 lines · 2763 bytes
4 symbols in this file
1package control
2
3import (
4 "bytes"
5 "strings"
6 "testing"
7
8 "gitbay.org/gitbay/internal/protocol"
9 "gitbay.org/gitbay/internal/store"
10)
11
12func TestShellWord(t *testing.T) {
13 tests := []struct {
14 input string
15 want string
16 }{
17 {"plain", "plain"},
18 {"foo-bar", "foo-bar"},
19 {"123", "123"},
20 {"foo bar", "'foo bar'"},
21 {"it's", "'it'\\''s'"},
22 {"a'b'c", "'a'\\''b'\\''c'"},
23 {"", "''"},
24 }
25 for _, tt := range tests {
26 if got := shellWord(tt.input); got != tt.want {
27 t.Errorf("shellWord(%q) = %q, want %q", tt.input, got, tt.want)
28 }
29 }
30}
31
32func TestCursorRoundTrip(t *testing.T) {
33 cur := encodeCursor("issue", "42")
34 key, err := decodeCursor("issue", cur)
35 if err != nil || key != "42" {
36 t.Fatalf("decode = %q, %v", key, err)
37 }
38 if _, err := decodeCursor("mr", cur); err == nil {
39 t.Fatal("cursor accepted under the wrong kind")
40 }
41 if _, err := decodeCursor("issue", "not base64!"); err == nil {
42 t.Fatal("garbage cursor accepted")
43 }
44 if _, err := decodeCursor("issue", encodeCursor("issue", "")); err == nil {
45 t.Fatal("empty key accepted")
46 }
47}
48
49func TestTrimPage(t *testing.T) {
50 key := func(n int) string { return "k" }
51 // No probe row: page as-is, no next.
52 items, next := trimPage(page{limit: 3}, []int{1, 2, 3}, "issue", key)
53 if len(items) != 3 || next != "" {
54 t.Fatalf("full page: %v next=%q", items, next)
55 }
56 // Probe row present: trimmed, next minted.
57 items, next = trimPage(page{limit: 2}, []int{1, 2, 3}, "issue", key)
58 if len(items) != 2 || next == "" {
59 t.Fatalf("trimmed page: %v next=%q", items, next)
60 }
61 // Unpaged: untouched.
62 items, next = trimPage(page{}, []int{1, 2, 3}, "issue", key)
63 if len(items) != 3 || next != "" {
64 t.Fatalf("unpaged: %v next=%q", items, next)
65 }
66}
67
68func TestEmitPageHintsTheNextPageAtATerminal(t *testing.T) {
69 st, repo, uid := newQueueTestRepo(t)
70 for i := 0; i < 3; i++ {
71 if _, err := st.CreateBuild(repo.ID, "unit", "aaa", "main", `["true"]`, "", "", true); err != nil {
72 t.Fatal(err)
73 }
74 }
75 c, errOut := pruneCtx(st, t.TempDir(), store.User{ID: uid})
76 c.Term = Term{Cols: 100}
77 if code := Dispatch(c, []string{"build", "list", repo.Path(), "--limit", "2"}); code != protocol.ExitOK {
78 t.Fatalf("exit %d: %s", code, errOut)
79 }
80 if strings.Contains(c.Stdout.(*bytes.Buffer).String(), "next\t") {
81 t.Errorf("cursor row on stdout at a terminal")
82 }
83 stderr := errOut.String()
84 cmd, ok := strings.CutPrefix(stderr, "Next page ")
85 if !ok {
86 t.Fatalf("stderr = %q, want a Next page line", stderr)
87 }
88 want := "gitbay build list " + repo.Path() + " --limit 2 --cursor "
89 if !strings.HasPrefix(cmd, want) {
90 t.Errorf("command = %q, want %q…", cmd, want)
91 }
92 // No empty word in the command.
93 if strings.Contains(cmd, " ") {
94 t.Errorf("command contains double space: %q", cmd)
95 }
96}