v0.5.0 c37833b

ui_test.go RawHistoryFolder

1package sessionwire
2
3import (
4	"testing"
5
6	"github.com/bnema/vev/internal/domain"
7	"github.com/bnema/vev/internal/protocol"
8	"github.com/bnema/vev/internal/protocol/wire"
9	"github.com/stretchr/testify/require"
10)
11
12func TestUISynchronizationClientDispatch(t *testing.T) {
13	for _, message := range []protocol.ClientMessage{
14		protocol.Input{InputSeq: 3, ActionID: 7, Data: []byte("x")},
15		protocol.UIFence{ActionID: 7},
16	} {
17		clientRaw := &scriptedTransport{recv: []wire.Envelope{mustPreambleResponse(t)}}
18		require.NoError(t, NewClientConnection(clientRaw).SendClient(message))
19		sent := mustSingleAppPayload(t, clientRaw)
20		serverRaw := &scriptedTransport{recv: mustServerPreambleQueue(t, sent)}
21		got, err := NewServerConnection(serverRaw).ReceiveClient()
22		require.NoError(t, err)
23		require.Equal(t, message, got)
24		headerLen := len(sent)
25		if input, ok := message.(protocol.Input); ok {
26			// Input carries opaque bytes after the envelope header; only
27			// the envelope framing has strict prefix truncation semantics.
28			headerLen -= len(input.Data)
29		}
30		for size := range headerLen {
31			raw := &scriptedTransport{recv: mustServerPreambleQueue(t, sent[:size])}
32			_, err := NewServerConnection(raw).ReceiveClient()
33			require.Error(t, err, "prefix %d", size)
34		}
35	}
36}
37
38func testUIOutputContext() *protocol.ViewContext {
39	return &protocol.ViewContext{Publication: 4,
40		Route: protocol.CommittedRouteIdentity{Target: protocol.ExactSessionTarget{LifecycleID: domain.SessionLifecycleID{1}, SessionName: "work"}},
41		TabID: "tab-1", FocusedPaneID: "pane-1"}
42}
43
44func TestUISynchronizationServerDispatch(t *testing.T) {
45	context := *testUIOutputContext()
46	for _, test := range []struct {
47		name    string
48		message protocol.ServerMessage
49	}{
50		{"output", protocol.Output{Epoch: 2, New: 1, Full: true, Size: domain.Size{Cols: 80, Rows: 24}, Context: &context}},
51		{"receipt", protocol.UIReceipt{ActionID: 7, Epoch: 2, State: 1, ViewPublication: 4, Outcome: protocol.UIReceiptProcessed}},
52		{"view update", protocol.UIViewUpdate{Epoch: 2, State: 1, Context: context}},
53		{"attach target", protocol.AttachTarget{CauseActionID: 7, Session: "work", Intent: protocol.IntentAttach}},
54		{"route action", protocol.RouteNavigationAction{CauseActionID: 7, SnapshotGeneration: 1, Key: 2, Generation: 3}},
55		{"route create", protocol.RouteCreateSessionAction{CauseActionID: 7, RequestID: 4, SnapshotGeneration: 1, Key: 2, Generation: 3, SessionName: "work"}},
56	} {
57		t.Run(test.name, func(t *testing.T) {
58			for _, async := range []bool{false, true} {
59				serverRaw := &capableTransport{}
60				server := NewServerConnection(serverRaw)
61				var sent []byte
62				if async {
63					require.NoError(t, server.SendServerAsync(test.message))
64					require.Equal(t, 1, len(serverRaw.async))
65					sent = serverRaw.async[0].Payload
66				} else {
67					require.NoError(t, server.SendServer(test.message))
68					require.Equal(t, 1, serverRaw.sentLen())
69					sent = serverRaw.sentPayload(0)
70				}
71				clientRaw := &scriptedTransport{recv: mustClientPreambleQueue(t, sent)}
72				got, err := NewClientConnection(clientRaw).ReceiveServer()
73				require.NoError(t, err)
74				require.Equal(t, test.message, got)
75				for size := range len(sent) {
76					raw := &scriptedTransport{recv: mustClientPreambleQueue(t, sent[:size])}
77					_, err := NewClientConnection(raw).ReceiveServer()
78					require.Error(t, err, "prefix %d", size)
79				}
80				raw := &scriptedTransport{recv: mustClientPreambleQueue(t, append(append([]byte(nil), sent...), 0))}
81				_, err = NewClientConnection(raw).ReceiveServer()
82				require.Error(t, err)
83			}
84		})
85	}
86}

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 12

Tags 11

↑↓ moveenter openesc close