v0.3.0 99dc266

remote_parity_test.go RawHistoryFolder

1package picker
2
3import (
4	"testing"
5
6	"github.com/stretchr/testify/require"
7
8	renderer "github.com/bnema/vev-vt"
9	"github.com/bnema/vev/internal/domain"
10)
11
12func remoteParityLifecycle(seed byte) domain.SessionLifecycleID {
13	var id domain.SessionLifecycleID
14	id[0] = seed
15	return id
16}
17
18func TestRemoteSessionHeaderIncludesOrigin(t *testing.T) {
19	lifecycle := remoteParityLifecycle(1)
20	key := domain.RemoteSessionKey{Host: "vev@arch", Name: "work", LifecycleID: lifecycle, DisplayOrigin: "arch"}
21	target := domain.RemoteSessionTarget{Endpoint: key.Host, DisplayOrigin: key.DisplayOrigin, LifecycleID: lifecycle, SessionName: key.Name, LiveTabID: "tab-1"}
22	model := New([]SessionView{{
23		ID: key.ID(), Name: key.Name, Tabs: []TabEntry{{TabID: "tab-1", Name: "main"}},
24		RemoteKey: &key, RemoteTarget: &target, RemoteAvailability: RemoteFresh, RemoteActivation: RemoteAttach,
25	}}, SelectionConfig{Mode: SelectNavigationTab})
26
27	require.Equal(t, "work", model.rows[0].dispName)
28	require.Equal(t, "@arch", model.rows[0].detail)
29	frame := model.Render(domain.Size{Cols: 32, Rows: 4}, Preview{}, RenderStyles{
30		Name: renderer.Style{Bold: true}, Detail: renderer.Style{Attrs: renderer.AttrDim},
31	})
32	require.Equal(t, '@', frame.At(4, 0).Rune)
33	require.True(t, frame.At(4, 0).Style.Equal(renderer.Style{Attrs: renderer.AttrDim}))
34	selected, ok := model.Selected()
35	require.True(t, ok)
36	require.Equal(t, key.ID(), selected.Session)
37	require.Equal(t, &target, selected.RemoteTarget)
38}
39
40func TestRemoteRowsWithDuplicateLabelsKeepDistinctRoutingIdentity(t *testing.T) {
41	firstLifecycle := remoteParityLifecycle(1)
42	secondLifecycle := remoteParityLifecycle(2)
43	firstKey := domain.RemoteSessionKey{Host: "arch", Name: "work", LifecycleID: firstLifecycle, DisplayOrigin: "same-origin"}
44	secondKey := domain.RemoteSessionKey{Host: "mule", Name: "work", LifecycleID: secondLifecycle, DisplayOrigin: "same-origin"}
45	firstTarget := domain.RemoteSessionTarget{Endpoint: "arch", DisplayOrigin: "same-origin", LifecycleID: firstLifecycle, SessionName: "work", LiveTabID: "tab-a"}
46	secondTarget := domain.RemoteSessionTarget{Endpoint: "mule", DisplayOrigin: "same-origin", LifecycleID: secondLifecycle, SessionName: "work", LiveTabID: "tab-b"}
47	model := New([]SessionView{
48		{
49			ID: firstKey.ID(), Name: "same visible label", Tabs: []TabEntry{{TabID: "tab-a", Name: "main"}},
50			RemoteKey: &firstKey, RemoteTarget: &firstTarget, RemoteAvailability: RemoteFresh, RemoteActivation: RemoteAttach,
51		},
52		{
53			ID: secondKey.ID(), Name: "same visible label", Tabs: []TabEntry{{TabID: "tab-b", Name: "main"}},
54			RemoteKey: &secondKey, RemoteTarget: &secondTarget, RemoteAvailability: RemoteFresh, RemoteActivation: RemoteAttach,
55		},
56	}, SelectionConfig{Mode: SelectNavigationTab})
57
58	expected := []struct {
59		name      string
60		session   domain.SessionID
61		endpoint  string
62		lifecycle domain.SessionLifecycleID
63		tabID     domain.TabStableID
64	}{
65		{name: "first", session: firstKey.ID(), endpoint: "arch", lifecycle: firstLifecycle, tabID: "tab-a"},
66		{name: "second", session: secondKey.ID(), endpoint: "mule", lifecycle: secondLifecycle, tabID: "tab-b"},
67	}
68	for i, want := range expected {
69		t.Run(want.name, func(t *testing.T) {
70			selected, ok := model.Selected()
71			require.True(t, ok)
72			require.Equal(t, want.session, selected.Session)
73			require.NotNil(t, selected.RemoteTarget)
74			require.Equal(t, want.endpoint, selected.RemoteTarget.Endpoint)
75			require.Equal(t, want.lifecycle, selected.RemoteTarget.LifecycleID)
76			require.Equal(t, want.tabID, selected.RemoteTarget.LiveTabID)
77		})
78		if i+1 < len(expected) {
79			model.Down()
80		}
81	}
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 12

Tags 11

↑↓ moveenter openesc close