session_view_test.go RawHistoryFolder

1package daemon
2
3import (
4	"reflect"
5	"testing"
6
7	"github.com/bnema/vev/internal/domain"
8)
9
10func TestSnapshotViewCapturesSessionFields(t *testing.T) {
11	tests := []struct {
12		name  string
13		build func() *session
14		opts  viewOptions
15		want  sessionView
16	}{
17		{
18			name: "named session with attention tab",
19			build: func() *session {
20				s := &session{sessionCore: sessionCore{id: domain.SessionID("s1"),
21					incarnation: domain.IncarnationID{1},
22					name:        "alpha",
23					createdAt:   42,
24
25					attachments: map[*attachedClient]struct{}{&attachedClient{}: {}}},
26
27					tabs: []*tab{
28						{stableID: "t1", name: "build"},
29						{stableID: "t2", name: "logs", attention: true},
30					},
31				}
32				s.mruAt.Store(7)
33				return s
34			},
35			opts: viewOptions{tabDetails: true},
36			want: sessionView{
37				id:           domain.SessionID("s1"),
38				incarnation:  domain.IncarnationID{1},
39				name:         "alpha",
40				createdAt:    42,
41				mruAt:        7,
42				attached:     true,
43				tabCount:     2,
44				hasAttention: true,
45				tabs: []tabView{
46					{id: domain.TabStableID("t1"), name: "build"},
47					{id: domain.TabStableID("t2"), name: "logs", attention: true},
48				},
49			},
50		},
51		{
52			name: "ephemeral detached session without tabs",
53			build: func() *session {
54				return &session{sessionCore: sessionCore{id: domain.SessionID("s2"), name: "9", ephemeral: true}}
55			},
56			opts: viewOptions{},
57			want: sessionView{
58				id:        domain.SessionID("s2"),
59				name:      "9",
60				ephemeral: true,
61				tabCount:  0,
62			},
63		},
64	}
65	for _, tt := range tests {
66		t.Run(tt.name, func(t *testing.T) {
67			got := tt.build().snapshotView(tt.opts)
68			if !reflect.DeepEqual(got, tt.want) {
69				t.Fatalf("snapshotView() = %+v, want %+v", got, tt.want)
70			}
71		})
72	}
73}
74
75func TestSnapshotViewFocusedTitlesOption(t *testing.T) {
76	s := &session{sessionCore: sessionCore{id: domain.SessionID("s1"),
77		name: "alpha"}, tabs: []*tab{{stableID: "t1", name: "build"}},
78	}
79	off := s.snapshotView(viewOptions{tabDetails: true})
80	if off.tabs[0].focusedTitle != "" {
81		t.Fatalf("focusedTitle without focusedTitles option = %q, want empty", off.tabs[0].focusedTitle)
82	}
83	// A pane-less tab has no focused pane: the option must be exercised
84	// without panicking and still yield an empty title.
85	on := s.snapshotView(viewOptions{tabDetails: true, focusedTitles: true, terminalTitle: true})
86	if on.tabs[0].focusedTitle != "" {
87		t.Fatalf("focusedTitle for pane-less tab = %q, want empty", on.tabs[0].focusedTitle)
88	}
89}
90
91func TestSnapshotViewAggregatesWithoutTabDetails(t *testing.T) {
92	s := &session{tabs: []*tab{
93		{stableID: "t1", name: "build"},
94		{stableID: "t2", name: "logs", attention: true},
95	}}
96	got := s.snapshotView(viewOptions{})
97	if got.tabCount != 2 || !got.hasAttention {
98		t.Fatalf("aggregates = (tabCount %d, hasAttention %t), want (2, true)", got.tabCount, got.hasAttention)
99	}
100	if got.tabs != nil {
101		t.Fatalf("tabs without tabDetails = %#v, want nil", got.tabs)
102	}
103
104	empty := (&session{}).snapshotView(viewOptions{tabDetails: true})
105	if empty.tabCount != 0 || empty.tabs == nil || len(empty.tabs) != 0 {
106		t.Fatalf("empty detailed snapshot = (tabCount %d, tabs %#v), want (0, non-nil empty)", empty.tabCount, empty.tabs)
107	}
108}

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