internal/control/control_test.go

4744c629ed4f0158bdea7d0f1d207fdccb1f7f99
gitbay/internal/control/control_test.go history · blame · raw

71 lines · 2179 bytes

 1package control
 2
 3import (
 4	"strings"
 5	"testing"
 6
 7	"gitbay.org/gitbay/internal/protocol"
 8)
 9
10// TestEveryCommandReachableFromBareSSH asserts that each registered command's
11// path, rendered exactly as a user would type it after `ssh <host>`, resolves
12// back to that command through the tokenizer and Lookup. This is the guard
13// that keeps the forge CLI optional.
14func TestEveryCommandReachableFromBareSSH(t *testing.T) {
15	cmds := Commands()
16	if len(cmds) == 0 {
17		t.Fatal("no commands registered")
18	}
19	for _, cmd := range cmds {
20		line := strings.Join(cmd.Path, " ")
21		argv, err := protocol.Tokenize(line)
22		if err != nil {
23			t.Errorf("command %q not tokenizable: %v", line, err)
24			continue
25		}
26		got, rest, ok := Lookup(argv)
27		if !ok {
28			t.Errorf("command %q not found by Lookup", line)
29			continue
30		}
31		if strings.Join(got.Path, " ") != line || len(rest) != 0 {
32			t.Errorf("Lookup(%q) resolved to %q with rest %v", line, strings.Join(got.Path, " "), rest)
33		}
34		if cmd.Run == nil {
35			t.Errorf("command %q has no Run", line)
36		}
37		if cmd.Summary == "" {
38			t.Errorf("command %q has no summary", line)
39		}
40	}
41}
42
43func TestLookupLongestMatch(t *testing.T) {
44	// "keys list" must not resolve to a hypothetical shorter prefix and
45	// unknown commands must not match.
46	if _, _, ok := Lookup([]string{"keys"}); ok {
47		t.Error("bare \"keys\" resolved; group prefixes must not be runnable")
48	}
49	if _, _, ok := Lookup([]string{"nope"}); ok {
50		t.Error("unknown command resolved")
51	}
52	cmd, rest, ok := Lookup([]string{"keys", "list", "--json"})
53	if !ok || strings.Join(cmd.Path, " ") != "keys list" || len(rest) != 1 {
54		t.Errorf("Lookup keys list --json = %v %v %v", cmd.Path, rest, ok)
55	}
56}
57
58// TestBuildJobsIsAReadCommand pins the properties the surfaces depend on:
59// the web build page and a read-scoped API token both need it over GET.
60func TestBuildJobsIsAReadCommand(t *testing.T) {
61	cmd, _, ok := Lookup([]string{"build", "jobs"})
62	if !ok {
63		t.Fatal("build jobs not registered")
64	}
65	if !cmd.ReadOnly {
66		t.Error("build jobs must be ReadOnly; listing jobs changes nothing")
67	}
68	if cmd.SSHOnly {
69		t.Error("build jobs must not be SSHOnly; the web and the app need it")
70	}
71}