v0.4.0 0b9cfda

query_test.go RawHistoryFolder

1package terminalquery
2
3import (
4	"testing"
5
6	"github.com/stretchr/testify/require"
7)
8
9func TestProbeRequiresKittyAndDA1(t *testing.T) {
10	for _, tc := range []struct {
11		name      string
12		data      string
13		kitty     bool
14		da1       bool
15		unrelated string
16	}{
17		{name: "both and input", data: "x\x1b[?1;2c" + "\x1b_Gi=31;OK\x1b\\y", kitty: true, da1: true, unrelated: "xy"},
18		{name: "secondary DA is insufficient", data: "\x1b[>1;2c\x1b_Gi=31;OK\x1b\\", kitty: true, unrelated: "\x1b[>1;2c"},
19		{name: "ordinary input", data: "hello", unrelated: "hello"},
20	} {
21		t.Run(tc.name, func(t *testing.T) {
22			var p Probe
23			got := append(p.Feed([]byte(tc.data)), p.Finish()...)
24			require.Equal(t, tc.kitty, p.KittyGraphics())
25			require.Equal(t, tc.da1, p.DA1())
26			require.Equal(t, tc.unrelated, string(got))
27		})
28	}
29}
30
31func TestProbeRecognizesFragmentedResponsesAndReplaysInput(t *testing.T) {
32	var p Probe
33	var unrelated []byte
34	for _, fragment := range []string{"a\x1b", "[?1;2", "c", "b\x1b_Gi=31;", "OK\x1b", "\\z"} {
35		unrelated = append(unrelated, p.Feed([]byte(fragment))...)
36	}
37	unrelated = append(unrelated, p.Finish()...)
38	require.True(t, p.Ready())
39	require.Equal(t, "abz", string(unrelated))
40}
41
42func TestProbeRequiresExactCapabilityResponses(t *testing.T) {
43	for _, data := range []string{
44		"\x1b_Gi=31;OK,extra\x1b\\",
45		"\x1b_Gi=310;OK\x1b\\",
46		"\x1b_Gi=31;OKAY\x1b\\",
47		"\x1b[?1;;2c",
48		"\x1b[?x;2c",
49	} {
50		var p Probe
51		got := append(p.Feed([]byte(data)), p.Finish()...)
52		require.False(t, p.Ready(), "response %q was accepted", data)
53		require.Equal(t, data, string(got))
54	}
55}
56
57func FuzzProbeNeverPanics(f *testing.F) {
58	f.Add([]byte("text\x1b[?1;2c\x1b_Gi=31;OK\x1b\\"))
59	f.Add([]byte("\x1b_G"))
60	f.Fuzz(func(t *testing.T, data []byte) {
61		var p Probe
62		_ = p.Feed(data)
63		_ = p.Finish()
64	})
65}
66
67func TestProbeDoesNotRetainLargeInputFragments(t *testing.T) {
68	var p Probe
69	input := append(make([]byte, 1<<20), []byte("\x1b_G")...)
70	got := append(p.Feed(input), p.Finish()...)
71	require.Equal(t, input, got)
72	require.LessOrEqual(t, cap(p.pending), maxProbeResponseBytes+2)
73}
74
75func TestProbeBoundsUnterminatedResponse(t *testing.T) {
76	var p Probe
77	input := append([]byte("prefix"), []byte("\x1b_G")...)
78	input = append(input, make([]byte, maxProbeResponseBytes+1)...)
79	got := append(p.Feed(input), p.Finish()...)
80	require.False(t, p.Ready())
81	require.Equal(t, input, got)
82}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 13

↑↓ moveenter openesc close